0

I have a git repository with several branches, and I would like to split it in two repositories.

Imagine that I list all commits made to that repository, and the result is something like:

Commit #1 to branch master
Commit #2 to branch master
Commit #3 to branch fixing_bugs
Commit #4 to branch master
Commit #5 to branch fixing_bugs
Commit #6 to branch master
Commit #7 to branch adding_sexy_french_girls_to_the_code
Commit #8 to branch adding_sexy_french_girls_to_the_code
Commit #9 to branch master

So in total, this repository has 3 branches: master, fixing_bugs and adding_sexy_french_girls_to_the_code.

Now I want to split this repository in two, using commit #6. So I would have two repositories like the following:

Repository 1

Commit #1 to branch master
Commit #2 to branch master
Commit #3 to branch fixing_bugs
Commit #4 to branch master
Commit #5 to branch fixing_bugs

Having branches master, fixing_bugs.

Repository 2

Commit #6 to branch master
Commit #7 to branch adding_sexy_french_girls_to_the_code
Commit #8 to branch adding_sexy_french_girls_to_the_code
Commit #9 to branch master

Having branches master, adding_sexy_french_girls_to_the_code.

I understand this may be technically challenging, but I believe it is not impossible to do with Git (le hope).

How can I do this?

Thank you.

2 Answers2

1

Create your 2nd branch from your master with

git checkout -b <your_new_branch>

I would suggest you to start with the same code in each branch and the rewrite the history by rebasing with :

git rebase HEAD~9 -i

And then you can easily delete the lines you want for each branch.

Because you are rewriting your history you will have to push force the changes :

git push origin <your_branch> --force

[UPDATE] I saw the last comments then you will have to squash your commits on repository 2 in order to replace each pick by s for squash with your last commit #6.

After git rebase HEAD~9 -i on Repository 1:

pick #1 to branch master
pick #2 to branch master
pick #3 to branch fixing_bugs
pick #4 to branch master
pick #5 to branch fixing_bugs
pick #6 to branch master
pick #7 to branch adding_sexy_french_girls_to_the_code
pick #8 to branch adding_sexy_french_girls_to_the_code
pick #9 to branch master 

you should have :

pick #1 to branch master
pick #2 to branch master
pick #3 to branch fixing_bugs
pick #4 to branch master
pick #5 to branch fixing_bugs

(type dd on vim to delete the lines)

After git rebase HEAD~9 -i on Repository 2:

pick #1 to branch master
pick #2 to branch master
pick #3 to branch fixing_bugs
pick #4 to branch master
pick #5 to branch fixing_bugs
pick #6 to branch master
pick #7 to branch adding_sexy_french_girls_to_the_code
pick #8 to branch adding_sexy_french_girls_to_the_code
pick #9 to branch master 

you should have :

s #1 to branch master
s #2 to branch master
s #3 to branch fixing_bugs
s #4 to branch master
s #5 to branch fixing_bugs
pick #6 to branch master
pick #7 to branch adding_sexy_french_girls_to_the_code
pick #8 to branch adding_sexy_french_girls_to_the_code
pick #9 to branch master 

(edit the lines and the first 5 lines will be squashed with #6)

Franck
  • 1,354
  • 12
  • 17
1

You can make use of git format-patch and git am to copy commits from your existing repository to the new one, follow by a git reset to remove the copied commits from the existing repository.

Try these commands to copy the commits to the new repository:

$ cd /path/to/new_repo_folder # don't forget to run git init if this is a new folder
$ git --git-dir=/path/to/existing_repo_folder/.git format-patch --stdout sha1_of_commit5..sha1_of_commit_9 | git am

So essentially, the git format-patch command creates one patch file for each of your commit, from commit 6 to commit 9. If the --stdout option is not provided, these patch files will be saved in your existing_repo_folder. Subsequently, the git am command applies the history of commit 6 to commit 9 in your new_repo_folder. Now when you run git log in your new_repo_folder, you will see the history of commit 6 to 9.

Finally, if commit 9 is your HEAD, then you can run git reset --hard HEAD~3 in your existing_repo_folder to set the position of HEAD to commit 5, which is 3 commits before, and that's what that ~3 represents.

Of course, you are essentially rewriting the history of your repository. If you are sharing your codes with other people, make sure you have their consensus. Otherwise, your next git push -f is going to cause everyone a lot of grief.

ivan.sim
  • 8,972
  • 8
  • 47
  • 63
  • Running the following command within the new repository directory git --git-dir=/home/nemewsys/Desktop/original/lumina.git format-patch --stdout ed2bf8e..aa9a48f | git am I get: http://pastebin.com/VsVydaz0 What am I doing wrong? –  Jan 09 '15 at 20:49
  • @ManelJ It's complaining about `error: proj/pom.xml: does not exist in index`. Does `proj/pom.xml` exist in your new folder? Also, your `--git-dir` option is supposed to be `Desktop/original/lumina/.git` (referring the `.git` folder). Keep in mind, the file structure in your `Desktop/original/lumina/` has to be the same as the old folder. – ivan.sim Jan 09 '15 at 23:55
  • Im confused. My new folder is empty, I just made git init there, nothing more. And I am running that command in the new folder. –  Jan 10 '15 at 00:36
  • Note: Desktop/original/lumina/ is the folder of the **old** repository. –  Jan 10 '15 at 00:37
  • @ManelJ Right. So what if you copy the content of `Desktop/original/lumina/` (except for `Desktop/original/lumina/.git`) to your new folder, then follow by `git init`? Remember, the `git format` and `git am` commands are simply patching your new repo with the commit history from the old folder. If `proj/pom.xml` doesn't exist in your new repo, it's not going to magically create it for you unless it's part of the history in your patch. – ivan.sim Jan 10 '15 at 00:56
  • But is he asking me all files from all commits to be present? This is so strange. Git init is the only straight command in git, everything else is as cryptic as the universe itself. Damn... –  Jan 13 '15 at 11:18
  • @ManelJ Yes, you have to copy all files (except for `.git` folder) from your existing `Desktop/original/lumina` to the folder of your new repo. – ivan.sim Jan 20 '15 at 05:57