Sunday, May 26, 2013

Importing/moving a git project into a directory

Recently I worked on a project which obviously used a git repository. Then the project needed to be integrated in a bigger project, as a directory. The simple method was to copy-paste the project to it's final destination, but that would mean loosing all the commits. Fortunately, there is a solution to do this without loosing the commits: filter-branch.

Let's assume that we want to copy/move project A into project B, in directory "a". The idea is simple enough and it involves 2 steps:
  1. Modify the structure of project A in order to have all the content in directory "a"
  2. Import project A in project B
In order to do the first step, we use filter-branch like this:
git clone a a_tmp # work on a copy of project A, just to be safe
cd a_tmp
git filter-branch -f --prune-empty --tree-filter '
mkdir -p .tmp-dir
mv * .tmp-dir
mv .gitignore .tmp-dir/
mv .tmp-dir a
' -- --all 

This command does the following:
- The "-f" switch will force filter-branch to continue, even in the case of an error.
- The "--prune-empty" switch will skip empty commits.
- The "--tree-filter" switch has a shell command as the argument. This command is composed from the following 4 lines.

As can be seen, we create a directory, but the name of this directory starts with a dot. This is done so that mv will not try to move a directory inside itself. The "mv" command skips names that start with a dot (are hidden). This is why we move the .gitignore file explicitly.

We now proceed to step 2, importing this restructured git repository inside of project B.
cd ../b
git remote add subproj_a ../a_tmp
git fetch subproj_a
git merge subproj_a/master
git remote rm subproj_a
git gc --aggressive
These commands add a new remote (named subproj_a) with the path ../a_tmp
When we fetch this remote, we will copy the content of that repository (not that you may receive a warning since there are no common commits).
We merge the 2 projects and delete the remote.
The "git gc" command is used in order to delete unused objects.

Resources:
Moving One Git Repository Into Another