【问题标题】:How to find all the "active" git commits in a tree?如何在树中找到所有“活动”的 git 提交?
【发布时间】:2020-11-23 04:14:25
【问题描述】:

我想获取目录树的“活动”git 提交的快照,这意味着 git 提交确实是构建的一部分,而不是已被新提交完全取代的提交。

我可以通过在每个文件上运行 git blame 并以这种方式提取提交来做到这一点,但是对于大型 repo 来说太慢了。

【问题讨论】:

  • 您这样做的目的是什么?也许有更好的方法。
  • 这是为了回答“我的提交在哪里?”这个问题。当您有很多应用程序的分支和部署时。我正在将提交加载到数据仓库中以进行交叉引用。
  • “我的提交在哪里”是什么意思? git branch --contains可以解决这个问题吗?
  • 它似乎显示提交是否在分支中,但如果它被另一个提交取代则不显示。
  • @CCS 知道提交的行是否在代码中仍未修改的目的是什么?如果它们被后续提交进行了微不足道的更改,例如样式更改,该怎么办?

标签: git git-log git-blame


【解决方案1】:

git blame 所做的几乎是找到所需信息的唯一方法。但是,您可以稍微简化操作,这对于您的目的可能已经足够了,也许也足够快。

请记住,每个提交都有每个文件的完整快照。分支名称标识某些提交链中的 last 提交。所以当你有:

... <-F <-G <-H   <-- branch

名称branch 包含提交H 的原始哈希ID。在提交H 中,有很多文件,每个文件都有很多行。这些文件的形式是它们在提交 H 中的形式,仅此而已 - 除了提交 H 包含先前提交 G 的哈希 ID。

您可以使用哈希 ID this 来定位提交 G 并提取所有 its 文件,当 G 中的文件与 H 中的文件完全匹配时,这意味着——至少在git blame 术语中——G 文件中的所有行都归因于G,如果不是早期的提交。因此GH不同 的文件应归于Hgit blame 命令逐行运行,如果它们不同,则将单个 归因于提交 H,但也许出于您的目的,将整个文件归因于 H 就足够了。

如果您决定该文件应该归属于提交G,现在是时候从提交G 中提取提交F 的哈希ID,并使用它来读取提交@ 中的所有文件987654344@。如果F 中的任何给定文件与G 中的副本匹配,则归属移回F;否则它会保留在G

你必须重复这个过程,直到你完全用完提交:

A <-B <-C ... <-H

由于提交 Ano 父级,A 中的任何文件在 last 提交期间一直未更改,都将归因于提交 @987654352 @。但是,一旦您将 H 中存在的所有文件完全归因于链中稍后的某个提交,您就可以停止向后遍历。将此与 git blame 进行比较,只要至少有一个 归因于某个较早的提交,它就必须继续向后看:您可能会在 git blame 必须之前很久就停下来。

此外,由于 Git 的内部数据结构,可以非常快速地判断某个较早提交中的文件是否与稍后提交中的同名文件完全匹配:每次提交中的每个文件都由哈希 ID 表示。如果哈希 ID 相同,则文件的内容在两次提交中是逐位相同的。如果不是,他们不是。

没有方便的 in-Git 命令可以准确地执行您想要的操作,1 如果您确实打算像这样遍历历史记录,您必须决定如何处理合并。请记住,合并提交有一个快照,但与非合并提交不同的是,它有 两个或更多个父节点:

...--o--K
         \
          M--o--o--...--o   <-- last
         /
...--o--L

如果M 中的文件与K 和/或L 中的一个或多个文件匹配,您应该遵循哪个提交? git log 命令有它自己的方法——git log &lt;start-point&gt; -- &lt;path&gt; 将通过跟随一个父级来简化历史记录,该父级是从一组父级中随机选择的,它与给定文件具有相同的哈希 ID。

请注意,您可以使用git rev-list,也可以使用--parents,来生成您可以选择检查的散列ID 集。 rev-list 命令是大多数其他 Git 命令的主力,包括git blame 本身,用于跟踪这样的历史记录。 (注意:git log 命令与git rev-list 使用相同的源构建,但有一些小的命令行选项差异和不同的默认输出。)


1虽然git log &lt;start-point&gt; -- &lt;path&gt; 在这里很有用,但对每条路径运行一次会太慢,而且在不给出单独路径的情况下运行它是无效的。

【讨论】:

  • 这真的很有帮助,谢谢。所以如果我在关注,这里的优化是通过提交/文件而不是git blame 所做的文件/行来遍历历史记录?
  • @CCS:是的,这就是一般的想法。你必须决定这是否真的符合你想要的结果,但我认为它会。
猜你喜欢
  • 1970-01-01
  • 2014-01-07
  • 2017-05-14
  • 1970-01-01
  • 2011-04-06
  • 2015-11-12
  • 2010-10-31
  • 2014-02-22
  • 2011-08-20
相关资源
最近更新 更多