合并在不同的分支上提交

时间:2017-02-13 08:57:33

标签: git

最好用一个例子来解释:

git init
touch a # create the file "a"
git add a && git commit -m "a"
git checkout -b test # create and checkout the branch "test" 
touch t
git add t && git commit -m "t"
git checkout master
touch b 
git add b && git commit -m "b"
git checkout test 
git merge master # when I do the merge the editor pops up asking for a commit message with something like "merge with master" as the default, and this commit is the problem

现在问题是,我希望“test”的提交历史记录有三个提交,这些提交在这里由它们的消息表示(与git log的顺序相同):

  

- b
   - t
   - 一个

但我得到了:

  

- 与主人合并    - t
   - b
   - 一个

有趣的是,[ b ]和[与主合并]提交与之前的提交具有相同的 diff 。更有趣的是, HEAD^实际上指向 [t] 的“test” HEAD^^指向<在“测试”中强> [a] 我想知道为什么会发生这种情况以及如何避免[与主合并]提交。 另请参阅Update-2。
我应该注意,如果我不在分支“test”上执行[ t ]提交,这将不会发生,即:我将在合并后的历史记录中获得两次提交:[ a ]和[ b ]。

更新

似乎我无法使用--ff-only选项并获得错误“无法快进”。但为什么会这样(因为没有冲突)?这已在“ckruczek”的评论中得到解决。

更新-2:

我猜这个问题自最初发布以来已经发生了一些变化: 提交[与主合并]和[ b ]都在其中包含创建的“b”,那么它是如何存在的呢?在序列中“播放这些提交”时没有错误?

2 个答案:

答案 0 :(得分:4)

合并提交应该在分支上发生

gitk提供了比git log更好的提交可视化。 合并两个分支时,它们在git log历史记录中的显示顺序无关紧要;重要的是他们来自两个不同的分支。

在您进行合并之前,这里是gitk的屏幕截图:

Before Merge

当您创建提交&#34; t&#34;时,您将从master创建分支分支,其将继续使用名称​​ test 。如果您在测试分支中,则现在将在提交之后添加未来提交&#34; t&#34;。

同时,分支在&#34; a&#34;之上有另一个提交,即提交&#34; b&#34;。当你进行合并时,git做的是它将 test 的所有提交压缩成一个并在&#34; b&#34;之上进行提交,这被称为合并提交,有两个父母 - 每个分支一个。您可以在gitk中观察它们。

这是合并后的屏幕截图:

After Merge

提交&#34; b&#34;和&#34; t&#34;没有任何共同之处,因此合并提交可以安全地创建在&#34; b&#34;之上,没有任何冲突。

所有这一切,你想要的是线性历史。如果是这样,在 test 分支中,执行 rebase 而不是合并:

$ git checkout test #making sure we're in 'test' branch
$ git rebase master

在rebase之后,历史看起来像这样:

Rebase

完全相同的事情;只是它是线性的。

如果你不做&#34; t&#34;提交,然后测试分支指向提交&#34; a&#34;并且 test 中没有任何内容 master ,因此快进合并会发生。这意味着 test 分支指针只是更新为指向与较新的 master 分支相同的提交。

回应OP的最新评论

您在代码中执行的操作已经签出 test 并将 master 合并到其中,这通常与您何时执行相反实践中的合并,因为分支是主要分支。在那种情况下,我会这样做:

$ git checkout master
$ git merge test

看起来像这样:

Actual Merge

这里, master 分支现在指向合并提交,合并提交包含&#34; b&#34;在它。

如果要还原此提交,请执行以下操作:

$ git revert <merge commit id>

没有工作 - 因为合并是在两个分支之间。您必须指定要与合并一起使用的父编号。要恢复&#34; b&#34;中的更改,您必须说&#34;我想恢复主要主分支&#34;,如:

$ git revert -m 1 <merge commit id>

将恢复提交&#34; b&#34;。指定2将恢复测试分支,并提交&#34; t&#34;。

答案 1 :(得分:1)

这是图git merge命令之前的图形:

  * 355aaea b             <-------- master is here
* | 4bfc6f1 t             <-------- test is here
|/  
* fd7cb2e a

如您所见,您的命令创建了与test不同的分支master

这是git log --graph之后git merge显示的内容:

$ git log --graph
*   be820db Merge branch 'master' into test
|\  
| * 355aaea b
* | 4bfc6f1 t
|/  
* fd7cb2e a

分支master仍指向355aaea(合并仅影响当前分支),test已移至新提交(be820db)。

合并不同的分支需要创建一个具有两个父项的新提交(be820db):4bfc6f1(当前由t指向)和355aaea(当前指向)在master)。 4bfc6f1是第一个父级,因为当test命令出现时git merge是当前分支。其他父项是git merge命令中指定的分支,按命令行中指定的顺序排列。

只有当前分支是您要分支的合并的祖先时才可以进行快速转发。例如,给定存储库的当前状态,以下命令会产生“快进”合并:

$ git branch new fd7cb2e
$ git checkout new
$ git merge test

“快进”合并是可能的,因为合并的分支(test)包含不在当前分支(new)中的提交,但当前分支不包含不是的提交在合并的分支中。在这种情况下,不需要新的提交,因为它不会产生任何新的提示。 “快进”表示当前分支向前移动,直到达到合并提交为止。