Merging One Git Repo into Another

After working with two separate git reposes for a while, I realized that they actually belonged together, and that the contents of one of the reposes actually should just reside in a subdirectory in the other one. After asking around, and experimenting quite a bit I figured out how to do this, and so I write this as a reminder, should I ever have to do this again. (Needless to say, if you intend to follow these instructions, make backups of your reposes.)

Fetch the repo to be included

First we need to get the data from the repo we’re about to include. We’ll put it into a separate branch (imaginativelly called “newbranch” here) of our main repo.

git fetch /path/to/repo/to/include master:newbranch

Move fetched stuff into its own subdir

Now, if we wanted, we could simply checkout this new branch, move all files in it into a subdirectory using git mv and thereafter do a merge—but then we’d loose all the log history of those files (actually, it’d still be there, but git log FILENAME wouldn’t give it to us since it doesn’t follow file name changes). So, to avoid this, let’s do a little bit of history re-engineering on this “newbranch”.

This magic isn’t mine, but actually comes from git help filter-branch (search for “move the whole tree into a subdirectory”—it’s at the very end of the page). This’ll move all contents into the newly fetched “newbranch” into a single subdirectory called “old”.

SUBDIR_NAME=old
BRANCH_NAME=newbranch
git filter-branch --index-filter \
    'git ls-files -s | \
        sed "s-\t-&'"$SUBDIR_NAME"'/-" | \
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && \
        mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
    ' "$BRANCH_NAME"

(If the above results in a “Cannot rewrite branch(es) with a dirty working directory.” error, then make sure your working directory is clean—i.e. that git status reports “nothing to commit”.)

Merge fetched stuff into main branch

Now we only need to merge “newbranch” into our main branch and remove it as a separate branch from our repository. Like so:

git merge newbranch
git branch -d newbranch   # optional, removes newbranch

Thanxes

Thanx to Grum on the #git IRC channel (on freenode), for pointing me in the right direction, and thanx to Merging repositories and their histories for being the right direction into which I was pointed.


By Zrajm C Akfohg in Uppsala [2009-03-07] (Validate: XHTML, CSS, links License: CC BY–SA)