0

我正在尝试合并两个分支

alpha_critical

gamme_mine

gamme_mine 是我的,需要 alpha_critical 的所有内容

当我做

git difftool f78606e3c60 94482fe3610

它显示了来自不同分支的这两个提交中不同的所有文件。然而

1 当我使用 difftool 保存并关闭文件时,更改会丢失

2 我考虑过使用mergetool,但是当我这样做时

git mergetool f78606e3c60 94482fe3610

它说

No files need merging

最终,我只想比较这两个分支中的两个特定文件,并将更改保存在我的分支上,如下所示

git mergetool f78606e3c60:./test_basic.py 94482fe3610:./test_basic.py
4

1 回答 1

1

TL; DR:您运行git mergetool之前无法运行,并且它在中间停止并出现合并冲突。git merge

合并操作涉及三个而不是两个提交,并且通常比仅涉及两个提交的 diff 操作复杂得多。实际上,差异是无状态的:它获取您拥有的内容并比较事物,并向您显示比较的结果。因此,您可以运行git diffgit difftool随时运行。如您所见,您所做的更改git difftool通常不会影响文件:diff 正在对每个文件的副本进行操作,并且在操作完成后副本消失。

合并不是无状态的。合并有一个独特的开始阶段,你和 Git 合作找到三个感兴趣的提交。接下来是一个扩展的中间部分,其中 Git 计算两个差异——一个从合并基础到您当前的提交,一个从合并基础到另一个提交——并尝试组合这两个差异。Git 有时可以自己完成这个阶段。有时,它不能,而且必须停下来寻求帮助。即使 Git可以自行完成此操作,您也可以指示 Git 停止,就好像它无法自行完成合并一样。

无论如何,一旦第二阶段完成,合并就会进入第三阶段,也是最后阶段。这涉及进行新的提交。新提交几乎与任何普通(非合并)提交完全相同,但有一个关键区别:新提交有两个父级,而不是通常的单亲级。

我认为,查看合并如何工作的说明很有帮助。想象一下每个提交都由某个哈希 ID 标识(实际上就是这种情况),每个提交都链接回之前的提交(实际上也是这种情况)。您的两个分支都来自一些常见的提交,如下所示:

          o--o--...--T   <-- alpha_critical
         /
...--o--B
         \
          o--...--o--H   <-- gamma_mine

每轮o代表一些提交,其中包含每个文件的一些快照。较新的提交出现在右侧。常见的共享提交是标记为B(用于 Base)的提交。由于此提交在两个分支上,并且只是一次提交,因此这里的每个文件在两个分支中都是相同的。因此,如果我们将 commitB与 commit T( --theirs) 进行比较,无论有什么不同——无论 diff 会显示什么——都必须是他们所做的更改。如果我们将 commitB与 commit H(--oursHEAD) 进行比较,那么任何不同之处都必须是所做的更改。

Git 的工作就是将这些差异结合起来。在 Git 可以自行执行此操作的范围内,它会将组合的差异应用于来自 commit 的快照B。如果不能,它将记录合并冲突

git mergetool命令不会启动或执行合并。相反,它从 Git 放弃合并冲突的那一点开始。

假设某个名为的文件main.py出现在提交B(base)、H(yours) 和T(theirs) 中,但它在 yours 和 theirs 中都发生了更改,其中一项更改是更改了使用消息。不幸的是,他们更改使用消息的方式与您更改使用消息的方式不同。因此,Git 无法将您的更改和他们的更改结合起来。

如果您要查看main.py工作树中的副本,该副本中将包含冲突标记,显示您的更改(来自H)及其更改(来自T)。如果您设置merge.conflictStylediff3,该文件还将显示该文件版本中冲突行的样子B

要做git mergetool的是找出文件的三个输入版本:来自 commitB的一个、来自 commit 的一个H和来自 commit 的一个T。(这些不在工作树中,但很容易用于git mergetool。)然后它将在这三个文件以及工作树副本上调用您选择的合并工具。您的工作是更新工作树副本,使其包含正确的合并分辨率,无论是什么。

mergetool 命令对每个冲突的文件重复此操作。退出合并工具后,它会将文件标记为已正确解析(尽管存在各种安全检查,因为并非每个工具都正确报告此信息)。当没有剩余的冲突文件时,mergetool 命令停止。它只能在存在冲突文件时使用。

因此,要进行合并,您必须:

  1. run git merge--no-commit如果你想检查结果,即使 Git 认为 Git 做对了;
  2. 完成 Git 留下的任何有冲突的合并,并将它们标记为已解决:您可以手动执行此操作,也可以使用git mergetool; 和
  3. 如果合并在第 1 步后停止,请使用git merge --continue(或git commit) 告诉 Git 完成合并。您还需要提供合并提交消息,就像您提供任何提交消息一样,尽管您可以使用git merge自行构建的(相对低质量的)默认值(大多数人都这样做)。

如果在第 1 步之后合并没有停止,除非您使用--no-commit.

合并完成后,您将得到以下结果:

          o--o--...--T   <-- alpha_critical
         /            \
...--o--B              M   <-- gamma_mine (HEAD)
         \            /
          o--...--o--H

其中新的合并提交M将旧的提示提交提交H作为其第一个父项,并将提交T(来自他们的分支)作为其第二个父项。您的分支名称现在指向新的合并提交。

于 2020-06-25T00:29:40.043 回答