【问题标题】:Is there a way to see the timestamp of the changes in a file when running a diff during a merge conflict?在合并冲突期间运行差异时,有没有办法查看文件更改的时间戳?
【发布时间】:2020-08-26 16:23:37
【问题描述】:

有时,我发现自己需要知道何时(如日期和时间)在解决合并冲突时对冲突文件进行了特定更改,以便我可以决定是否要采取一个接一个或编辑文件。

在这些情况下,我在各自分支中的相关文件上使用git blame,并获取我感兴趣的特定更改的日期和时间。这很好用,但我觉得应该有更简单的方法这样做。

有没有人提出更好的方法来实现这一目标?我检查了git 文档,但找不到任何可以简化此过程的内容。不必在git 我很乐意找到替代方法/工具..etc

【问题讨论】:

  • afaik 适用于所有编程编辑器的 Git 插件将为您执行此操作,在 vim 中,我直接从合并工具缓冲区中输入“:Git blame”,这就是全部。
  • git blame 适用于生成的文件。我想查看该文件的所有其他更改的时间戳,包括旧的和新的。本质上类似于git diffgit blame 的组合,其中每个差异也将具有相应的时间戳

标签: git command-line command-line-arguments


【解决方案1】:

没有。没有,因为提交不保存更改,它们保存快照。合并操作只查看三个快照:合并基础提交和两个分支提示提交。

我可以通过在它们各自分支中的这些文件上运行 git blame 来解决它...

至少在 Git 中,这是一个完全不同的操作。 git blame(或git annotate)命令遍历图表,一次一个提交,向后(像往常一样)比较每个父子提交对中的一些文件和行。这会在链中定位一个特定的earlier 提交,其中出现在链中last 提交中的特定行仍然出现在那个较早的提交中。 Blame 实际上对 starting 提交中的每个源代码行执行一次 - 嗯,latest 提交;也许您会称其为 end 而不是 start,但经过优化以使其快速运行。

让我们把它画成一个具体(但简单)的例子——git blame 处理更复杂的情况,包括分支合并子图,但在构建例子时我们会忽略这些。假设我们有以下内容:

          I--J   <-- branch1 (HEAD)
         /
...--G--H
         \
          K--L   <-- branch2

即,您当前的提交是提交J,而您运行git merge branch2。 Git 将自行定位 合并基础 提交 H,并且实际上运行两个 git diffs:

git diff --find-renames <hash-of-H> <hash-of-J>   # what we changed
git diff --find-renames <hash-of-H> <hash-of-L>   # what they changed

Git 现在将尝试合并这两组更改。如果文件 F 出现在所有三个提交中,HJL,但在所有三个提交中不同,则两个单独的差异输出将具有两个差异中 F 的一些更改。这些更改需要组合成一个更改,该更改可以应用于提交H中出现的F副本。

当这些更改重叠(触摸H 中的 F 的同一行)或邻接时(任一方更改的结尾正好位于另一边,再次引用HF的副本),这是一个合并冲突

我认为你想要的是一个工具,因为我们知道H-vs-JH-vs-L 都“触摸”了 中的某些行F,针对适当的行范围运行 git blame -L&lt;range&gt; H^@..Jgit blame -L&lt;range&gt; H^@..L(基于 HF 的副本,分别在 JL 中修改) .如果JLH 中出现这些行的点上方总体上添加或删除了行,则这两个&lt;range&gt; 表达式可能会有所不同。

这两个git blame 将检查提交J,然后是I,然后是H(对于第一种情况)和L,然后是K,然后是H(对于第二种情况)。这些检查几乎是对称的,所以在考虑问题时,我们可以只看一个“侧面”。我们将重复该操作——但可能使用不同的行号,如上所述——另一个。因为存在合并冲突,我们知道有问题的行确实H-vs-J 中发生了变化。因此,他们:

  • H-vs-I 而不是在 I-vs-J 中更改,或者
  • H-vs-I 中没有变化,但I-vs-J 中确实发生了变化,或者
  • 改变了两者 H-vs-I I-vs-J

所以git blame 将为范围内的每一行分配它提交I 或提交J

提交IJ时间戳 并不是这里真正感兴趣的项目。相反,提交哈希很有趣:它们确定哪些提交促成了更改。

最大的复杂性是,对于范围内的每一行,贡献可能来自一个不同的提交。由于git merge 只查看H-vs-J,可能是两行更改:

-first
-second
+1st
+2nd

实际上是在I 中将“first”替换为“1st”,然后在J 中将“second”替换为“2nd”的单行更改。

当合并中的提交范围较大时,如:

          A--B--C--D--...--Y--Z   <-- branch1 (HEAD)
         /
...--o--*
         \
          o--...--o   <-- branch2

从合并基本提交 * 到提交 Z 的差异可能有 30 行“更改”,其中有来自 A-B-...-Z 序列表示的 26 个提交中的 15 个的贡献。因此,您至少可能需要大量信息。

如果你能让git merge 为你运行适当的git blame 可能会很好,但你不能。你可以做的是编写你自己的工具来自动化这个:

  • 假设您知道当前 (HEAD) 提交的合适说明符(它是 HEAD),并且您有一个 other 提交的说明符——在我们的简单示例中为L以上——可用,在冲突合并期间,在名称 MERGE_HEAD 下,您必须找到 merge base 提交哈希。执行此操作的命令是 git merge-base

    有一个复杂性:可能有多个合并基础。使用git merge-base --all 查找所有 合并基(默认情况下git merge 会这样做)。如果有多个,请决定如何处理。 Merge 的默认设置是合并合并基础,将结果作为临时提交提交,其哈希 ID 对您来说是无法访问的。 (如果git merge 在冲突合并期间将这个哈希 ID 保存在某处可能会很好,但事实并非如此。临时提交甚至可能一开始就没有连接到提交图;我没有t 检查。无论哪种方式,它都不可用,因此除非您修改 Git 以使其可用,否则追求这条路径没有真正意义。)除了可能选择所有合并之外,我不知道临时处理这个问题的好方法基地作为git blame 的停止点。

  • 无论如何,找到一个或多个合并基础(并弄清楚在多个基础的情况下该怎么办),您现在可以让您的工具运行git blame。这里的难点在于找到正确的行号。

  • H^@..HEADH^@..MERGE_HEAD 中看起来很神奇的H^@ 语法只是告诉git blame,当它到达H 的任何父提交时,它可以停止查找,这可能会加速其操作。鉴于适当的-L 限制,这可能是不必要的。这可能仍然是一个好主意——事实上,如果git blame 服从--ancestry-path,您可能也想在这里使用--ancestry-path。 (我没有对此进行测试。)这将防止git blame 走下任何可能出现在更复杂图表中的死胡同。

该工具可能会让您保持 git blame 的输出未修改。

【讨论】:

    【解决方案2】:

    要查找对特定文件所做的所有提交,我们可以使用

    git log filename

    我们可以得到两个提交之间文件的所有差异

    git diff commit1 commit2 -- filename

    【讨论】:

      猜你喜欢
      • 2020-10-06
      • 2013-10-22
      • 2021-04-02
      • 2021-04-10
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      相关资源
      最近更新 更多