合并 Git 存储库的前两个提交?

Posted

技术标签:

【中文标题】合并 Git 存储库的前两个提交?【英文标题】:Combine the first two commits of a Git repository? 【发布时间】:2010-09-30 22:36:42 【问题描述】:

假设您的历史记录包含三个提交 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

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

【问题讨论】:

另见:Edit the root commit in Git?。 参见:Squash the first two commits in Git?。 【参考方案1】:

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

pick A
pick B
pick C

变成:

pick A
squash B
pick C

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

【讨论】:

【参考方案2】:

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

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

这应该会给你留下一个包含 AB 和 C 作为提交的分支。

【讨论】:

因为旧的和新的初始提交没有共同的祖先,当 git 试图将 master 的整个历史应用到 a 时,即使它们有一个共同的树,你也可能会遇到一些不必要的冲突。通过对 git rebase 使用 --onto 选项,您可以告诉 git 开始应用的正确位置。【参考方案3】:

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

【讨论】:

这会在我执行git rebase --onto tmp &lt;sha1_for_B&gt; 时触发大规模的交互式变基 考虑到我有一个全新的 repo,只有两个提交(我想合并为一个),这对我来说非常有效。谢谢@CB Bailey【参考方案4】:

你试过了:

git rebase -i A

如果您继续使用edit 而不是squash,则可以这样开始:

edit e97a17b B
pick asd314f C

然后运行

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

完成。

【讨论】:

如果你这样做是为了悄悄地修复一个 github gist,你必须在提交中添加 -m "initial"。 ;-) git rebase --abort 重新开始并以正确的方式进行(不压缩编辑器中的第一个提交)【参考方案5】:

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

如果您有兴趣:git: how to insert a commit as the first, shifting all the others?

【讨论】:

如果这里也重复这个答案会更好吗?我不确定。【参考方案6】:

使用git rebase -i --root 从 Git version 1.7.12.

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

pick f4202da A
squash bea708e B
pick a8c6abc C

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

发现于this answer。

【讨论】:

【参考方案7】:

如果你有成百上千的提交,使用kostmo's answer of

git rebase -i --root

可能是不切实际和缓慢的,只是由于变基脚本必须处理大量提交两次,一次生成交互式变基编辑器列表(您可以在其中选择要采取的操作每个提交),并且一次实际执行提交的重新应用。

这是一个替代解决方案,它将避免生成交互式变基编辑器列表的时间成本首先不使用交互式变基。这样,就类似于Charles Bailey's solution。您只需从第二次提交创建一个 孤儿分支,然后在其上重新设置所有后代提交:

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

文档

git-checkout(1) Manual Page git-rebase(1) Manual Page

【讨论】:

【参考方案8】:

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

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

pick 5152061 壮举:增加了对保存图像的支持。 (一种) pick 39c5a04 修复:错误修复。 (乙) pick 839c6b3 修复:冲突已解决。 (C)

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

pick 5152061 壮举:增加了对保存图像的支持。 (一种) s 39c5a04 修复:错误修复。 (乙) pick 839c6b3 修复:冲突已解决。 (C)

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

【讨论】:

以上是关于合并 Git 存储库的前两个提交?的主要内容,如果未能解决你的问题,请参考以下文章

忽略已提交到 Git 存储库的文件 [重复]

你推动每一次提交吗? [关闭]

如何通过非交互方式压缩除最近提交之外的所有提交来减少臃肿的 Git 存储库的大小?

如何请求提交到开源 git 存储库的权限? [复制]

忽略已经提交到Git存储库的文件[重复]

git rebase 交互式:将提交合并到一起