合并Git仓库的前两次提交?

dwthyt8l  于 2023-06-28  发布在  Git
关注(0)|答案(9)|浏览(139)

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

有办法吗?还是根本不可能?

brjng4g3

brjng4g31#

从Git version 1.7.12开始使用git rebase -i --root
在交互式变基文件中,将commit B 的第二行更改为 squash,并将其他行保留在 pick

pick f4202da A
squash bea708e B
pick a8c6abc C

这将把两个提交 AB 合并为一个提交 AB
this answer中找到。

vu8f3i0k

vu8f3i0k2#

你试过:

git rebase -i A

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

edit e97a17b B
pick asd314f C

然后跑

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

好了

yruzcnhs

yruzcnhs3#

A是初始提交,但现在您希望B成为初始提交。git提交是整个树,而不是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
qzwqbdag

qzwqbdag4#

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

git rebase -i --root

可能是不切实际和缓慢的,只是由于大量的提交,rebase脚本必须处理 * 两次 *,一次是生成交互式rebase编辑器列表(在那里你选择对每个提交采取什么行动),一次是实际执行提交的重新应用。
这里有一个替代解决方案,它将避免生成交互式变基编辑器列表 * 的时间成本,因为它首先不使用交互式变基 *。在这种情况下,它类似于Charles Bailey's solution。你只需要从第二次提交创建一个 *orphan分支 *,然后在它的基础上重基所有的后代提交:

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

文档

wgx48brx

wgx48brx5#

在交互式变基的情况下,你必须在A之前做,这样列表将是:

pick A
pick B
pick C

成为:

pick A
squash B
pick C

如果A是初始提交,那么在A之前必须有一个不同的初始提交。Git在差异中思考,它将处理(A和B)和(B和C)之间的差异。因此,squash在您的示例中不起作用。

htzpubme

htzpubme6#

在一个相关的问题中,我设法提出了一种不同的方法来解决第一次提交的挤压需求,也就是说,让它成为第二次提交。
如果您感兴趣:git: how to insert a commit as the first, shifting all the others?

piok6c0g

piok6c0g7#

Git命令:git rebase -i HEAD~[提交次数]
假设你有下面的git commit history:
pick 5152061 feat:增加了保存图像的支持。(一)
pick 39 c5 a04修复:错误修复。(B)
pick 839 c6 b3修复:冲突解决。(C)
现在你想将A和B压缩到AB,请执行以下步骤:
pick 5152061 feat:增加了保存图像的支持。(一)
s 39 c5 a04修复:错误修复。(B)
pick 839 c6 b3修复:冲突解决。(C)
注意:对于压缩提交,我们可以使用squash或s。最终结果将是:
pick 5152061 feat:增加了保存图像的支持。(AB)
pick 839 c6 b3修复:冲突解决。(C)

ego6inou

ego6inou8#

我也在想如果结构像

X-Y------Z
 \-A-B-C/

我希望最终的结构是

X-Y-----Z
 \-AB-C/

在这种情况下,如何将A和B合并?

ftf50wuq

ftf50wuq9#

您必须执行一点命令行魔法。

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

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

相关问题