3

我正在尝试压缩我的提交并将我的分支合并到 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

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

4

2 回答 2

2

我并不完全清楚你正在合并的提交是什么,因此你为什么会得到这个结果。您可以通过以下方式解决第一个问题(因为我没有提交,所以对我没有太大帮助)

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的)。这里的合并基础提交是 commit B:它是提交链,从两者同时开始master并向feature后工作(在此图中向左),首先聚集在一起。B换句话说,Commitbranchmaster branch上的最新提交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 应该只复制一份该更改。例如,如果我们对on进行了相同的更改,我们毕竟不需要它们的更改:它已包含在我们的更改中。foo.pymaster

假设我们改变README了,我们和他们都修复了相同的东西foo.py,但他们也改变了doc.txtmain.py。所以我们的最后一组更改是保留我们添加的行 in README,保留我们的foo.py更改,并获取doc.txtmain.py更改。效果是 Git 将所有这些应用到合并基础提交的内容B这为我们提供了新提交的内容H (注意其中的内容,H因为它可能会再次困扰我们。)Git 将索引(下一次提交的位置)和工作树(我们可以看到将要提交或已提交的内容)更新到这个新内容,准备提交。

现在常规与壁球合并突然变得很重要,因为如果 Git 要进行常规合并提交,它将执行以下操作:

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

这个新的合并提交 H,它将提交中完成的C-D所有工作与提交中完成的所有工作结合在一起,将同时E-F-G指向提交,即 的前一个提示,并指向提交,即 的前一个且仍然是当前的提示。DmasterGfeature

但是,如果 Git 要进行squash提交——好吧,它会在说:

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

假设这一切都按照它应该的方式工作,我们实际上是 make commit H。这引起了我认为最有可能的情况。

可能的情况

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

Git 和以前一样开始,通过找到合并基础:分支masterfeature连接点。这B又是 commit 。

现在 Git 区分了两个分支提示。master这一次,是的尖端H,所以两个差异是:

git diff B H
git diff B G

Git 现在去结合这些变化。这一次,我们改变了READMEfoo.pydoc.txtmain.py。(请记住,这些是我们所说的通过合并所有内容而得到的变化。)同时,它们(在 中featurefoo.py以与我们相同的方式进行了更改doc.txt,以与我们相同的方式进行了更改,并main.py以与我们相同的方式进行了更改。

因此,Git 接受了我们所有的更改,而不是他们的。结果与 commitH完全匹配。Git 现在停止并显示与以前相同的消息。

这一次,当我们运行时:

git commit

为了完成任务,Git 将我们的索引(我们为提交暂存的内容)与我们的HEAD提交进行比较,发现它们完全、完全、100% 相同。 我们已经完成了所有的工作feature Git 说“没有什么要提交”和“工作树干净”,因为没有什么要提交并且工作树与索引匹配。

不太可能的可能性

我们可以在这里获得相同效果的另一种方法H是,如果提交系列E-F-G“撤消自身”足够多,这并不重要。例如,假设F是匹配的更改foo.py(它可能是 commit 的副本C),但 commitG是 commit 的恢复E。现在不再触摸doc.txtand main.py,从Bto的变化G 总和包含在我们原来的B-to-D变化中。已提交合并,但同样对最终的源树git merge --squash没有影响。我们的索引和工作树将匹配提交并且根本不会进行新的提交。Ggit commitH

就“提交差异”而言,这与以前的情况相同:在另一个分支上引入的任何更改(如果有),我们已经有了。但是这一次我们没有通过 squash-merging 得到它:反正我们已经有了它。

于 2017-05-19T08:37:46.697 回答
0

如果您想压缩提交,请转到 HEAD(last) 提交,然后:

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

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

然后合并你的分支,这里是如何描述的。

于 2017-05-17T10:00:31.720 回答