简体   繁体   中英

accessing Notes in a git pre-receive hook

We have a chicken-and-egg situation with commit message rules. One piece of info cannot be known until after the commit. We thought that instead of requiring the user to amend the commit (or rebase if the commit is older), it would be nice if the user could just add the info via the 'notes' mechanism. OK, so far, so good.

The problem is that I want the 'pre-receive' hook to be able to fail the push if the commit+notes info does not adhere to the rules. However, I cannot seem to figure out how to see the notes for a given commit, unless the notes have already been pushed ahead of the commit.

I could simply allow a notes push to go through unchecked, then check both the commit message and its notes when I see the commit. However, this is a less-than-ideal workaround. We can guarantee the order will be notes first, commits second. But, it is a hack. What if the commit+notes fails because of info in the notes? That means the notes, which were allowed through, need to be revised.

Instead, I want to get both notes and commits together (something like git push origin refs/notes/* refs/heads/<branch> ). We can control this, because our pushes use a wrapper script. If the two pushes occur together, I should be able to pass/fail the whole thing. No errant info gets through.

But I cannot for the life of me figure out how to see the notes. The ideal would be to use something like git log --format=%N -1 <commit> on each commit in the push. But this produces nothing, I guess because both commits and notes have not gone through yet. I've tried git notes list in hopes that I could then print the object pointed to by the hash ( git cat-file -p <hash> ). But git notes list produces nothing as well.

Ideas? Thanks.

A pre-receive hook gets all the reference updates (on stdin), so you could read through them all, see if there are refs/notes/ updates, read through the notes, and then apply your rules to underlying notes objects . This is very painful, though: you would have to dive deep into the implementation of notes, since (as you noted) the refs/notes/ reference itself is not yet updated, so that git log cannot find the new notes.

As an alternative, you could perhaps manually update the notes reference update inside the hook . This is at least a little bit dangerous, though: you'd want to "undo" this update before proceeding (to make updates look as atomic as they should) and make sure nothing else uses the notes, or the Git repository at all, during this period. (The reason for this is complicated and Git-version-dependent: newer Gits place incoming objects in a separate alternate object store, making them available for pre-receive and update hooks but not available in general, so that the incoming objects need not be discarded if the push is rejected.)

I think eckes' suggestion (in a comment) is perhaps the way to go. To make it more elaborate and automatic, instead of forbidding or allowing a push to refs/heads/foo , you might use gitnamespaces so that all pushes wind up going to refs/proposed/refs/heads/foo for instance (and require that this be the new creation of said name). Then, after accepting the push, run a post-processing pass that checks the update. If it's good, move it to refs/heads/foo . If not, delete the refs/proposed/refs/heads/foo name anyway, and send whoever did the push email, saying that their push has been automatically rolled back. There is an obvious drawback to this idea: their Git will think the push has been accepted and they will have to re-run git fetch to get their refs/remotes/origin/foo re-set back to the un-updated value. Also, it's somewhat difficult technically to know precisely who did the push unless all your pushes happen over ssh using unique user information (which you can record at the same time you accept the refs/proposed/refs/heads/foo ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM