Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining multiple git repositories

Tags:

git

People also ask

Can I merge 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.

How do I merge Git repositories and keep history?

To combine two separate Git repositories into one, add the repository to merge in as a remote to the repository to merge into. Then, combine their histories by merging while using the --allow-unrelated-histories command line option.


Here's a solution I gave here:

  1. First do a complete backup of your phd directory: I don't want to be held responsible for your losing years of hard work! ;-)

    $ cp -r phd phd-backup
    
  2. Move the content of phd/code to phd/code/code, and fix the history so that it looks like it has always been there (this uses git's filter-branch command):

    $ cd phd/code
    $ git filter-branch --index-filter \
        'git ls-files -s | sed "s#\t#&code/#" |
         GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
         git update-index --index-info &&
         mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
    
  3. Same for the content of phd/figures and phd/thesis (just replace code with figures and thesis).

    Now your directory structure should look like this:

    phd
      |_code
      |    |_.git
      |    |_code
      |         |_(your code...)
      |_figures
      |    |_.git
      |    |_figures
      |         |_(your figures...)
      |_thesis
           |_.git
           |_thesis
                |_(your thesis...)
    
  4. Then create a git repository in the root directory, pull everything into it and remove the old repositories:

    $ cd phd
    $ git init
    
    $ git pull code
    $ rm -rf code/code
    $ rm -rf code/.git
    
    $ git pull figures --allow-unrelated-histories
    $ rm -rf figures/figures
    $ rm -rf figures/.git
    
    $ git pull thesis --allow-unrelated-histories
    $ rm -rf thesis/thesis
    $ rm -rf thesis/.git
    

    Finally, you should now have what you wanted:

    phd
      |_.git
      |_code
      |    |_(your code...)
      |_figures
      |    |_(your figures...)
      |_thesis
           |_(your thesis...)
    

One nice side to this procedure is that it will leave non-versioned files and directories in place.

Hope this helps.


Just one word of warning though: if your code directory already has a code subdirectory or file, things might go very wrong (same for figures and thesis of course). If that's the case, just rename that directory or file before going through this whole procedure:

$ cd phd/code
$ git mv code code-repository-migration
$ git commit -m "preparing the code directory for migration"

And when the procedure is finished, add this final step:

$ cd phd
$ git mv code/code-repository-migration code/code
$ git commit -m "final step for code directory migration"

Of course, if the code subdirectory or file is not versioned, just use mv instead of git mv, and forget about the git commits.


git-stitch-repo will process the output of git-fast-export --all --date-order on the git repositories given on the command-line, and create a stream suitable for git-fast-import that will create a new repository containing all the commits in a new commit tree that respects the history of all the source repositories.


Perhaps, simply (similarly to the previous answer, but using simpler commands) making in each of the separate old repositories a commit that moves the content into a suitably named subdir, e.g.:

$ cd phd/code
$ mkdir code
# This won't work literally, because * would also match the new code/ subdir, but you understand what I mean:
$ git mv * code/
$ git commit -m "preparing the code directory for migration"

and then merging the three separate repos into one new, by doing smth like:

$ cd ../..
$ mkdir phd.all
$ cd phd.all
$ git init
$ git pull ../phd/code
...

Then you'll save your histories, but will go on with a single repo.


You could try the subtree merge strategy. It will let you merge repo B into repo A. The advantage over git-filter-branch is it doesn't require you to rewrite your history of repo A (breaking SHA1 sums).