git:获取commit-id和提交的注释 [英] git: get the commit-id and the note of a commit

查看:420
本文介绍了git:获取commit-id和提交的注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个钩子来验证在git日志的注释部分输入的url。我循环每次提交以获取该特定提交的注释并为url进行字符串比较。如果提交是新提交,则会弹出问题,因为新提交不包含注释。



示例: -

  git add sample 
git commit -madded sample
git notes add -msample note< commitID-of-sample>
git push origin master
git push origin refs / notes / *

问题与上面的例子是,首先我推提交但提交没有注意,因为git push origin refs / notes / *被推后主。我基本上想访问pre-receive钩子中提交的提示。



有什么建议吗?

解决方案

你从字面上看不能按照你展示的方式来做。问题归结为笔记的工作方式。正如mart1n在评论中所建议的,您需要首先或同时推送笔记。这是为什么:

笔记如何工作​​



附加到提交的笔记存在(因此可以是显示为 git log git show )nowif:


  1. 让我们说这个提交的SHA1(我们试图找到它的注释)是 1234567 ...

  2. refs / notes / commits 存在,并且
  3. 通过提交读取 refs / notes / commits points-to,有一个文件的文件名匹配 1234567 ...

注释是带有有趣名称的文件内容。



让我们来探索过程。

背景,使用低级别的rawgit命令



最低级别大多数回购的访问命令是 git cat-file 。这让你看看类型( git cat-file -t sha1 )和内容( git cat-file - p sha1 )。这里的 sha1 部分可以是任何git引用名称,只要它解析为40个字符的十六进制SHA-1值之一即可。注释的默认ref-name是 refs / notes / commits ,并且(如果存在)它应该总是指向 commit 对象。因此:
$ b $

  $ git cat-file -p refs / notes / commitits 
tree 28db2757c2b7c6e4bbfef35e61e8bd7c698626dc
parent ce97e80bfbdab9bc163ecb93779d071d7ed8c739
作者AU Thor< author@example.example> 1376652910 -0600
提交者A U Thor< author@example.example> 1376652910 -0600

'git notes edit'添加注释

我们的下一个一步是看看这里命名的

  $ git cat-file -p 28db2757c2b7c6e4bbfef35e61e8bd7c698626dc 

对于一小组笔记,这产生了几乎相同的结果见下文。如果有很多笔记,这会导致更多 s,这又可能有更多的子树,所以这是一个痛苦。有一个更简单的方法。

获得笔记



要查看当前笔记是什么(如果有的话) ,使用 git notes list

  $ git notes list 
b9458a531c3f93bd36af0025d56029ef58cf8d00 5e013711f5d6eb3f643ef562d49a131852aa4aa1
1c716d4d58325651ceecba14ce8974b0ac6d13e9 a546ad9299465c9cf304fecf01d1514337419e2f

在 记事内容 关于使用SHA-1每行左边,每个音符内容文件附加到提交 1 ,其SHA-1位于右侧。让我们用第一行来看看它是如何工作的:

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

add ast ... [休息片断]

当然,您可以 git show 5e0137 git log -1 5e0137 等等,看看那个提交,它也会显示注释内容。

   原始音符内容仅用于  $ git cat-file -p b9458a531c3f93bd36af0025d56029ef58cf8d00 
实验:添加一个注释

这是我放在注释中的文本

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

  $ git notes edit 5e0137 

$ git的笔记列表
d87650a968ff684e69175eacde0880595f9f2989 5e013711f5d6eb3f643ef562d49a131852aa4aa1
1c716d4d58325651ceecba14ce8974b0ac6d13e9 a546ad9299465c9cf304fecf01d1514337419e2f

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

  $ git cat-file -p d87650a968ff684e69175eacde0880595f9f2989 
更改注释中的某些内容

我编辑了5e0137附带的注释。

如果您现在 git show git log 等等)旧笔记附加到的提交,您将获得新笔记。实际上,这些做的是运行 git notes list ,在右侧检查匹配的ID,如果找到, git cat-file -p 左侧的ID(重新格式化/缩进)。 (当然,这是一个更优化的版本。)



注释中查找提交ID的机制 refs / notes / commitits 在code列表中添加一个新的提交在这个分支下面添加/更改文件(它不是一个真正的分支,分支以 refs / heads / 开头,但它其实只是 a科)。新文件具有适用于现有(旧)提交的新注释。那些旧的提交根本没有改变,但当 git log git show 查看注释时,看看commit-ID在那里,他们得到新的,不同的注释以显示相同的旧提交。


$ b

命名的提交对象refs / notes但是/ commitits 现在必须存在,并且必须指向你想要附加到你所提交的提交的注释。如果你推送一些新的提交给一些remote-repo,并且没有 push 编辑 refs / notes / commitits commit,但是在remote-repo上看到的东西都看不到你的笔记,因为它们根本就不是那里






1 实际上,一个注释可以列出任何 SHA-1:一个提交对象,一个blob对象,一个带注释的标记对象,甚至一个树对象。如果您愿意,甚至可以输入与回购中任何对象不相对应的SHA-1值,即分离说明。我知道这样的事情没有用处,但没有技术上的理由,它不能做到。



古怪



当然, refs / notes / commitits 本身就是一个常规的提交树。因此,我们可以及时回顾并查看最近的 git notes edit 之前的注释。但是这似乎没有前端界面。我尝试过,例如:

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

但是它只显示没有任何注释,这似乎很奇怪/中断,因为 - notes = refs / notes / commitits 有效。


I am writing a hook for validating url's which are entered in the notes section of the git log. I loop through each commit to get the note for that particular commit and do a string comparison for the url. The problem pops up if the commit is a new commit, since the new commit does not contain a note.

example:-

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/*

problem with the above example is, first i push the commit but the commit has no note since git push origin refs/notes/* is pushed after master. I basically want to access the note of a commit in the pre-receive hook.

any suggestions?

解决方案

You literally can't do this the way you showed. The problem boils down to the way notes work. As mart1n suggested in a comment, you need to push the notes either first, or simultaneously. Here's why:

How notes work

A note "attached to" a commit exists (and thus can be shown by git log and git show) "now" if:

  1. Let's say the SHA1 of this commit (whose note we're trying to find) is 1234567....
  2. refs/notes/commits exists, and
  3. reading via the commit that refs/notes/commits points-to, there's a "file" whose file-name matches 1234567....

The note is the content of the file with the funny name.

Let's explore the process of finding a note.

Background, using low-level "raw" git commands

The lowest-level access command for most of the repo is git cat-file. This lets you look at the type (git cat-file -t sha1) and contents (git cat-file -p sha1) of any object within the repository. The sha1 part here can be any git reference name, as long as it resolves to one of those 40-character hexadecimal SHA-1 values. The default ref-name for notes is refs/notes/commits, and (if it exists) it should always point to a commit object. Hence:

$ 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'

Our next step would be to look at the tree named here:

$ git cat-file -p 28db2757c2b7c6e4bbfef35e61e8bd7c698626dc

For a short set of notes this produces almost the same thing we'll see below. If there are a lot of notes, this leads to more trees, which in turn can have yet more subtrees, so it's a pain. There's a much easier way.

Obtaining the notes

To see what the current notes are (if any), use git notes list:

$ git notes list
b9458a531c3f93bd36af0025d56029ef58cf8d00 5e013711f5d6eb3f643ef562d49a131852aa4aa1
1c716d4d58325651ceecba14ce8974b0ac6d13e9 a546ad9299465c9cf304fecf01d1514337419e2f

The "note contents" use the SHA-1 on the left of each line, and each note-content-file is attached to the commit1 whose SHA-1 is on the right. Let's use the first line to see how this works:

$ 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]

You can, of course, git show 5e0137 or git log -1 5e0137, etc., to see that commit, which will also show you the note contents. To see just the raw note contents, though, use the SHA-1 on the left:

$ git cat-file -p b9458a531c3f93bd36af0025d56029ef58cf8d00
experiment: add a note

this is the text I put in the note

Let's do a git notes edit 5e0137 and change the note for the commit, and then git notes list again:

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

The two "file names" on the right are still exactly the same, but on the left, the first SHA1 is different. Let's look at it:

$ git cat-file -p d87650a968ff684e69175eacde0880595f9f2989
change some stuff in the note

I edited the note attached to 5e0137.

If you now git show (git log, etc) the commit the old note was attached to, you get the new note. What these do, in effect, is to run git notes list, check on the right for a matching ID, and if found, git cat-file -p the ID on the left (reformatted / indented). (Well, a more optimized version of that, of course.)

This mechanism, of looking up the commit ID in the notes list, is why notes can change.

Adding a new commit under refs/notes/commits adds/changes files under that "branch" (it's not really a branch, branches start with refs/heads/, but it's otherwise just like a branch). The new files have new notes that apply to existing (old) commits. Those old commits are not changed at all, but when git log and git show look at the notes to see if the commit-ID is in there, they get new, different notes to show for the same old commit.

The commit object named by refs/notes/commits must exist by now, though, and must point to the notes you want to see attached to the commit(s) you're asking about. If you push a bunch of new commits to some remote-repo, and have not pushed the refs/notes/commits commit yet, anything looking on the remote-repo can't see your notes, as they simply are not there. Push the notes first, or at the same time, and they will be there to find.


1Actually a note can list any SHA-1: a commit object, a blob object, an annotated tag object, or even a tree object. You could even put in SHA-1 values that do not correspond to any object in the repo, a "detached note" if you will. I know of no uses for such a thing, but there's no technical reason it could not be done. [Edit to add: git notes won't do this; I mean you could do it with git plumbing commands. I haven't tried it though.]

An oddity

Naturally, refs/notes/commits is itself a regular commit tree. We can therefore "go back in time" and look at what the notes looked like before the most recent git notes edit. But there seems to be no "front end" interface for this. I tried, e.g.:

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

but that just shows no note at all, which seems weird / broken, since --notes=refs/notes/commits works.

这篇关于git:获取commit-id和提交的注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆