Setup and Config
Getting and Creating Projects
Basic Snapshotting
Branching and Merging
Sharing and Updating Projects
Inspection and Comparison
Patching
Debugging
External Systems
Server Admin
Guides
- gitattributes
- Command-line interface conventions
- Everyday Git
- Frequently Asked Questions (FAQ)
- Glossary
- Hooks
- gitignore
- gitmodules
- Revisions
- Submodules
- Tutorial
- Workflows
- All guides...
Administration
Plumbing Commands
- 2.43.1 → 2.47.0 no changes
- 2.43.0 11/20/23
- 2.39.1 → 2.42.3 no changes
- 2.39.0 12/12/22
- 2.24.1 → 2.38.5 no changes
- 2.24.0 11/04/19
- 2.23.1 → 2.23.4 no changes
- 2.23.0 08/16/19
- 2.19.3 → 2.22.5 no changes
- 2.19.2 11/21/18
- 2.16.6 → 2.19.1 no changes
- 2.15.4 12/06/19
- 2.11.4 → 2.14.6 no changes
- 2.10.5 09/22/17
- 2.1.4 → 2.9.5 no changes
- 2.0.5 12/17/14
概述
git merge-base [-a | --all] <提交> <提交>… git merge-base [-a | --all] --octopus <提交>… git merge-base --is-ancestor <提交> <提交> git merge-base --independent <提交>… git merge-base --fork-point <引用> [<提交>]
描述
git merge-base 会找出两个提交之间的最佳共同祖先,用于三方合并。 如果一个公共祖先是另一个公共祖先的祖先,那么后者就比前者 “更好”。 没有更好的共同祖先的共同祖先就是 “最佳共同祖先”,即 “合并基础”。 请注意,一对提交可以有多个合并基础。
运行模式
在最常见的特殊情况下,在命令行中只指定两个提交,意味着要计算给定的两个提交之间的合并基数。
一般来说,在计算合并基础的两个提交中,一个由命令行上的第一个提交参数指定;另一个提交是一个(可能是假设的)提交,是命令行上所有剩余提交的合并。
因此,如果指定了两个以上的提交,‘合并基础’ 并不一定包含在每个提交参数中。当使用 --merge-base
选项的时候,这不同于 git-show-branch[1]。
- --octopus
-
计算所有提交的最佳公共祖先,为 n 次合并做准备。 这模仿了 git show-branch --merge-base 的行为。
- --independent
-
与其打印合并库,不如打印所提供的具有相同祖先的提交的最小子集。 换句话说,在给出的提交中,列出那些无法从其他提交到达的提交。 这模仿了 git show-branch—independent 的行为。
- --is-ancestor
-
检查第一个 <提交> 是否是第二个 <提交> 的祖先,如果是,则以状态 0 退出;如果不是,则以状态 1 退出。 如果状态不是 0,则表示出错。
- --fork-point
-
查找一个分支(或导致 <提交> 的任何历史)从另一个分支(或任何引用)<引用> 分支出去的时间点。这不仅仅是查找两个提交的共同祖先,而且还要考虑 <引用> 的引用日志,以查看导致 <提交> 的历史是否从分支 <引用> 的早期化身分叉而来(请参阅下文对该模式的讨论)。
讨论
给定两个提交 A 和 B,git merge-base A B
会输出一个通过父级关系从 A 和 B 都能到达的提交。
例如,采用这种拓扑结构:
o---o---o---B / ---o---1---o---o---o---A
A 和 B 之间的合并基数为 1。
给定三个提交 A 、B 和 C, git merge-base A B C
会计算 A 和假设提交 M 之间的合并基础,M 是 B 和 C 之间的合并。 例如这个拓扑:
o---o---o---o---C / / o---o---o---B / / ---2---1---o---o---o---A
git merge-base A B C
的结果是 1。 这是因为 B 和 C 之间有一个合并提交 M 的等效拓扑结构是:
o---o---o---o---o / \ / o---o---o---o---M / / ---2---1---o---o---o---A
和 git merge-base A M
的结果是 1 。 提交 2 也是 A 和 M 的共同祖先,但 1 是更好的共同祖先,因为 2 是 1 的祖先。 因此,2 不是合并基础。
git merge-base --octopus A B C
的结果是 2 ,因为 2 是所有提交的最佳共同祖先。
当历史涉及交叉合并时,两个提交的 ‘最佳’ 共同祖先可能不止一个。 例如这个拓扑:
---1---o---A \ / X / \ ---2---o---o---B
1 和 2 都是 A 和 B 的合并基础。 如果没有给出 --all
选项,则不会指定输出哪个是最好的。
检查两个提交 A 和 B 之间的 “快进性” 的一个常见习语是(或至少曾经是)计算 A 和 B 之间的合并基数,并检查它是否与 A 相同,在这种情况下,A 就是 B 的祖先。
A=$(git rev-parse --verify A) if test "$A" = "$(git merge-base A B)" then ... A 是 B 的一个祖先 ... fi
在现代 Git 中,可以用更直接的方式来表达:
if git merge-base --is-ancestor A B then ... A 是 B 的一个祖先 ... fi
代替。
关于叉点模式的讨论
在使用 git switch -c topic origin/master
创建的 topic
分支上工作后,远程跟踪分支 origin/master
的历史可能会被倒带和重建,从而导致出现这种形状的历史:
o---B2 / ---o---o---B1--o---o---o---B (origin/master) \ B0 \ D0---D1---D (topic)
其中,origin/master
曾指向 B0、B1 和 B2 提交,现在则指向 B,而您的 topic
分支是在 origin/master
指向 B0 时在其上创建的,您在其上创建了 D0、D1 和 D 三个提交。 想象一下,你现在想在更新后的 origin/master 分支上重建你在主题上所做的工作。
在这种情况下,git merge-base origin/master topic
会返回上图中 B0 的父提交,但 B0^..D 并 不是 你想在 B 上重放的提交范围(它包括 B0,而 B0 并不是你写的内容;它是另一个提交从 B0 移到 B1 时丢弃的提交)。
git merge-base --fork-point origin/master topic
就是为这种情况而设计的。 它不仅会考虑 B,还会考虑 B0、B1 和 B2(即仓库的引用日志所知道的远程跟踪分支的旧提示),以查看你的特性分支是在哪个提交上建立的,并找到 B0,从而只重放你的特性上的提交,而不包括对方后来丢弃的提交。
因此
$ fork_point=$(git merge-base --fork-point origin/master topic)
会发现 B0,而
$ git rebase --onto origin/master $fork_point topic
将在 B 的基础上重放 D0、D1 和 D,以创建该形状的新历史:
o---B2 / ---o---o---B1--o---o---o---B (origin/master) \ \ B0 D0'--D1'--D' (topic - updated) \ D0---D1---D (topic - old)
需要注意的是,仓库中较早的引用日志条目可能会被 git gc
过期。 如果 B0 不再出现在远程跟踪分支 origin/master
的引用日志中,--fork-point
模式显然就找不到它,并会失败,从而避免给出一个随机而无用的结果(例如 B0 的父分支,就像不使用 --fork-point
选项的同一命令给出的结果一样)。
另外,使用 --fork-point
(分叉点)"模式的远程跟踪分支必须是你的主题从其顶点分叉出来的分支。 如果你从比顶端更早的提交中分叉,该模式将无法找到分叉点(想象一下,在上面的示例历史中,B0 并不存在,origin/master 从 B1 开始,移动到 B2,然后是 B,而你在 origin/master^ 分叉你的主题时,origin/master 是 B1;B1 的父提交会被 git merge-base origin/master topic
正确找到,但在 `-fork-point`模式下不会,因为它不是 origin/master 最前沿的提交之一)。
GIT
属于 git[1] 文档