git:获取commit-id和commit的注释

时间:2013-08-16 12:56:47

标签: git

我正在编写一个用于验证url的钩子,它在git log的notes部分输入。我遍历每个提交以获取该特定提交的注释,并对该URL进行字符串比较。如果提交是新提交,则会弹出问题,因为新提交不包含注释。

例如: -

git add sample
git commit -m "added sample"
git notes add -m "sample note" <commitID-of-sample>
git push origin master
git push origin refs/notes/*

以上示例的问题是,首先我推送提交但是提交没有注释,因为git push origin refs / notes / *在master之后被推送。我基本上想要在预接收挂钩中访问提交的注释。

有什么建议吗?

2 个答案:

答案 0 :(得分:10)

你实际上不能按照你展示的方式做到这一点。问题归结为笔记的工作方式。正如mart1n在评论中建议的那样,您需要先按或同时按下音符。原因如下:

注释如何工作

存在“附加到”提交的注释(因此可以通过git loggit show显示)“现在”如果:

  1. 让我们说这个提交的SHA1(我们试图找到它的注释)是1234567...
  2. refs/notes/commits存在,
  3. 通过refs/notes/commits指向的提交进行阅读,其中有一个文件名与1234567...匹配的“文件”。
  4. 该注释是具有有趣名称的文件的内容。

    让我们探索寻找笔记的过程。

    后台,使用低级“原始”git命令

    大部分仓库的最低级访问命令是git cat-file。这使您可以查看存储库中任何对象的类型(git cat-file -t sha1)和内容(git cat-file -p sha1)。这里的 sha1 部分可以是任何git引用名称,只要它解析为这些40个字符的十六进制SHA-1值之一即可。注释的默认引用名称为refs/notes/commits,并且(如果存在)它应始终指向commit对象。因此:

    $ git cat-file -p refs/notes/commits
    tree 28db2757c2b7c6e4bbfef35e61e8bd7c698626dc
    parent ce97e80bfbdab9bc163ecb93779d071d7ed8c739
    author A U Thor <author@example.example> 1376652910 -0600
    committer A U Thor <author@example.example> 1376652910 -0600
    
    Notes added by 'git notes edit'
    

    我们的下一步是查看此处命名的tree

    $ git cat-file -p 28db2757c2b7c6e4bbfef35e61e8bd7c698626dc
    

    对于一小段笔记,这产生了几乎相同的东西,我们将在下面看到。如果有很多笔记,这会导致更多tree s,这反过来可能会有更多的子树,所以这很痛苦。有一种更简单的方法。

    获取笔记

    要查看当前的音符(如果有),请使用git notes list

    $ git notes list
    b9458a531c3f93bd36af0025d56029ef58cf8d00 5e013711f5d6eb3f643ef562d49a131852aa4aa1
    1c716d4d58325651ceecba14ce8974b0ac6d13e9 a546ad9299465c9cf304fecf01d1514337419e2f
    

    “注释内容”使用每行左侧的SHA-1,每个note-content-file附加到其右侧为SHA-1的commit 1 。让我们使用第一行来看看它是如何工作的:

    $ git cat-file -t 5e013711f5d6eb3f643ef562d49a131852aa4aa1
    commit
    $ git cat-file -p 5e013711f5d6eb3f643ef562d49a131852aa4aa1
    tree ead5cc295ae64c9186f392b80ca4ed10888f20d9
    parent 309b36c8166f5ff330a6e8a0a674ed161d45b5f4
    author ...[line snipped]
    committer ...[line snipped]
    
    add ast ... [rest snipped]
    

    您当然可以git show 5e0137git log -1 5e0137等来查看该提交,它还会向您显示注释内容。但是,要查看只是原始注释内容,请使用左侧的SHA-1:

    $ git cat-file -p b9458a531c3f93bd36af0025d56029ef58cf8d00
    experiment: add a note
    
    this is the text I put in the note
    

    让我们做一个git notes edit 5e0137并更改提交的注释,然后再次git notes list

    $ git notes edit 5e0137
    [editor session snipped]
    $ git notes list
    d87650a968ff684e69175eacde0880595f9f2989 5e013711f5d6eb3f643ef562d49a131852aa4aa1
    1c716d4d58325651ceecba14ce8974b0ac6d13e9 a546ad9299465c9cf304fecf01d1514337419e2f
    

    右侧的两个“文件名”仍然完全相同,但在左侧,第一个SHA1是不同的。我们来看看它:

    $ git cat-file -p d87650a968ff684e69175eacde0880595f9f2989
    change some stuff in the note
    
    I edited the note attached to 5e0137.
    

    如果您现在git showgit log等)提交旧笔记,则会收到新笔记。实际上,这些操作是运行git notes list,检查右侧是否有匹配的ID,如果找到,则git cat-file -p左侧的ID(重新格式化/缩进)。 (当然,这是一个更优化的版本。)

    这种在notes列表中查找提交ID的机制是注释可以更改的原因。

    refs/notes/commits下添加新的提交会在“分支”下添加/更改文件(它不是真正的分支,分支以refs/heads/开头,但它只是喜欢分店)。新文件具有适用于现有(旧)提交的新注释。这些旧提交根本没有改变,但是当git loggit show查看注释以查看提交ID是否在那里时,它们会获得新的,不同的注释以显示相同的旧提交

    refs/notes/commits命名的提交对象现在必须存在,并且必须指向您要查看附加到您询问的提交的注释。如果您push对一些远程回购提交了大量新提交,但尚未push提交refs/notes/commits提交,那么在远程回购上看的任何内容都无法看到您的注释,因为他们根本就不是那里。首先或同时按下音符,它们将在那里找到。


    1 实际上,注释可以列出任何 SHA-1:提交对象,blob对象,带注释的标记对象,甚至是树对象。你甚至可以输入与repo中的任何对象不对应的SHA-1值,如果你愿意,也可以输入“分离的注释”。我知道没有这种用途的用途,但没有技术上的原因它无法完成。 [编辑添加:git notes不会这样做;我的意思是你可以用git管道命令来做到这一点。我没试过。]

    奇怪

    当然,refs/notes/commits本身就是一个常规提交树。因此,我们可以“回到过去”并查看最近git notes edit之前的注释。但似乎没有“前端”接口。我试过了,例如:

    $ git log -1 --notes=refs/notes/commits^ 5e0137
    

    但是这根本没有显示任何注释,这似乎很奇怪/破碎,因为--notes=refs/notes/commits有效。

答案 1 :(得分:3)

要添加到torek&#39; answer(这说明了为什么需要push notes并提交,以便pre-receive挂钩工作),这是进化论。

问题是:

  

当然,refs/notes/commits本身就是一个常规的提交树   因此,我们可以及时回到过去。并在最近的git笔记编辑之前查看笔记的样子。但似乎没有&#34;前端&#34;这个界面。我试过了,例如:

$ git log -1 --notes=refs/notes/commits^ 5e0137
  

但是这根本没有显示任何注释,这似乎很奇怪/破碎,因为--notes=refs/notes/commits有效。

这将适用于commits@{1},位于git 2。8(2016年3月)。

commit ee76f92Mike Hommey (glandium)(2015年10月8日) (由Junio C Hamano -- gitster --合并于commit b4e8e0e,2016年1月20日)

  

一些&#34; git notes&#34;操作,例如&#34; git log --notes=<note>&#34;,应该   能够阅读形状像笔记的任何tree-ish的笔记   树,但注释基础结构要求参数必须   是refs/notes/下的参考文献   只有在操作更新注释时才会将其松开以要求有效的ref(在这种情况下,我们必须有一个存储更新的注释树的位置,iow,ref)。

     

通过此更改,可以任意使用以只读方式使用笔记的操作   可以使用音符形tree-ish ,例如git log --notes = notes @ {1}。

(在树上,见gitrevisions

如果你创建了两个音符(b4,那么b3):

MSG=b4 git notes add
MSG=b3 git notes add

然后,您可以看到与提交树关联的最新注释(b3):

test "b3" = "$(git notes --ref commits^{tree} show)"
  

后缀^后跟括号对中的对象类型名称意味着递归地取消引用<rev>处的对象,直到找到<type>类型的对象。
  <rev>^{tree}描述了相应的树对象。

之前的说明确实是b4

test "b4" = "$(git notes --ref commits@{1} show)"

使用:

<refname>@\{<n>\}, e.g. commits@{1}
  

ref后跟后缀@,括号对中包含序数规范(例如{1}{15})指定该ref的第n个先前值。 />   例如,commits@{1}commits的直接先前值。