git: migrating a directory into a new repository with history
I had a problem. I started a new project in git with a very broadly defined scope. As I started hacking along, I realized that some of the components of my project should probably be pulled out into their own seperate library. With this came the problem:
I wanted to:
- pull a directory of my existing git project out of the repo
- put those files into a new repo
- retain the history of the files that were moved in the new repository
Let’s assume for this example that I have the following existing git repository:
big_project/ '-> test/ src/ '-> mylib/ '-> mylib.h mylib.c main.c doc/
Through the process of evolution, we’ve found that ‘mylib’ is actually quite capable of standing on it’s own, and thus we’d like to move it into it’s own seperate repository. WARNING: Make sure you have backups of your repository in case anything goes wrong, some operations listed below are destructive
step 1: clone existing repository
cd to the directory with the repository and issue the following command:
$ git clone --no-hardlinks big_project mylib
This will create a copy of the project ommiting filesystem hardlinks. Both big_project and mylib are exactly the same at this point. Now let’s do some history modification:
step 2: filter branch the subdirectory
cd to the mylib repository copy and issue the follow commands:
$ git filter-branch --subdirectory-filter src/mylib HEAD
$ git reset --hard
$ git gc --aggressive
$ git prune
The first command will make the ‘src/mylib’ directory the root of your repository and strip out all the files and history not in that directory. The reset –hard will move your current HEAD to the top of the history that was rewritten. git gc –aggressive will repack all of git’s objects and remove ones that are not in your new history. git prune will remove all unreachable objects from the object database.
Next we need to remove ‘src/mylib’ out of big_project:
step 3: remove files and history from old repository
cd back to your original project (big_project) and issue the following command:
git filter-branch --tree-filter "rm -rf src/mylib" --prune-empty HEAD
This will remove the ‘src/mylib’ directory from big_project.
end result
You should now have 2 git repositories that look like this:
big_project/ '-> test/ src/ '-> main.c doc/
mylib/ '-> mylib.h mylib.c
Each of these repositories will have history that corresponds with the files that are present in the respective repository.
sources
This information was derived from this StackOverflow question.
» More blog posts
« Back to home