Splitting the first commit in git [duplicate]
Asked Answered
Z

2

19

I want to split the first commit in my git repository, but I cannot use rebase to do this because a parent node is required. I found Edit the root commit in Git? useful for modifying the first commit, but not splitting it. How can I split it?

Zena answered 12/9, 2010 at 16:52 Comment(1)
I can’t answer because the question is closed, but IMO it shouldn’t be, because the other answers don’t ask about splitting. The way I found is: do a git rebase --root -i, add a b or break line before the root commit, and mark the root commit with s / skip. This way you the rebase stops before any commits, you can use get checkout <root hash> -- . to get the code from the root commit, and proceed like with at usual split.Branching
U
15

You can just follow exactly the same process in the question you've linked to, but after checking out the root commit you can use git commit --amend to modify the original commit and then git commit to make an additional commit before continuing the with the rebase command.

Depending on how you want to split the commit you can use git rm --cached to remove files that you want to add at the second commit before the initial git commit --amend and edit any files that you want to look different before calling git add on those files, again before you call git commit --amend.

After calling git commit --amend, to make sure that you commit exactly the state of the original root commit you can call:

git checkout <sha1-of-original-root> -- .

before calling git commit to make the second commit of the split root commit.

Uniocular answered 12/9, 2010 at 18:5 Comment(3)
(rewritten) You do not want git reset --hard here. You might use git reset <sha1-of-original-root> -- ., but that will not “restore” the working tree, only the index. Probably the best idea is git checkout <sha1-of-original-root> -- . which will update the index and working tree but not HEAD (leaving you ready to commit the second part of the split (original root) commit). The main idea here is that both reset and checkout will change HEAD except when you give them a path argument.Rato
@Chris Johnsen: You're absolutely correct. I was thinking of a two stage reset, path then --hard but then didn't actually write that. The checkout solution is better.Uniocular
I think it should be clearly mentioned, that before amending the first commit, you need to delete all files from the working directory that should go into the second commit. This seems scary, but is not. After amending, you get them back using the git checkout <sha1-of-original-root> -- .. It's worth noting down the hash of the original root commit beforehand to have it handy.Flacon
V
5

You can use the --root option to tell rebase that you want to rewrite the root/first commit:

$ git rebase --interactive --root

Then the root commit will show up in the rebase TODO list, and you can select to edit it:

edit <root commit sha> <original message>
pick <other commit sha> <message>
...

This is the explanation of --root from the Git rebase docs:

Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a branch.

Varsity answered 14/7, 2013 at 19:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.