215

假设您有一个包含三个提交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

有没有办法或者这是不可能的?

4

8 回答 8

195

git rebase -i --root 从 Git版本 1.7.12开始使用。

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

pick f4202da A
squash bea708e B
pick a8c6abc C

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

这个答案中找到。

于 2014-02-09T02:14:48.493 回答
126

你试过:

git rebase -i A

如果您继续使用edit而不是squash

edit e97a17b B
pick asd314f C

然后运行

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

完毕。

于 2009-02-12T14:29:00.527 回答
66

A是最初的提交,但现在你想B成为最初的提交。git 提交是整棵树,而不是差异,即使它们通常是根据它们引入的差异来描述和查看的。

即使 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
于 2009-01-12T18:46:20.810 回答
10

在交互式 rebase 的情况下,您必须在 A 之前执行此操作,以便列表为:

pick A
pick B
pick C

成为:

pick A
squash B
pick C

如果 A 是初始提交,则必须在 A 之前进行不同的初始提交。Git 考虑差异,它将处理(A 和 B)和(B 和 C)之间的差异。因此,壁球在您的示例中不起作用。

于 2009-01-12T15:05:39.883 回答
10

如果您有数百或数千次提交,请使用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

文档

于 2014-07-23T15:00:27.867 回答
1

在一个相关的问题中,我设法提出了一种不同的方法来解决第一次提交的压缩需求,也就是说,使它成为第二次提交。

如果您有兴趣:git:如何将提交作为第一个插入,然后转移所有其他提交?

于 2009-03-14T08:15:03.477 回答
0

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

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


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

现在你想将 A 和 B 压缩到 AB,执行以下步骤:


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

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

于 2018-11-22T06:35:18.700 回答
-1

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

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

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

于 2009-01-12T15:36:17.530 回答