1

是否可以使用 git 命令行工具获取已通过给定提交哈希添加到存储库的所有 git 对象哈希的列表?

我已经尝试使用 git 管道工具将其存档git-diff-tree。也许这是错误的方法。以下是迄今为止我能得到的最好结果。但是(非常长的手册页)文档并没有帮助找出必须如何准确地解释输出。

$ git diff-tree --no-commit-id 2b53d04dbb7cd35d030ddc59b13c0836a87daeb7 
:100644 100644 03f15b592c7d776da37e3d4372c215b14ff8820f 6e0ed0b1ed56e9a35a3be52a9de261c8ffcccae8 M      file1.ts
:100644 100644 b5083bdb9c31005ebd16835a0f49dc848d3f387a 4b7f9e6624a66fec0510d76823303017e224c9d7 M      file2.ts
:100644 100644 368d64862e6aa2a0110f201c8a5193d929e2956d 0e51626a9866a8a3896489f497fbd745a5f4a9f2 M      file3.ts
:040000 040000 c332b1e576af0dbb93cc875106bc06c3de6b74c8 f7f3478a9b0eaac85719699d97e323563a1b102b M      some_folder

第一个和第二个 git 对象 blob 哈希是否分别显示修改文件的旧对象和新对象?在最坏的情况下,我可以通过解析输出来获取该信息。

我的主要目标是找到一个如下工作的命令行:

$ git <command> <option1> <option2> 368d64862e6aa2a0110f201c8a5193d929e2956d 
6e0ed0b1ed56e9a35a3be52a9de261c8ffcccae8 
4b7f9e6624a66fec0510d76823303017e224c9d7 
0e51626a9866a8a3896489f497fbd745a5f4a9f2 

在下面编辑以响应@torek

为了回应@torek 的回答,我想更清楚我的意图是什么,因为他绝对正确地指出新的不一定是新的。

我打算用来git rev-list --reverse <branch>按提交顺序获取该分支上所有提交的列表。然后我想按这个顺序访问每个提交,并在每次提交时收集这个分支上第一次看到的 blob 哈希。

最终结果应该类似于以下内容:

C:368d64862e6aa2a0110f201c8a5193d929e2956d
B:03f15b592c7d776da37e3d4372c215b14ff8820f
B:4b7f9e6624a66fec0510d76823303017e224c9d7
B:c332b1e576af0dbb93cc875106bc06c3de6b74c8
C:5521a02ce1bc4f147d0fa39a178512476764dd66 
B:e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e
B:adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
C:a3db5c13ff90a36963278c6a39e4ee3c22e2a436
B:4888920a568af4ef2d2f4866e75b4061112a39ea
.
.
.

C:提交 B:blob

如果这不容易完成,则可以进行两次通过。由于您指出的原因,在第一遍中,可以在不同的提交中多次提及 blob:

  • 在另一个文件中添加具有相同内容的文件
  • 文件修改后内容相同

然后我可以对文件进行第二次传递,通过该文件awk '!x[$0]++'将删除任何重复项。这不会很有效,但会得到我想要的结果。

我希望我现在表达了我的意图。有什么想法吗?

4

1 回答 1

1

是否可以使用 git 命令行工具获取已通过给定提交哈希添加到存储库的所有 git 对象哈希的列表?

是和/或否:您必须准确定义添加到存储库的含义。

例如,假设我从一个完全空的存储库开始:

$ mkdir foo && cd foo && git init
Initialized empty Git repository in ...

现在我创建它README.mdgit add提交:

$ echo for testing > README.md
$ git add README.md
$ git commit -m initial
[master (root-commit) 19278e9] initial
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

README.md是一个 blob,其哈希 ID 为:

$ git rev-parse HEAD:README.md
43b18adf702be62761e3affd85c4c3ee5c396be7

后来,我写了一个新文件:

$ echo for testing > newfile.txt
$ git add newfile.txt
$ git commit -m 'add new file'
[master 5521a02] add new file
 1 file changed, 1 insertion(+)
 create mode 100644 newfile.txt

如果我们查看此提交,我们将看到新文件。如果我们用以下格式查看它,git show --raw我们会看到它:git diff-tree

$ git show --raw
commit 5521a02ce1bc4f147d0fa39a178512476764dd66 (HEAD -> master)
Author: Chris Torek <chris.torek gmail.com>
Date:   Fri Oct 18 14:10:55 2019 -0700

    add new file

:000000 100644 0000000 43b18ad A        newfile.txt

这似乎是一个已添加到存储库中的 blob,但是等等,有一些非常熟悉的东西43b18ad

$ git rev-parse HEAD:newfile.txt
43b18adf702be62761e3affd85c4c3ee5c396be7

是的,这与以下哈希 ID相同README.md

$ git ls-tree -r HEAD
100644 blob 43b18adf702be62761e3affd85c4c3ee5c396be7    README.md
100644 blob 43b18adf702be62761e3affd85c4c3ee5c396be7    newfile.txt

这是一个 blob,但有两个文件。真的是新加的吗?

如果您对上述问题的回答是“是的,它是新的,即使它很旧”,那可能会回答第二个问题。如果您的回答是“不,它不是新的”,那么重新引入在先前提交中删除的 blob 的提交呢?或者,如果两个提交IJ在两个分支上并行进行:

          I   <-- br1
         /
...--G--H
         \
          J   <-- br2

两者都引入了相同的blob,哪一个实际上将它添加为全新的,而哪一个只是复制另一个?

一般来说,如果您想要全新的,则必须遍历整个提交图,检查每个提交的树(请参阅 参考资料git ls-tree -r),并选择哪些提交首先引入了之前尚未出现的 blob 对象 ID(父级和/或日期和时间)提交对象。如果您想“在此提交中新添加为新文件”,请检查提交及其父级,可能使用git diff-tree或类似。请注意,全新文件在其父文件中具有全零模式,并且状态字母为A(add),而从其父文件修改的文件具有状态字母M(modified) 和两个非零哈希。名义上已删除的文件 - 存在于父级中但不再存在于子级中的文件 - 具有状态字母D(已删除)。如果启用重命名检测,您将获得Rstatus-es 和相似性索引值;您可能想要禁用此功能,或者至少将相似性测试强制为 100%。

于 2019-10-18T21:48:32.413 回答