Can I add metadata to git commits? Or can I hide some tags in gitk Can I add metadata to git commits? Or can I hide some tags in gitk git git

Can I add metadata to git commits? Or can I hide some tags in gitk


Git-notes

With git notes you can add a “note” to a commit. You can also add themto other Git objects, but let’s just focus on commits since that is whatthe question is about.

A note is a Git object, and can in principle be “whatever” (arbitrarydata). But we’ll focus on something simple and textual for our purposes.

Example: review id

The question mentions review ids, so let’s make up some way to representsuch a thing. I don’t know what review ids really look like, buthopefully the following would be sensible:

Review-id: 42

So this is effectively a key-value pair. Let’s add the above string tothe current commit:

git notes add -m "Review-id: 42"

If you run git log the note will be shown inline:(†1)

Author: Victor Version Control <vvc@vcs.org>Date:   Tue Nov 8 21:10:25 2016 +0100    Implement feature xNotes:    Review-id: 42

Another example

Of course you can add more “subnotes” to this note (we will stick withthe simple key: value syntax, one value per line). For example, if youfound out three months later that the commit message got somethingwrong, just append the correction to the note:

git notes append -m "Errata: It was actually feature y."

git log:

Author: Victor Version Control <vvc@vcs.org>Date:   Tue Nov 8 21:10:25 2016 +0100    Implement feature xNotes:    Review-id: 42    Errata: It was actually feature y.

We use git notes append in order to easily add this extra data to thenote. You could also use git notes edit in order to edit the filedirectly.

Of course, since a Git note is just a single mutable file, you can runinto merge conflicts. To make that less likely, you can:

  1. Stick to simple data like the above (one key-value per line).
  2. Use special merge strategies; see man git-notes, section “Notesmerge strategies”.

Visibility

The OP asked:

> Can I make certain tags invisible?

By default, git log only shows one note, namely.git/refs/notes/commits. commits is just one note in the namespace.Maybe you want issues to be in their own namespace:

git notes --ref=issues add -m "Fixes: #32"

Since this is stored in .git/refs/notes/issues and not in.git/refs/notes/commits, “Fixes: #32” won’t show up when you rungit log. So you have effectively made such notes invisible by default.

If you want it to be shown, pass --notes=issues to git log:

$ git log --notes=issuesAuthor: Victor Version Control <vvc@vcs.org>Date:   Tue Nov 8 21:10:25 2016 +0100    Implement feature xNotes (issues):    Fixes: #32

But now .git/refs/notes/commits are hidden. That one can easily beincluded as well:

$ git log --notes=issues --notes=commitsAuthor: Victor Version Control <vvc@vcs.org>Date:   Tue Nov 8 21:10:25 2016 +0100    Implement feature xNotes (issues):    Fixes: #32Notes:    Review-id: 42    Errata: It was actually feature y.

There are variables to configure which notes are shown by default; seeman git-config.

Benefits compared to commit messages

Metadata can of course be recorded in the commit message directly.(†2) Butcommit messages are immutable, so to change them really means to make awhole new commit, with all the rippling consequences that that entails.Git-notes on the other hand are mutable, so you are always able torevise them. And each modification of a note is of course versioncontrolled. In our case, for .git/refs/notes/commits:

$ git log refs/notes/commitsAuthor: Victor Version Control <vvc@vcs.org>commit 9f0697c6bbbc6a97ecce9834d4c9afa0d668bcadDate:   Tue Nov 8 21:13:52 2016 +0100    Notes added by 'git notes append'commit b60997e49444732ed2defc8a6ca88e9e21001a1dAuthor: Victor Version Control <vvc@vcs.org>Date:   Tue Nov 8 21:10:38 2016 +0100    Notes added by 'git notes add'

Sharing notes

Your notes aren’t shared by default; you have to do so explicitly. Andcompared to other refs, sharing notes isn’t very user-friendly. We haveto use the refspec syntax:

git push refs/notes/*

The above will push all of your notes to your remote.

It seems that fetching notes is a bit more involved; you can do it ifyou specify both sides of the refspec:

git fetch origin refs/notes/*:refs/notes/*

So that’s definitely not convenient. If you intend to use Git-notesregularly, you’ll probably want to set up your gitconfig to always fetchnotes:

[remote "origin"]    …    fetch = +refs/notes/*:refs/notes/*

Carry over notes on rewrites

Git has the inconvenient default that notes are not carried over when a commitis rewritten. So if you for example rebase a series of commits, the notes willnot carry over to the new commits.

The variable notes.rewrite.<command> is by default set to true, so one mightassume that notes are carried over. But the problem is that the variablenotes.rewriteRef, which determines which notes will be carried over, has nodeafult vaule. To set this value to match all notes, execute the following:

git config --global notes.rewriteRef "refs/notes/*"

Now all notes will be carried over when doing rewrite operations like gitrebase.

Carry over notes through email patches

If you are using git format-patch to format your changes to be sent as emails,and you have some metadata stored as Git notes, you can pass the --notesoption to git format-patch in order to append the notes to the email draft.


† 1: “This is the default for git log […] when there is no --pretty,--format, or --oneline option given on the command line.” ― man git-log, git version 2.10.2

† 2: One practice/convention for metadata-in-commit-messages that is used in projects like e.g. Git and the Linux kernel is to add key–value pairs in the “trailer” of the commit message, i.e. at the bottom. See for example this commit by Linus Torvalds:

 mm: remove gup_flags FOLL_WRITE games from __get_user_pages() This is an ancient bug that was actually attempted to be fixed once (badly) by me eleven years ago in commit 4ceb5db9757a ("Fix get_user_pages() race for write access") but that was then undone due to problems on s390 by commit f33ea7f404e5 ("fix get_user_pages bug"). In the meantime, the s390 situation has long been fixed, and we can now fix it by checking the pte_dirty() bit properly (and do it better).  The s390 dirty bit was implemented in abf09bed3cce ("s390/mm: implement software dirty bits") which made it into v3.9.  Earlier kernels will have to look at the page state itself. Also, the VM has become more scalable, and what used a purely theoretical race back then has become easier to trigger. To fix it, we introduce a new internal FOLL_COW flag to mark the "yes, we already did a COW" rather than play racy games with FOLL_WRITE that is very fundamental, and then use the pte dirty flag to validate that the FOLL_COW flag is still valid. Reported-and-tested-by: Phil "not Paul" Oester <kernel@linuxace.com> Acked-by: Hugh Dickins <hughd@google.com> Reviewed-by: Michal Hocko <mhocko@suse.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Kees Cook <keescook@chromium.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Willy Tarreau <w@1wt.eu> Cc: Nick Piggin <npiggin@gmail.com> Cc: Greg Thelen <gthelen@google.com> Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

See:

  • man git-interpret-trailers
  • This Kernel Wiki page which lists various trailer lines (usually key–value pairs) that are used in various projects.