Skip to content

Instantly share code, notes, and snippets.

@msrose
Last active November 5, 2024 10:15
Show Gist options
  • Save msrose/2feacb303035d11d2d05 to your computer and use it in GitHub Desktop.
Save msrose/2feacb303035d11d2d05 to your computer and use it in GitHub Desktop.
How to combine two git repositories.

Combining two git repositories

Use case: You have repository A with remote location rA, and repository B (which may or may not have remote location rB). You want to do one of two things:

  • preserve all commits of both repositories, but replace everything from A with the contents of B, and use rA as your remote location
  • actually combine the two repositories, as if they are two branches that you want to merge, using rA as the remote location

NB: Check out git subtree/git submodule and this Stack Overflow question before going through the steps below. This gist is just a record of how I solved this problem on my own one day.

Before starting, make sure your local and remote repositories are up-to-date with all changes you need. The following steps use the general idea of changing the remote origin and renaming the local master branch of one of the repos in order to combine the two master branches.

Change the remote origin of B to that of A:

$ cd path/to/B
$ git remote rm origin
$ git remote add origin url_to_rA

Rename the local master branch of B:

$ git checkout master
$ git branch -m master-holder

Pull all the code of A from rA into your local B repo.

$ git fetch
$ git checkout master
$ git pull origin master

Now the master branch of A is master in B. The old master of B is master-holder.

Delete all the things! (i.e, scrap everything from A.) If you actually want to merge both repos, this step is unnecessary.

$ git rm -rf *
$ git commit -m "Delete all the things."

Merge master-holder into master. (If you didn't do the delete step above, you have to option of git checkout master-holder; git rebase master instead.) For more recent versions of git, you'll probably have to add the --allow-unrelated-histories flag (thanks to @sadzik).

git merge master-holder --allow-unrelated-histories

git log should show all the commits from A, the delete commit, the merge commit, and finally all the commits from B.

Push everything to rA

git push origin master

Now your local copy of B has become a "unified" repository, which includes all the commits from A and B. rA is used as the remote repo. You no longer need your local copy of A or the remote repo rB (although keeping rB around for a bit longer isn't a bad idea).

@Ayushi-Rohela
Copy link

@msrose I want to merge one particular branch say B1 from repository R1 to a branch B2 of repository R2, any ideas on this?

@sayashraaj
Copy link

Hi, will this remove contributions from deleted repo?

@BenjaminTJohnson
Copy link

I like this approach, but it doesn't work with bare repositories, failing at the merge portion.

@Brian-Pho
Copy link

This is exactly what I needed and it worked perfectly. Thanks.

@edazpotato
Copy link

Bro, you actually saved my life. Thank you so, so much!

@sheldonhull
Copy link

Super helpful. Much appreciated!

@zyilmaz
Copy link

zyilmaz commented Jul 10, 2020

It is really helpful. Thank you so much!

@lesovsky
Copy link

lesovsky commented Aug 9, 2020

When i do git rm -rf * I get fatal: pathspec 'internal' did not match any files.

Solved with removing all stuff using "rm -rf ..." and then removing from git using "git rm -rf *".

@IamPhytan
Copy link

@untmdsprt If ever you want to add more complexity, submodules are the way to go

@sheldonhull
Copy link

You are brave :-) I really really don't like dealing with submodules.
I haven't tried subtrees yet but read about them recently and seem interesting to try out.

@MrLixm
Copy link

MrLixm commented Oct 20, 2021

Hey, first thanks a lot, perfect explanations.

Then I got the same error as levosky:
when doing git rm -rf * I get fatal: pathspec 'somefilename' did not match any files.

I was using PyCharm when doing this and this thread redirect me to the good workflow: https://stackoverflow.com/questions/15931238/unable-to-remove-file-that-really-exists-fatal-pathspec-did-not-match-any/51623763

I ended manually deleting (in the file explorer) all the content of github directory (except the .git) and commit right after.

@abhinavmanchanda
Copy link

I wrote a script for this a few years ago. You can check it on my blog.

@Timsword
Copy link

Timsword commented Jan 4, 2022

If you get fatal: refusing to merge unrelated histories just read here.

@Saddam-tech
Copy link

its an awesome tutorial, thank you a lot!

@ysulyma
Copy link

ysulyma commented Mar 15, 2022

Very helpful, cheers!

@guadagn0
Copy link

guadagn0 commented Jun 7, 2022

Very helpful, thank you!

@kotorkovsciy
Copy link

It is really helpful. Thank you so much!

@marvin-hris
Copy link

if you have 2 duplicate repositories like this with same origin main :

  1. https://github.com/user-1/repo_name (first create last month)
  2. https://github.com/user-2/repo_name (active development last push today)

and you want to apply change in repo 2 into repo 1
you just need do this :

  1. cd /path_to_repo_2

  2. open .git directory

  3. open file name "config"

  4. change line of remote origin and save it
    [remote "origin"]
    url = "https://github.com/repo_2/repo_name.git"
    to
    [remote "origin"]
    url = "https://github.com/repo_1/repo_name.git"

  5. git push all of your change into new origin main

done.

note : change remote origin is only for a duplicate repo mistake, i recommended back it up before you doing this.

thanks

@RicardoJeronimo
Copy link

Thank you so much!

@4mubarak
Copy link

This Doesnt work for me Now

@Ehtz
Copy link

Ehtz commented Apr 22, 2024

What i did:

Let's say you want to merge repo A main into repo B main.

  1. Go to internal repo of A and add the remote repo connection to B -> terminal -> git add remote <any name> (git URL repo B)

  2. Then to check if there are 2 remote repos associated to the internal repo: git remote -v

This should return:

any name https://github.com/reponame/app.git (fetch)<- (this is repo B)
any name https://github.com/reponame/app.git (push) <- (this is repo B)
origin https://github.com/reponame/app.git (fetch) <- (this is repo A)
origin name https://github.com/reponame/app.git (push) <- (this is repo A)
  1. Then push the A commits to B repo: git push any name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment