Is there an easy way to retrieve all notes for a certain commit including information about the note author and the note committer?
Using git show --notes=refs/notes/* <commit_hash> I was able to get all notes. However I did not find out how to get the author and committer of the note using plumbing commands.
While
git notesactually works by committing something, the author and/or committer name attached to agit notescommit is not considered useful and hence not made available. There are some good reasons for this.Let's take a quick look at a repository that has notes. Here, I am going to use the freebsd repository on GitHub, as it has
refs/notes/commits(which for $reasons I have mapped torefs/notes/origin/commits). At the moment, we have:Look at what is going on in this commit: it adds a file named
13/06/ece6bde0e4291eaf08139085990e5f55a622. This file contains the note for the object whose ID is1306ece6bde0e4291eaf08139085990e5f55a622:(I have this repository configured to use
refs/notes/origin/commitsso the note gets shown here.) In this case—which is typical—the author and committer of the note itself is the same as the author and committer of the commit to which the note attaches.If we look closer at object
af51c6d65d574faa11ab8026398e045e5f584040, though, we see that it has many files with these odd names:If we look at
598b9e08b0138536da55f5ef55868b2a3a607194, we find another 253 sub-trees named00,01,02, .... The top one is:and
825029e67b3e99c8c9f36c68c26c57b7f4c2edb4itself has only 7 entries:The names on the left are file names: these are the files stored in the
00sub-tree of the00tree of the commit. So this "top level" note commit, made by hselasky, contains hundreds of thousands of files (332,670 at the moment), all of whose names are these funky hash IDs, split up into directories of directories so that no one sub-directory has too many files.What
git showdoes with a real commit, such as1306ece6bde0e4291eaf08139085990e5f55a622(the current tip ofrefs/heads/stable/10), is to look in commitaf51c6d65d574faa11ab8026398e045e5f584040to see if it has a file whose name is1306ece6bde0e4291eaf08139085990e5f55a622, or whose directory name starts with13. If it finds a directory, it checks within it to see if there is a file whose name starts with06ece6bde0e4291eaf08139085990e5f55a622or a directory whose name starts with06. If it finds a directory, it peels off the next two characters, and so on. Eventually, it either finds the file, or it doesn't.If Git does find a file whose name matches the commit's hash, then that file contains the notes for that commit.
If Git does not find such a file, then there is no note for that commit.
Now, it is possible to update a note. Updating a note just means that we make a new commit whose contents are the same as the previous notes-commit except for one file. Let's say that we decide to update the note for commit
1306ece6bde0e4291eaf08139085990e5f55a622. We find that it's been put in13/06/ec..., so we extract notes-commitaf51c6d6...into a tree, edit the file13/06/ec..., change the note, write the file, and write a new commit whose parent commit isaf51c6d6.... We stuff the new hash for this new commit intorefs/notes/origin/commitsorrefs/notes/commits... and now we have replaced the note.Replacing the note like this is one way we could get a different author and committer for the note that goes with the original commit
1306ec....But let's take a look at an earlier commit. The next commit down on
stable/10is8f2e6e2e028ef61fd105967432ff2838153110f7. We find its note by looking at the commit to whichrefs/notes/origin/commitspoints: that'saf51c6...again. Does it have a directory named8f? Why yes, it does. Does that directory have a sub-directory named2e? Sure enough, it does. Does that have a file named6e2e...?Indeed it does, and that's a blob that we can view:
so that's the note for commit
8f2e74c5.... But the author and committer of the place we looked—refs/notes/origin/commitsakaaf51c6...—is hselasky, while the author and committer of8f2e6e2e028ef61fd105967432ff2838153110f7is avos.To find the author and committer of whoever most recently changed the note for
8f2e6e2e028ef61fd105967432ff2838153110f7, we must start at the top levelrefs/notes/origin/commitscommit and see who has touched a file whose name looks like that. The name itself is actually, currently,8f/2e/6e2e...; but at some earlier point, the name would have been8f/2e6e2e..., and as the repository continues to grow, the name will at some point suddenly change to8f/2e/6e/2e.... So we would need a tool that is not only aware of the funky hash-ID-as-file-name thing, but also knows that the split, into directories containing sub-directories containing files, evolves over time. This makes it pretty hard to find when the note changed, if it ever did.If the note never changes, the first time it gets added to the repository is usually "when the commit itself is created" and therefore its author and committer will match the commit's author and committer. So that's usually good enough. If it's not good enough for your use case, you will have to write your own tools.