获取提交的所有注释,包括作者和提交者

时间:2017-08-14 10:45:10

标签: git git-commit git-notes

是否有一种简单的方法可以检索某个提交的所有注释,包括有关注释作者和注释提交者的信息?

使用git show --notes=refs/notes/* <commit_hash>我能够获得所有笔记。但是我没有找到如何使用管道命令获取笔记的作者和提交者。

1 个答案:

答案 0 :(得分:2)

虽然git notes实际上通过提交某些内容而起作用,但附加到git notes提交的作者和/或提交者名称不被认为有用,因此无法使用。这有一些很好的理由。

让我们快速浏览一下有备注的存储库。在这里,我将使用GitHub上的freebsd存储库,因为它有refs/notes/commits(由于$ $我已映射到refs/notes/origin/commits)。目前,我们有:

$ git rev-parse refs/notes/origin/commits
af51c6d65d574faa11ab8026398e045e5f584040
$ git show af51c6d65d574faa11ab8026398e045e5f584040 | sed 's/@/ /'
commit af51c6d65d574faa11ab8026398e045e5f584040
Author: hselasky <hselasky FreeBSD.org>
Date:   Mon Aug 14 12:59:14 2017 +0000

    Adding Git note for current refs/heads/stable/10

diff --git a/13/06/ece6bde0e4291eaf08139085990e5f55a622 b/13/06/ece6bde0e4291eaf08139085990e5f55a622
new file mode 100644
index 000000000000..3d1ba58d02fa
--- /dev/null
+++ b/13/06/ece6bde0e4291eaf08139085990e5f55a622
 @ -0,0 +1 @@
+svn path=/stable/10/; revision=322500

查看此提交中发生了什么:它添加了一个名为13/06/ece6bde0e4291eaf08139085990e5f55a622的文件。此文件包含ID为1306ece6bde0e4291eaf08139085990e5f55a622的对象的注释:

$ git show --decorate 1306ece6bde0e4291eaf08139085990e5f55a622 | sed 's/@/ /'
commit 1306ece6bde0e4291eaf08139085990e5f55a622 (origin/stable/10)
Author: hselasky <hselasky FreeBSD.org>
Date:   Mon Aug 14 12:59:14 2017 +0000

    MFC r314878:
    Add support for constant pointer constructs to READ_ONCE() in the
    LinuxKPI. When the type of the argument is constant the temporary
    variable cannot be assigned after the barrier. Instead assign the
    temporary variable by initialization.

    Approved by:            re (kib)
    Sponsored by:           Mellanox Technologies

Notes (origin/commits):
    svn path=/stable/10/; revision=322500

[diff snipped]

(我已将此存储库配置为使用refs/notes/origin/commits,因此这里会显示注释。)在这种情况下 - 这是典型的 - 注释本身的作者和提交者是相同的作为该笔记所附的提交者的作者和提交者。

但是,如果我们仔细观察对象af51c6d65d574faa11ab8026398e045e5f584040,我们会发现它有许多具有这些奇怪名称的文件:

$ git ls-tree af51c6d65d574faa11ab8026398e045e5f584040
040000 tree 598b9e08b0138536da55f5ef55868b2a3a607194    00
040000 tree 5101bb91ab93102057e242b41e19c55fdf3314e7    01
040000 tree 2105ada31d9191d03b50a7ad5c97471c0b531283    02
040000 tree 3e42537c937f0f36cff65b7b19570d2e301a17d2    03
[and so on for 256 names]

如果我们查看598b9e08b0138536da55f5ef55868b2a3a607194,我们会发现另外253个子树名为000102,....最重要的是:

$ git ls-tree 598b9e08b0138536da55f5ef55868b2a3a607194 | head -1
040000 tree 825029e67b3e99c8c9f36c68c26c57b7f4c2edb4    00

825029e67b3e99c8c9f36c68c26c57b7f4c2edb4本身只有7个条目:

$ git ls-tree 825029e67b3e99c8c9f36c68c26c57b7f4c2edb4
100644 blob 47efcb375199433eaff1932ab03ff51ffbc0f4b2    067319a197c517553b4bd00eeca22fbbb7bb
100644 blob a6aa47f5b27bc95afedb4178da68958d10c0665a    252549bd16445f7a9c45ff41b295a8bc653d
100644 blob b892978bc9120fe06997841b48e6cc05027234db    a5b6354a4d39247d26563c2cf96ea644af63
100644 blob b50a07b6e41e178bc374ab25e860a33560929801    b2ecb7b200786a0a17d90036510a2aa4fa86
100644 blob 5725ea47215dd0697cb4510c53b63c49f6285a1b    d86e693087beab26f4d49d7e3eb86a611efb
100644 blob 86754af5a4c9077db1e0bc52952823b3012278b4    e846eae3e7cb94a93496931c64d69682818f
100644 blob 8798a0048bf97bce373e24f0fb0456544c127406    fe19d1123431f6cbad809f708ab744b4d02c

左侧的名称是文件名:这些是存储在提交的00树的00子树中的文件。因此,这个由hselasky制作的“顶级”笔记提交包含数十万个文件(目前为332,670个),所有文件的名称都是这些时髦的哈希ID,分成目录目录,因此没有一个子目录文件太多了。

git show对真实提交的作用,例如1306ece6bde0e4291eaf08139085990e5f55a622refs/heads/stable/10的当前提示),是查看提交af51c6d65d574faa11ab8026398e045e5f584040以查看它是否有名称为1306ece6bde0e4291eaf08139085990e5f55a622的文件,或其目录​​名以13开头的文件。如果找到目录,则会在其中检查是否存在名称以06ece6bde0e4291eaf08139085990e5f55a622开头的文件或名称以06开头的目录。如果找到一个目录,它会剥离接下来的两个字符,依此类推。最终,它要么找到文件,要么找不到。

如果Git 找到一个名称与提交的哈希匹配的文件,那么该文件包含该提交的注释。

如果Git 没有找到这样的文件,那么该提交没有备注。

现在,可以更新一个音符。更新注释只是意味着我们创建一个新提交,其内容与之前的notes-commit相同,但一个文件除外。假设我们决定更新提交1306ece6bde0e4291eaf08139085990e5f55a622的注释。我们发现它已被放入13/06/ec...,因此我们将notes-commit af51c6d6...提取到树中,编辑文件13/06/ec...,更改注释,编写文件,然后编写新提交其父提交为af51c6d6...。我们将这个新提交的新哈希填充到refs/notes/origin/commitsrefs/notes/commits ...现在我们已经替换了该注释。

替换这样的注释是我们可以获得与原始提交1306ec...一致的注释的不同作者和提交者的一种方式。

但是让我们来看看早先的提交。 stable/10上的下一次提交是8f2e6e2e028ef61fd105967432ff2838153110f7。我们通过查看refs/notes/origin/commits点的提交来找到它的注释:再次af51c6...。它有一个名为8f的目录吗?为什么是,确实如此。该目录是否有名为2e的子目录?果然,确实如此。那有一个名为6e2e...的文件吗?

$ git rev-parse refs/notes/origin/commits:8f/2e/6e2e028ef61fd105967432ff2838153110f7
46fa8873ffcf4c9e0d0270b02a3e2abcdf10e31e

确实如此,这是我们可以看到的一个blob:

$ git cat-file -p 46fa8873ffcf4c9e0d0270b02a3e2abcdf10e31e
svn path=/stable/10/; revision=322462

这是提交8f2e74c5...的注释。但是我们所看到的地方的作者和提交者 - refs/notes/origin/commits又名af51c6... - 是hselasky,而8f2e6e2e028ef61fd105967432ff2838153110f7的作者和提交者是avos。

要找到最近更改 8f2e6e2e028ef61fd105967432ff2838153110f7注释的作者和提交者,我们必须从顶级refs/notes/origin/commits提交开始,看看谁触摸了文件这个名字看起来像那样。实际上,名称本身是8f/2e/6e2e...;但是在某些早期,名称将是8f/2e6e2e...,随着存储库的不断增长,名称将在某个时刻突然变为8f/2e/6e/2e...。因此,我们需要一种工具,它不仅能够识别时髦的hash-ID-as-file-name,而且还知道拆分到包含包含文件的子目录的目录中,随着时间的推移而发展。这使得当音符改变时很难找到它,如果有的话。

如果注释从不更改,则第一次将其添加到存储库通常是“创建提交本身时”,因此其作者和提交者将匹配提交的作者和提交者。所以这通常足够好。如果它对你的用例不够好,你将不得不编写自己的工具。