Combine the first two commits of a Git repository?

2019-01-02 19:16发布

Suppose you have a history containing the three commits A, B and C:

A-B-C

I would like to combine the two commits A and B to one commit AB:

AB-C

I tried

git rebase -i A

which opens up my editor with the following contents:

pick e97a17b B
pick asd314f C

I change this to

squash e97a17b B
pick asd314f C

Then Git 1.6.0.4 says:

Cannot 'squash' without a previous commit

Is there a way or is this just impossible?

8条回答
裙下三千臣
2楼-- · 2019-01-02 19:38

In the case of interactive rebase, you have to do it before A so that the list will be:

pick A
pick B
pick C

to become:

pick A
squash B
pick C

If A is the initial commit, you have to have a different initial commit before A. Git thinks in differences, it will work on the difference between (A and B) and (B and C). Hence the squash not working in your example.

查看更多
爱死公子算了
3楼-- · 2019-01-02 19:40

Git command for squad: git rebase -i HEAD~[number of commits]

Lets say you have below git commit history:


pick 5152061 feat: Added support for saving image. (A)
pick 39c5a04 Fix: bug fixes. (B)
pick 839c6b3 fix: conflict resolved. (C)

Now you want to squash A and B to AB, perform below steps:


pick 5152061 feat: Added support for saving image. (A)
s 39c5a04 Fix: bug fixes. (B)
pick 839c6b3 fix: conflict resolved. (C)

Note: for squashing commit we can use squash or s. The end result will be:
pick 5152061 feat: Added support for saving image. (AB)
pick 839c6b3 fix: conflict resolved. (C)

查看更多
有味是清欢
4楼-- · 2019-01-02 19:43

In the case that you have hundreds or thousands of commits, using kostmo's answer of

git rebase -i --root

can be impractical and slow, just due to the large number of commits that the rebase script has to process twice, once to generate the interactive rebase editor list (where you select what action to take for each commit), and once to actually execute the re-application of commits.

Here is an alternative solution that will avoid the time cost of generating the interactive rebase editor list by not using an interactive rebase in the first place. In this way, it's similar to Charles Bailey's solution. You simply create an orphan branch from the second commit, and then rebase all the descendant commits on top of it:

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

Documentation

查看更多
听够珍惜
5楼-- · 2019-01-02 19:45

You tried:

git rebase -i A

It is possible to start like that if you continue with edit rather than squash:

edit e97a17b B
pick asd314f C

then run

git reset --soft HEAD^
git commit --amend
git rebase --continue

Done.

查看更多
弹指情弦暗扣
6楼-- · 2019-01-02 19:48

Use git rebase -i --root as of Git version 1.7.12.

In the interactive rebase file, change the second line of commit B to squash and leave the other lines at pick:

pick f4202da A
squash bea708e B
pick a8c6abc C

This will combine the two commits A and B to one commit AB.

Found in this answer.

查看更多
几人难应
7楼-- · 2019-01-02 19:50

In a related question, I managed to come up with a different approach to the need of squashing against the first commit, which is, well, to make it the second one.

If you're interested: git: how to insert a commit as the first, shifting all the others?

查看更多
登录 后发表回答