我有两个分支:master
和test-branch
(分支为master
)。我的工作看起来如下:
git checkout master
git checkout -b test-branch
git checkout master
git pull
- >其他人做出了改变大师git checkout test-branch
git rebase -i master
pick
之外的所有内容更改为s
我想做的是在变基之前压缩test-branch
上的所有提交,这样我只需要解决一次合并冲突。这可能吗?如果是这样,怎么样?
答案 0 :(得分:6)
有可能,甚至很容易。 Git就是这样,有很多不同的方法可以做到。
从字面上做你最初的建议:
如果你在分支...在重新定位之前压缩测试分支上的所有提交
git merge
上运行master
之前 ,那么最简单。 (我知道您没有将git merge
列为命令,但您在第6步中确实运行了git merge
:
- 醇>
git pull
- >其他人做出了改变大师
因为git pull
只是git fetch
后跟git merge
。)但它之后仍然很容易做到;我们只需要定位正确的commit-ID。
让我们绘制您在步骤4中提交的提交图:
...<- o <- * <-- master, origin/master
\
A <- B <-- HEAD=test-branch
此图显示的是有两个标签 1 指向我标记为*
的提交,即master
和origin/master
。提交*
点返回提交o
,提交回更多提交:这是分支master
的历史。
您创建的分支的标签(现在已开启,因此HEAD=
部分)指向提交B
。提交B
然后指向提交A
,其指向提交*
。这是分支test-branch
的历史记录:您在*
时创建了它,然后添加了A
,然后添加了B
。
此时有两种方法可以轻松压缩提交A
和B
:
git rebase -i master
这为您提供了一个交互式编辑会话,您可以在其中选择&#34;第一次提交,然后&#34;壁球&#34;第二个,它将收集两个提交消息,并让您以通常的方式编辑结果。然后它进行(单个)新提交,其树是commit B
。
git reset --soft master; git commit
这不为rebase打开一个交互式编辑会话:它只是保持staging-area-and tree不会提交B
({{1} ({1}})的一部分,将标签--soft
移回指向直接提交git reset --soft
(test-branch
*
部分git reset
部分,并像往常一样进行新的提交(git reset --soft
)。
缺点是您必须撰写新的提交消息,但您可以通过多种方式从提交git commit
或A
恢复提交消息。例如,您可以使用B
或-c
标记-C
(您必须标识提交git commit
或A
,例如,使用B
或@{1}
或@{1}^
或其他一些reflog说明符)。或者,在执行@{yesterday}
之前,您可以使用git reset --soft
并将日志消息保存在文件中,或者其他任何内容。
(第二种方法闪耀,而不是只有两次提交壁球,你有42左右。)
这两种方法都做同样的事情:他们添加新提交(让我们称之为git log
),留下AB
和{{1我不能正确地绘制出来的灰色背景:
A
您的分支的幽灵版本对于大多数正常使用是不可见的,并且最终(默认情况下在30天左右之后)被垃圾收集掉。 (在此之前,它仍然在您的存储库和您的reflog中,以便您可以找到原始提交B
和 AB <-- HEAD=test-branch
/
...<- o <- * <-- master, origin/master
\
A <- B [ghost version of test-branch]
,以防万一您需要它们。)
如果您已经完成第6步怎么办?在这种情况下,您仍必须识别提交A
。您在撰写本文时可以do it the way jsexpert suggested,或者您可以使用B
找到它:
*
这是如何运作的。在git merge-base
之后(步骤5和6,或多或少),您的提交图现在看起来更像是:
$ mergebase=$(git merge-base HEAD master)
# then pick just ONE of the next two
$ git rebase -i $mergebase
$ git reset --soft $mergebase; git commit
git checkout master; git fetch; git merge; git checkout test-branch
和...<- o <- * <- o <-- master, origin/master
\
A <- B <-- HEAD=test-branch
指向的新o
提交 - 或者它可能是整个提交链 - 是&#34;在方式&#34;中,但是&#34;合并基地&#34; master
(你现在在哪里)和origin/master
是提交test-branch
:两个分支分歧之前最近的共享提交。
然后我们只是在该提交中定位master
或*
。当我们完成并拥有一个新的rebase
提交时,它看起来像这样:
reset --soft
一旦你被压扁AB
提交,你就可以 AB <-- HEAD=test-branch
/
...<- o <- * <- o <-- master, origin/master
\
A <- B [ghost version of test-branch]
以AB
方式进行提交。
请注意,另一个答案是完全相同的事情,它只是通过计算提交来识别提交git rebase
。如果你知道master
的提示和&#34;有趣的&#34;之间有两个提交。 commit *
,test-branch
标识与*
相同的提交。使用HEAD~2
只允许您避免计数。
1 &#34;参考文献&#34;是实际的一般git术语。在这种情况下,他们是分支名称,我使用的是&#34;标签&#34;将它们与此提交图形成的分支历史区分开来。单词&#34; branch&#34;在git中用来指代至少这两个不同的东西,它会让人感到困惑。
答案 1 :(得分:2)
当然有可能,yoiu只需输入: git rebase -i HEAD~<# of commits to squash>
-i用于交互式rebase。一旦你这样做,你将看到vi,其中包含每次提交下一步的说明。
有关它的详细信息可以在 Rewriting history 找到: