您的根本错误在于认为git merge 有两个 输入——您的分支和其他一些分支。情况并非如此:它有 三个 输入,其中没有一个是 分支。三个输入是提交。
让我们画一些提交,以及记住每个分支中的 last 提交的分支名称:
o--o--A <-- branch-A
/
...--o--*
\
o--o--B <-- branch-B
如果你运行git checkout branch-A,你得到的是commit A,因为名称branch-A 指向那个特定的提交。 git checkout branch-B 也是如此。比较这两个提交显示了某些文件中的一些差异。这确实很重要,但没那么重要。
从提交A,我们可以向后工作(就像git log 那样)到一个未命名的提交,然后是另一个未命名的提交,然后提交*。从B,我们可以做同样的事情,如果我们这样做,我们也会到达提交*。因此,提交*——提议的合并操作的合并基础——是最佳公共提交,即两个 分支上的最佳提交。
合并的工作方式是运行两个 git diffs:
- 第一个将提交
* 中的快照与提交 A 中的快照进行比较,以查看某人在该路径上所做的更改。
- 第二个将提交
* 中的快照与提交 B 中的快照进行比较,以查看某人在该路径上进行了哪些更改。
然后 Git 结合这两组变化。如果没有冲突,则生成的组合更改将应用到快照来自提交 *。
将这两组更改组合并正确应用它们——或尽可能正确地应用 Git 可以确定——Git 继续进行新的提交,主要以通常的方式。新提交会导致您签出的任何一个分支(两个分支-A 或分支-B 名称之一)更新以指向新提交。新提交有 两个 父提交,它们是提交 A 和 B。所以最终的结果是:
o--o--A
/ \
...--o--* M <-- branch-<whichever> (HEAD)
\ /
o--o--B
无论哪个分支名称没有移动,仍然指向A 或B。
新合并提交M 中的快照 是来自* 的快照,加上两组更改。如果A 没有从* 更改某些内容,但B 确实从* 更改了某些内容,那么您将得到B 的更改。如果A 确实改变了一些东西而B 没有改变,那么你会得到A 的改变。如果两者都更改了 same 文件的 same 行,那么您会遇到合并冲突 — 您必须完成合并作业并生成 @ 987654354@你自己。
(如果文件C 在A 和B 之一中,但不在另一个中,则文件C 必须要么已创建-since-* 要么已删除-since-* . Merge 通过获取新文件将 create new file 与 nothing 结合。它通过以下方式将 remove old files 与 nothing 结合删除旧文件。根据您的文本描述,C 必须退出 *,为您提供 删除文件 操作。)