我想获取目录树的“活动” git 提交的快照,这意味着 git 提交确实是构建的一部分,而不是已被新提交完全取代的提交。
我可以通过git blame
在每个文件上运行并以这种方式提取提交来做到这一点,但是在大型 repo 上它太慢了,不实用。
什么git blame
几乎是找到您正在寻找的信息的唯一方法。但是,您可以稍微简化操作,这对于您的目的可能已经足够了,也许也足够快。
请记住,每个提交都有每个文件的完整快照。分支名称标识某个提交链中的最后一个提交。所以当你有:
... <-F <-G <-H <-- branch
该名称branch
包含 commit 的原始哈希 ID H
。在 commitH
中有很多文件,每个文件都有很多行。这些文件是它们在 commit 中的形式H
,仅此而已——<em>除了 commitH
包含较早 commit 的哈希 ID G
。
您可以使用哈希 ID 来定位提交G
并提取其所有文件,并且当 in 中的文件与 inG
中的文件完全匹配时H
,这意味着 -git blame
至少就 - 文件中的所有行都G
可归因于G
,如果不是一些较早的提交。因此,不同的文件应归于. 该命令逐行工作,如果它们不同,则将各个行归因于要提交,但也许出于您的目的,将整个文件归因于就足够了。G
H
H
git blame
H
H
如果您决定该文件应该归于提交G
,现在是时候F
从提交中提取提交的哈希 ID G
,并使用它来读取提交中的所有文件F
。如果 中的任何给定文件F
与 中的副本匹配G
,则归属移回F
;否则它保持在G
。
您必须重复此过程,直到您完全用完提交:
A <-B <-C ... <-H
由于 commit没有父级,因此在最后一次A
提交中一直未更改的任何文件都将归因于 commit 。但是,一旦您将所有存在的文件完全归因于链中稍后的某个提交,您就可以停止向后遍历。将此与 比较,只要至少有一行归因于某个较早的提交,它就必须继续向后看:您可能会在must 之前很久就停止。A
A
H
git blame
git blame
此外,由于 Git 的内部数据结构,可以非常快速地判断某个较早提交中的文件是否与稍后提交中的同名文件完全匹配:每次提交中的每个文件都由哈希 ID 表示。如果哈希 ID 相同,则文件的内容在两次提交中是逐位相同的。如果不是,他们不是。
没有方便的 in-Git 命令可以准确地执行您想要的操作,1如果您确实打算像这样遍历历史记录,您必须决定如何处理合并。请记住,合并提交有一个快照,但与非合并不同的是,它有两个或多个父级:
...--o--K
\
M--o--o--...--o <-- last
/
...--o--L
如果 in 中的文件与and/orM
中的一个或多个文件匹配,您应该遵循哪个提交?该命令有它自己的方法——<code>git log <start-point>——<path> 将通过跟随一个父级来简化历史,该父级是从一组父级中随机选择的,它具有相同的哈希 ID给定的文件。K
L
git log
请注意,您可以使用git rev-list
(也许与 一起--parents
)来生成您可以选择检查的散列 ID 集。rev-list 命令是大多数其他 Git 命令的主力,包括git blame
它自己,用于跟踪这样的历史。(注意:该git log
命令是从与 相同的源构建的git rev-list
,有一些小的命令行选项差异和不同的默认输出。)
1虽然在git log <start-point> -- <path>
这里很有用,但为每个路径运行一次会太慢,并且在不给出单独路径的情况下运行它是无效的。