Git: get commit id and commit note

I am writing a hook for checking the urls that are introduced in the notes section of the git log. I go through each commit to get a note for this particular commit and do string comparisons for the url. The problem occurs if the commit is a new commit, as 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/* 

The problem with the above example is that I press commit first, but commit has no note, since git push origin refs / notes / * is pressed after the wizard. I basically want to access the commit note in the pre-hook.

any suggestions?

+4
source share
2 answers

You literally cannot do as you showed. The problem comes down to how the notes work. As pointed out in mart1n's comment, you need to click notes first or simultaneously. That's why:

How notes work

The note "attached to" the commit exists (and therefore git log and git show can be shown) "now" if:

  • Say SHA1 of this commit (whose note we are trying to find) is 1234567...
  • refs/notes/commits exists, and
  • reading through a commit that refs/notes/commits point-to is a "file" whose file name matches 1234567...

Note - this is the contents of a file with a funny name.

Let's look at the process of finding notes.

Background using low-level raw git commands

The lowest access command for most repos is git cat-file . This allows you to see the type ( git cat-file -t sha1 ) and contents ( git cat-file -p sha1 ) of any object in the repository. The sha1 part here can be any git link name if it resolves one of these 40-character SHA-1 hexadecimal values. The default value 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 AU Thor < author@example.example > 1376652910 -0600 committer AU Thor < author@example.example > 1376652910 -0600 Notes added by 'git notes edit' 

Our next step is to look at the tree named here:

 $ git cat-file -p 28db2757c2b7c6e4bbfef35e61e8bd7c698626dc 

For a short set of notes, this gives almost the same thing that we will see below. If there are many notes, this leads to more tree s, which in turn can have even more subtrees, so this is a pain. It’s much easier there.

Receive notes

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

 $ git notes list b9458a531c3f93bd36af0025d56029ef58cf8d00 5e013711f5d6eb3f643ef562d49a131852aa4aa1 1c716d4d58325651ceecba14ce8974b0ac6d13e9 a546ad9299465c9cf304fecf01d1514337419e2f 

The “note content” uses SHA-1 to the left of each line, and each note-content file is attached to a commit of 1 whose SHA-1 is on the right. Let us use the first line to see how it 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. see this message, which will also show you the contents of the note. However, to see only the contents of the original note, use SHA-1 on the left:

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

Do a git notes edit 5e0137 and change the note to 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 the same, but on the left, the first SHA1 is different. Look at this:

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

If you are now git show ( git log , etc.), then commit the old note, you will receive a new note. In fact, this means that you need to run git notes list , check the correct identifier, and if found, git cat-file -p identifier on the left (reformatted / indented). (Well, this is a more optimized version, of course.)

This mechanism for finding a fix identifier in the notes list is why notes can change.

Adding a new commit to refs/notes/commits adds / modifies files in this branch (this is not a branch, branches start with refs/heads/ , but otherwise it's just like a branch). New files have new notes that apply to existing (old) records. These old commits don't change at all, but when git log and git show look at the notes to see if there is a commit id, they get new, different notes for the same old commit.

The commit object, called refs/notes/commits , should still exist and should point to the notes you want to see attached to the commit messages you are asking for. If you push bunch of new commits to some remote repo and have not yet edited the refs/notes/commits commit, everything that looks at the remote repo cannot see your notes, because they simply do not exist, first click the notes or one and same time, and they will be there to find them.


1 In fact, a note can display any SHA-1: a commit object, a blob object, an annotated tag object, or even a tree object. You can even enter SHA-1 values ​​that do not match any object in the repo if you do. I do not know anything about such things, but there are no technical reasons why this is impossible. [Edit to add: git notes will not do this; I mean, you can do this with git plumbing commands. I have not tried, though.]

Oddness

Naturally, refs/notes/commits itself is a regular commit tree. Therefore, we can "go back in time" and see how the notes looked before the latest git notes edit . But there seems to be no front end interface for this. I tried for example:

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

but it just doesn't show any note, which seems weird / broken, because --notes=refs/notes/commits works.

+8
source

To add to torek's answer (which illustrates why you need to click notes and lock in order for pre-receive hook to work), here is the evolution.


The problem was this:

Naturally, refs/notes/commits itself is a regular commit tree.
In this way, we can “go back in time” and see how the notes looked before the latest changes to git notes. But there seems to be no front end interface for this. I tried for example:

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

but it just doesn't show any note, which seems weird / broken since --notes=refs/notes/commits works.


This will work with commits@ {1} , in git 2.8 (March 2016).

See commit ee76f92 (October 08, 2015) by Mike Homm ( glandium ) .
(merger of Junio ​​C Hamano - gitster - on commit b4e8e0e , January 20, 2016)

Some git notes operations, for example. " git log --notes=<note> ", you should be able to read notes from any ish tree that has the form of a notes tree, but the notes infrastructure requires the be ref argument to refs/notes/ .
Loosen it to require a valid reference number only when the operation updates the notes (in this case, we should have a place to store the updated notes tree, iow, a ref ).

With this change, operations that use read-only notes can use a tree-ish note , for example. git log --notes = notes @ {1}.

(on a tree, see gitrevisions )

If you create two notes ( b4 , then b3 ):

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

Then you can see the most recent note ( b3 ) associated with the commit tree:

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

The suffix ^ followed by an object type name enclosed in a pair of brackets means dereferencing the object in <rev> recursively until an object of type <type> .
<rev>^{tree} describes the corresponding tree object.

And the previous note would really be b4 :

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

FROM

 <refname>@\{<n>\}, eg commits@ {1} 

A link followed by the @ suffix with an ordinal specification enclosed in a pair of brackets (for example, {1} , {15} ) indicates the nth previous value of this ref.
For example, commits@ {1} is the immediate value of the previous commits value.

+3
source

Source: https://habr.com/ru/post/1497429/


All Articles