如何在Git中压缩提交?

时间:2017-05-17 09:39:45

标签: git github git-merge git-squash

我正在尝试压缩我的提交并将我的分支合并为master,作为一次提交。这就是我正在尝试的。我切换到主分支然后我做

git merge --squash <branch_name>

我得到了

Automatic merge went well; stopped before committing as requested
Squash commit -- not updating HEAD

之后我承诺。但是,这就是我得到的

$ git commit -m "Resolved"
On branch master
nothing to commit, working tree clean

由于某种原因,更改没有反映出来,我得到的消息没有提交。我已经在堆栈上经历了很多帖子和问题但直到现在都没有任何帮助。

2 个答案:

答案 0 :(得分:1)

我不完全清楚你承认什么是壁球合并,因此你得到这个结果的原因。您可以向自己清理第一个问题(因为我没有提交,因此很难帮助):

git log --decorate --oneline --graph --boundary master...<branch-name>

(请注意这里的三个点)。这将显示您现在在master上提交的内容,以及您将通过这两个分支的合并基础提交从<branch-name>引入的内容。

无论如何,我可以做出很好的猜测,因为git merge的工作方式是将此合并基数与两个分支提示进行比较。这是在进行合并之前的示例图片段(此时,无论这是常规合并还是压缩合并都无关紧要):

...--B--C--D   <-- master (HEAD)
      \
       E--F--G   <-- feature

每个单个大写字母代表一个提交(其真实ID是Git哈希ID,如a9f3c72或其他)。这里的合并基础提交是提交B:它是提交链的位置,同时从masterfeature开始提交向后工作(在此图中向左),首先聚集在一起。换句话说,提交B 分支master 分支feature上的最新提交。这就是使其成为合并基础提交的原因。

Git现在实际上会运行:

git diff B D   # see what "we" did on branch master
git diff B G   # see what "they" did on branch feature

Git必须组合这些更改:如果我们更改README以在最后添加一行,Git应该将此额外行添加到最后。如果他们以某种方式更改foo.py(可能会添加一行并删除另一行),Git应将其更改为foo.py。但是,如果我们两者都完全相同的事情,那么Git应该只需要一个副本。例如,如果我们在foo.py上将相同的更改为master,那么我们根本不需要他们的更改:它被我们的更改。

让我们说我们更改了README,我们和他们都在foo.py修复了相同的事情,但他们也改变了doc.txtmain.py。因此,我们的最后一组更改是将我们添加的行添加到README,保持foo.py更改,并选择doc.txtmain.py更改。结果是Git将所有这些应用于合并基础提交B的内容。 这为我们提供了新提交的内容H(请注意H中的内容,因为它可能会回来困扰我们。)Git更新这个新内容的索引(下一次提交的地方)和工作树(我们可以看到将要或将被提交的内容)准备好提交。

现在常规vs squash合并突然变得很重要,因为如果Git要进行常规合并提交,它会这样做:

...--B--C--D---H   <-- master (HEAD)
      \       /
       E--F--G   <-- feature

这个新的合并提交 H将提交C-D中完成的所有工作与提交E-F-G中完成的所有工作相结合,将指向两者提交Dmaster的上一个提示,并提交Gfeature的前一个和当前提示。

如果Git要进行壁球提交,那么,它会在说完之后停止:

Automatic merge went well; stopped before committing as requested
Squash commit -- not updating HEAD
$ 

它使我们进行提交。一旦我们进行了这次提交,我们就会得到新的提交H,但这次它指向两者 D G。这次,新提交H仅将指向指向D

...--B--C--D---H   <-- master (HEAD)
      \
       E--F--G   <-- feature

让我们说这一切都按照应有的方式运行,而我们实际上是提交H。这引起了我认为最有可能的情况。

可能的情况

如果我们再次运行git merge --squash feature ,让我们看看现在会发生什么。

Git通过查找合并基础开始与之前相同:分支masterfeature加入的点。这又是B的提交。

现在Git将两个分支提示区分开来。这一次,master的提示是H,因此两个差异是:

git diff B H
git diff B G

Git现在转到合并这些更改。这一次,我们更改了READMEfoo.pydoc.txtmain.py。 (请记住,这些是我们通过组合所有内容而得到的更改。)同时,他们(在feature中)以与我们相同的方式更改foo.py,以与我们相同的方式更改doc.txt,并以与我们相同的方式更改main.py

因此,Git采取了我们所有的改变,而不是他们的改变。结果完全匹配提交H 。 Git现在停止使用与以前相同的消息。

这一次,当我们跑:

git commit

要完成某些事情,Git会将我们的索引(我们已经提交的提交内容)与我们的HEAD提交进行比较,并发现这些完全是100%完全相同的。 我们已经完成了feature的所有工作。 Git说&#34;什么都没有提交&#34;还有&#34;工作树清洁&#34;因为没有提交,工作树与索引匹配。

可能性较小

另一种方式我们可以在这里得到相同的效果,而不首先进行压缩提交H,如果提交系列E-F-G&#34;撤消自身&#34;这无关紧要。例如,假设Ffoo.py的匹配更改(它可能是提交C的副本),但提交G是提交的恢复{ {1}}。现在,我们不是触及Edoc.txt,而是main.pyB 的更改总和包含在我们的原始G中到 - B更改。 D已提交合并,但再次对最终的源树没有影响。我们的索引和工作树将匹配提交git merge --squash,而G根本不会进行新提交git commit

在&#34;提交差异&#34;这是与以前相同的情况:无论如何变化,如果有的话,在另一个分支上引入,我们已经有了。但是这次我们没有通过挤压合并来获得它:我们还是已经拥有它了。

答案 1 :(得分:0)

如果你想要压缩提交,请转到HEAD(最后)提交,然后只需:

git reset --soft HEAD~2 && git commit

输入此命令后,系统会要求您将提交消息写入新提交 此命令将使用您编写的新提交消息将最后两个提交压缩为一个。

然后合并你的分支如何描述here