gitgit-pushgit-pullgit-fetchgit-notes

git overrides refs/notes when fetching?


I'm keeping my changelog in git-notes --ref changelog when developing. I'm always putting a note on the merge-to-master commit and push it out to three remotes (git push <remote> refs/notes/changelog) - but every time I forget to push to one remote and fetch from it, the ref gets overridden with some old version:

(Sorry for german locale)

$ git fetch github -p
Von github.com:<user>/<repo>
 + ca36d98d...1f3b9041 refs/notes/changelog -> refs/notes/changelog  (Aktualisierung erzwungen)

How to prevent that? Is it somehow related to my .git/config?

(excerpt from .git/config):

[remote "github"]
    url = git@github.com:<user>/<repo>.git
    fetch = +refs/heads/*:refs/remotes/github/*
    fetch = +refs/pull/*/head:refs/remotes/github/pr/*
    push = +refs/notes/changelog:refs/notes/changelog
    fetch = +refs/notes/changelog:refs/notes/changelog
[notes "rewrite"]
    rebase = true
    amend = true
[notes]
    rewriteRef = refs/notes/changelog

Solution

  • You are correct. Each fetch line in your .git/config file specifies one of however-many default fetch refspecs Git will use, so:

    fetch = +refs/heads/*:refs/remotes/github/*
    fetch = +refs/pull/*/head:refs/remotes/github/pr/*
    fetch = +refs/notes/changelog:refs/notes/changelog
    

    provides three such refspecs.

    Each refspec consists of two main parts separated by a colon: on the left there is the source reference and on the right there is the destination reference. Asterisks * may be used and act mostly like shell glob * (as a source only; the destination * is replaced with whatever the source * matched). If this pair is prefixed with a plus sign +, the update is always forced (as if you used --force on the command line).

    Note that remote-tracking names such as refs/remotes/github/master exist in a per-remote space: you will fetch origin's master into refs/remotes/origin/master which is clearly different from refs/remotes/github/master. Hence it's safe, at least for all ordinary purposes, to fetch with force for such names: you cannot overwrite your own branches, which are in refs/heads/, nor any other remote's remote-tracking names.

    This is of course not true for notes references in refs/notes/, nor for tags in refs/tags/, so use care with leading + on either of those.