结合Git仓库的前两个提交?


197

假设您有一个包含三个提交A,BC的历史记录:

A-B-C

我想将两个提交AB合并到一个提交AB

AB-C

我试过了

git rebase -i A

这将打开我的编辑器,其中包含以下内容:

pick e97a17b B
pick asd314f C

我将其更改为

squash e97a17b B
pick asd314f C

然后Git 1.6.0.4说:

Cannot 'squash' without a previous commit

有办法还是这不可能?


另请参阅:在Git中编辑根提交?

Answers:


168

使用git rebase -i --root 作为的Git 版本1.7.12

在交互式rebase文件中,将提交B的第二行更改为squash,而将其他行保留为pick

pick f4202da A
squash bea708e B
pick a8c6abc C

这会将两个提交AB合并为一个提交AB

找到了这个答案


126

您尝试过:

git rebase -i A

如果继续edit而不是squash:可以这样开始。

edit e97a17b B
pick asd314f C

然后跑

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

做完了


4
如果您这样做是为了悄悄地修复github要点,则必须在提交中添加-m“ initial”。;-)
Bruno Bronosky 2011年

1
git rebase --abort重新开始并以正确的方式进行操作(不压缩编辑器中的第一次提交)
oma

66

A是初始提交,但是现在您想B成为初始提交。git commit是完整的树,而不是diff,即使它们通常根据引入的diff进行描述和查看也是如此。

即使A和B以及B和C之间有多次提交,此配方仍然有效。

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp

1
当我这样做时git rebase --onto tmp <sha1_for_B>
Alex

考虑到我有一个只有两个提交的全新回购协议(我想合并为一个),所以这对我来说非常理想。谢谢@CB Bailey
RominRonin

10

对于交互式变基,您必须在A之前执行,这样列表将是:

pick A
pick B
pick C

成为:

pick A
squash B
pick C

如果A是初始提交,则必须在A之前具有不同的初始提交。Git认为差异,它将对(A和B)与(B和C)之间的差异起作用。因此,壁球在您的示例中不起作用。


9

在你已经提交的数百或数千使用情况kostmo的答案

git rebase -i --root

可能是不切实际且缓慢的,仅是因为rebase脚本必须处理两次提交,一次是生成交互式rebase编辑器列表(您可以在其中选择每次提交要采取的操作),一次是实际执行重新提交。

这是一个替代解决方案通过首先不使用交互式资源库,可以避免生成交互式资源库编辑器列表的时间成本。这样,它类似于Charles Bailey的解决方案。您只需从第二个提交创建一个孤立分支,然后在其顶部重新排列所有后代提交:

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

文献资料



0

小队的Git命令:git rebase -i HEAD〜[提交数]

假设您有以下git commit历史记录:


选择5152061壮举:添加了对保存图像的支持。(A)
选择39c5a04修复:错误修复。(b)
选择839c6b3修复:冲突已解决。(C)

现在,您要将A和B压缩到AB,请执行以下步骤:


选择5152061壮举:添加了对保存图像的支持。(A)
的39c5a04修复:错误修复。(b)
选择839c6b3修复:冲突已解决。(C)

注意:对于挤压提交,我们可以使用s或s。最终结果将是:
选择5152061壮举:添加了对保存图像的支持。(AB)
选择839c6b3修复:解决了冲突。(C)


-1

您必须执行一些命令行魔术。

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

那应该给您留下一个具有AB和C作为提交的分支。


因为旧的和新的初始提交没有共同的祖先,所以即使git有一个共同的树,当git尝试将master的整个历史应用到a上时,您也可能会遇到一些不必要的冲突。通过使用--onto选项进行git rebase,可以告诉git开始应用的正确位置。
CB Bailey
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.