5

Currently if I add notes to an object in git I have to explicitly push/pull this information to the remote server.

Is it possible to configure git so that when I do a git push it will push my local notes changes as well as any local source changes?

Likewise for git pull.

Daniel Serodio
  • 4,229
  • 5
  • 37
  • 33
DaveG
  • 143
  • 1
  • 2
  • 5

2 Answers2

4

Yes for git pull, no for git push.

You can fetch notes:

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

but, as mentioned in "Note to Self" (2010, but I don't think this has changed):

However, you can push anything under 'refs/' to a server, you just need to be more explicit about it. If you run this it will work fine:

$ git push origin refs/notes/bugzilla

In fact, you may want to just make that git push origin refs/notes/* which will push all your notes.
This is what Git does normally for something like tags. When you run git push origin --tags it basically expands to git push origin refs/tags/*.

git push doesn't push all tags by default (see "Why git doesn't push tags by default?").
git push doesn't push all notes for the same reason.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • However "you *can*" not "can't" – Craig Ringer Oct 26 '18 at 05:27
  • I found a way to do it btw. Mostly. The downside is that you get behaviour like `push.default = current` as a side-effect, instead of the nice, upstream-aware `push.simple`. I'd love your advice on if there's something I'm missing to take it that next step, or if it's submit-a-patch time. https://stackoverflow.com/a/53003190/398670 – Craig Ringer Oct 26 '18 at 07:02
3

You can auto-push notes, but it changes default push

Yes, you can configure a remote to push multiple branches and additional branches.

It comes at the cost of overriding the default "push current branch" behaviour defined by push.default = 'simple', making it behave like current instead; it pushes to a branch with the same name as the upstream and ignores any git branch --set-upstream-to that's been configured.

Assuming your remote is origin then:

git config --unset-all remote.origin.push
git config --add remote.origin.push "HEAD"
git config --add remote.origin.push "refs/notes/commits:refs/notes/commits"

Push notes and push branch to upstream-tracking branch

We should be able to achieve behaviour like push.default = upstream with something like:

# THIS WON'T WORK
git config --unset-all remote.origin.push
git config --add remote.origin.push "HEAD:@{upstream}"
git config --add remote.origin.push "refs/notes/commits:refs/notes/commits"

instead.

But it doesn't work on my git 2.17.1, failing with:

fatal: Invalid refspec 'HEAD:@{upstream}'

even though I see documentation talking about using @{upstream} in push refspecs. You can

git push origin "@{upstream}"

and you'll get a complaint like

fatal: remote part of refspec is not a valid name in @{upstream}

because git resolves it to a refspec @{upstream}:@{upstream}, doesn't resolve @{upstream} to anything on the remote-side, and complains. This is distinct from its behaviour when pushing HEAD where it automagically uses the branch-name as the upstream.

Unfortunate. But you could argue @{upstream} doesn't make sense on the remote side.

Wishlist: simple plus extra refspecs

What we really want to be able to do is add extra refspecs and leave the push.default behaviour alone.

But git doesn't understand push.default names in remote.*.push settings - it couldn't tell them apart from branch names, after all.

It also doesn't seem to have a way to say "use this remotes.origin.push config to ADD to the default refspec list".

I want something like this imaginary non-working config:

# THIS WON'T WORK
git config --add remote.origin.push "{DEFAULT}"
git config --add remote.origin.push "refs/notes/commits:refs/notes/commits"

or

# THIS WON'T WORK
git config remote.origin.push_default "simple"
git config --add remote.origin.push "refs/notes/commits:refs/notes/commits"

or

# THIS WON'T WORK
git config remote.origin.push @{simple}
git config --add remote.origin.push "refs/notes/commits:refs/notes/commits"

You have to use an explicit refspec like refs/heads/master:refs/heads/master (always push master) or (DANGER) refs/heads/*

And there doesn't seem to be a way to encode the "simple" behaviour of "push to configured upstream origin, refuse if there isn't one" into the remote-side of a refspec.

Testing

I very strongly recommend that you first

git push --verbose --dry-run --porcelain origin

before you do anything for real. The --porcelain disables the summary's "helpful" habit of simplifying refs/heads in ways that make them ambiguous if you've made a mistake in your config.

Also, be aware that you will have disabled git's default protection against accidentally pushing a branch that doesn't correspond to an upstream of the same name.

Overall, I recommend not doing it.

See also

Craig Ringer
  • 307,061
  • 76
  • 688
  • 778