Reputation: 7539
I have a git
repository which, essentially, contains two related projects, which I would like now to split. I would like to move the files related to one project to a new repository, preserving the history of changes. To be concrete, let us suppose that the original git repository contains:
file1.c
file2.c
subdir/file2_extra.c
Also, the original git
repository contains several branches. I want to keep onlly some of them, those related with the files I want to separate.
How can I create a new git
repository containing, say, file2.c
and subdir/file2_extra.c
only, together with the history of commits to them?
Notice that the files I want to separate are not found in a separate directory. For otherwise, I think one can use git subtree
.
I tried to use git filter-branch
, without success. Let us assume the original repository is git_original
, what I have tried is
$ git clone git_original/ git_new
Cloning into 'git_new'...
done.
$ cd git_new
$ git rm file1.c
rm 'file1.c'
$ git filter-branch --prune-empty -- --all
Cannot rewrite branches: Your index contains uncommitted changes.
But if I commit the removal of file1.c
, then git filter-branch
does not do anything.
Upvotes: 2
Views: 164
Reputation: 7539
Based on this link (thanks to @marekful for providing this) I have devised this solution. The main idea is to clone the repository into a new one, and eliminate the unwanted files in each commit. I am assuming one has a remote repository, and each local branch tracks the corresponding remote branch.
Clone the old repository into a new one.
$ git clone git_original/ git_new
Go into the new repository.
$ cd git_new
For each desired branch in the new repository set up a branch.
$ git branch -t branch_name origin/branch_name
Delete every unwanted file in the new repository. E.g., in the example of the question, I wanted to delete the file file1.c.
$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch file1.c' \
--prune-empty -- --all
The option -f
should be necessary if you delete more than one file, as it forces to overwrite the "old" refs.
By a git checkout
to all the branches of the new repository, you can check that indeed the unwanted files have been eliminated.
Some cleanup.
$ git reflog expire --expire=now --all
$ git gc --prune=now --aggressive
Now, remove the old origin and associate with a new remote repository.
$ git remote rm origin
$ git remote add origin remote_origin_address
Finally push everything to the new remote.
$ git push -u origin --all
$ git push -u origin --tags
Upvotes: 2