1

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

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

4

1 回答 1

2

虽然git notes实际上通过提交某些东西来工作,但附加到git notes提交的作者和/或提交者名称不被认为是有用的,因此不可用。这有一些很好的理由。

让我们快速浏览一个有注释的存储库。在这里,我将使用 GitHub 上的 freebsd 存储库,因为它有refs/notes/commits(我已经映射到 $reasons 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,因此注释会显示在此处。)在这种情况下——这是典型的——注释本身的作者和提交者与注释所附加的提交的作者和提交者相同。

但是,如果我们仔细观察 object 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]

如果我们查看,我们会发现另外 253 个名为, , , ... 的598b9e08b0138536da55f5ef55868b2a3a607194子树。最上面的一个是: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真正的提交(例如1306ece6bde0e4291eaf08139085990e5f55a622(的当前提示))的作用是refs/heads/stable/10查看提交af51c6d65d574faa11ab8026398e045e5f584040以查看它是否具有名称为 的文件1306ece6bde0e4291eaf08139085990e5f55a622,或者其目录名称以13. 如果找到一个目录,它会检查其中是否存在名称以 . 开头的文件06ece6bde0e4291eaf08139085990e5f55a622或名称以 . 开头的目录06。如果它找到一个目录,它会剥离接下来的两个字符,依此类推。最终,它要么找到该文件,要么没有。

如果 Git确实找到了名称与提交的哈希匹配的文件,则该文件包含该提交的注释。

如果 Git没有找到这样的文件,则没有该提交的注释。

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

像这样替换注释是我们可以为原始提交附带的注释获取不同1306ec...作者和提交者的一种方式。

但是让我们看一下较早的提交。下一个提交stable/108f2e6e2e028ef61fd105967432ff2838153110f7. 我们通过查看提交到哪些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

这就是 commit 的注释8f2e74c5...。但是我们查看的地方的作者和提交者 - <code>refs/notes/origin/commits aka af51c6...- 是 hselasky,而作者和提交者8f2e6e2e028ef61fd105967432ff2838153110f7是 avos。

要找到最近更改注释的人的作者和提交者8f2e6e2e028ef61fd105967432ff2838153110f7,我们必须从顶级refs/notes/origin/commits提交开始,看看谁触及了名称看起来像这样的文件。这个名字本身实际上是,目前,8f/2e/6e2e...; 但在更早的时候,名称应该是8f/2e6e2e...,并且随着存储库的不断增长,名称会在某个时候突然更改为8f/2e/6e/2e.... 所以我们需要一个工具,它不仅知道时髦的 hash-ID-as-file-name 事物,而且还知道拆分为包含包含文件的子目录的目录会随着时间的推移而演变。这使得很难找到笔记何时更改(如果有的话)。

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

于 2017-08-14T14:06:10.860 回答