8

我一直在浏览“git merge-base”手册页,但我无法理解多个合并基础是如何发展的。具体来说,我挂断了手册页中的以下插图:

When the history involves criss-cross merges, there can be more than one best common
ancestor for two commits. For example, with this topology:
  ---1---o---A
      \ /
       X
      / \
  ---2---o---o---B
both 1 and 2 are merge-bases of A and B. Neither one is better than the other (both
are best merge bases). When the --all option is not given, it is unspecified which
best one is output.

我只是无法理解这种情况是如何造成的。我试图使用测试存储库在分支之间重新创建这种纵横交错的合并情况,但我无法复制它。在所有情况下,我总是以 A 和 B 都指向的 1 个合并提交结束(而不是 A 和 B 指向独立的合并提交,如图所示)。

谁能说明这种情况是如何出现的?这是常见情况还是错误情况?

4

4 回答 4

10

我只是无法理解这种情况是如何造成的。我试图使用测试存储库在分支之间重新创建这种纵横交错的合并情况,但我无法复制它。在所有情况下,我总是以 A 和 B 都指向的 1 个合并提交结束(而不是 A 和 B 指向独立的合并提交,如图所示)。

谁能说明这种情况是如何出现的?

交叉合并可以以不同的方式出现。例如,当您有两个分支引用指向同一个合并提交(其中一个分支被签出)并且您运行git commit --amend. 以下玩具示例就是这样做的:

# set things up
cd ~/Desktop
mkdir crisscross
cd crisscross
git init

# make an initial commit
printf "bar\n" > README.md
git add README.md
git commit -m "add README"

# add a line at the top of the file and commit
sed -i '' '1s/^/foo\n/' README.md
git commit -am "add foo line"

# create and checkout a branch pointing at the initial commit
git checkout -b other master^

# add a line at the bottom of the file and commit
printf "baz\n" >> README.md
git commit -am "add baz line"

# do a merge and make both branches point to this merge commit
git merge master
git checkout master
git merge other

在这个阶段,输出git log --graph --oneline --decorate --all

*   30b9175 (HEAD, master, other) Merge branch 'master' into other
|\  
| * f318ead add foo line
* | 31875d9 add baz line
|/  
* 8b313a0 add README

现在修改最后一次提交(有关更多详细信息,请参阅git commit --amend 究竟是如何工作的?):

git commit --amend

之后, 的输出git log --graph --oneline --decorate --all将是

*   69bbcbe (HEAD, master) Amended merge commit
|\  
| | *   30b9175 (other) Merge branch 'master' into other
| | |\  
| |/ /  
|/| /   
| |/    
| * f318ead add foo line
* | 31875d9 add baz line
|/  
* 8b313a0 add README

你去吧:历史现在包含纵横交错的合并。

这是常见情况还是错误情况?

如上所述,可能会出现这种情况。这可能是不可取的,但不应将其视为“错误状态”。

于 2014-10-14T22:06:53.610 回答
3

这是一系列将生成交叉合并的提交。比涉及 的步骤更多--amend,但仅使用基础知识。运行这个脚本,看看你确实得到了一个纵横交错的合并。

#!/bin/sh
# Initialize 
git init .                                                                                                                       
echo date > file.txt; git add file.txt
git commit -m "Initial commit"

# Make branches                                                                                                                     
git branch A; git branch B

# Make change in A                                                                                                                  
git checkout A
echo date > fileA.txt; git add fileA.txt
git commit -m "first commit along branch A"

# Make change in B; add tag for later                                                                                                               
git checkout B
echo date > fileB.txt; git add fileB.txt
git commit -m "first commit along branch B"
git tag "tag-B"

# Merge A into B (still on B)                                                                                                       
git merge --no-edit A; git tag "M"

# Add another commit on B whose parent is M                                                                                         
echo date > fileB2.txt; git add fileB2.txt
git commit -m "second commit along B"

# Switch to A and add a commit; note that
# M is not an ancestor of this commit                                                                          
git checkout A
echo date > fileA2.txt; git add fileA2.txt
git commit -m "second commit along A"

echo "Best common ancestors (before criss-cross):"
# Should be only one
git merge-base --all A B

# Merge the commit tagged "tag-B" 
# into A generating the cris-cross-merge                                                            
git merge --no-edit tag-B

echo "Best common ancestors (after criss-cross):"
# Should be two
git merge-base --all A B
于 2017-04-30T13:26:44.347 回答
2

当其他开发人员从您那里获取提交时,就会发生这种情况,您从他们那里获取,然后在你们都获取之后,你们都将彼此的分支合并到自己的分支。这可能发生,这不是错误状态。

于 2014-10-14T22:16:31.273 回答
1

当历史涉及交叉合并时,两次提交可能有多个最佳共同祖先。例如,使用此拓扑:

---1---o---A
    \ /
     X
    / \
---2---o---o---B

以上来自git网站,我猜它忘记了添加箭头。

让我们看看下面的图片,很明显如何制作一个纵横交错的情况。当分支 A 需要来自分支 B 的一些代码时,它会从分支 B 合并;当分支 B 需要来自分支 A 的一些代码时,它会从分支 A 合并;在这里,我们遇到了纵横交错的情况。

更重要的是,很容易找出分支 A 和分支 B 共享祖先 1 和 2。

在此处输入图像描述

于 2018-11-06T16:20:20.807 回答