I spent a lot of time today trying to figure out why notes I was adding were getting removed at seemingly random points. Even notes that I pushed to remote with a non-default ref weren’t showing up after I added another local-only commit note. This turned out to be another case in the “two different tools working fine individually combine to create weird behaviour” phenomenon.
For a long time now I had the following setting in my main gitconfig file:
At a very high level, pruning ensure that all the local refs are maintained 1=1 with the configured remotes, and any remote branch that doesn’t exist locally gets removed from local.
pruneTags does the same thing for tags. The PRUNING section of git-fetch manpage has more information on this.
This, with a combination of my shell configuration drove me mad for a bit.
Pruning and notes behaviour
I completely missed this part: the local notes refs will get pruned if they’re not explicitly synced1 to the remote:
refs/notes/commits item? This is the default reference under which notes get added. This behaviour was surprising in hindsight because another local-first annotation mechanism that similarly needs explicit syncing is Git’s tagging system, and that has a specific flag for pruning.
git fetch --prune won’t prune local tags that weren’t pushed to remote.
I use the excellent pure prompt in my main (zsh) shell. The plugin also comes with a script that frequently syncs the state of the git repostory, using
git fetch --all. This way, the prompt can show helpful arrows as and when it knows that there are some changes on the remote, or perhaps when you switch to a new branch that has diverged from the remote upstream.
Without this script, you’d have to periodically run
git fetch --all or plain
git fetch, inorder for git to know the difference between the local and remote branches.
Needless to say, a combination of auto-running
git fetch, with pruning turned on wreaked havoc!
How this manifested
I had a branch on the remote and local that had a note on the last commit. On running
git log the first time in a new shell, the remote note showed up. When I tried to add a local note using
git note add -m 'some message', that didn’t show up sometimes. This got very confusing and I ended up spending lots of time debugging this thinking the issue might be in the git config or git itself. Only when I tried this out in a VM did I realized the problem.
So the moral of the story is, avoid running
prune or configuring it globally unless you’re absolutely sure you’re not adding any local-only refs.
The bright side of all this, though, is our team now has a very rudimentary build information tagging workflow without requiring another layer of abstraction (think: a website that maintains the build <-> commit mappings).
Syncing notes has to be done explicitly using
git push origin refs/notes/<ref>; plain
git pushwon’t do this, which is a good default to have anyway. A good resource I’ve found on this is this cheatsheet ↩