I am finding a lot of answers to how to make a local branch look like a remote branch, but in my case, I need to take in changes that were force pushed to the remote to refs/notes/commits
.
The changes were made using git notes add
. The remote was updated using git push origin refs/notes/* -f
.
I have different history for refs/notes/commits
locally. Until now I was using git fetch origin "refs/notes/*:refs/notes/*"
to integrate remote notes changes to my local. With the forced push, the two histories are now disjoint. I want to throw away mine and take in theirs.
Since refs/notes/commits
is not a branch (right?) I cannot use git push
or git checkout
to enter it and then git reset
(again, right?). So, what can I use to make my local refs/notes*
equivalent to the remote refs/notes/*
?
CodePudding user response:
It's true that refs/notes/commits
is not a branch, as all branch names by definition start with refs/heads/
instead. However, git fetch
and git push
work with any ref-name, and you can force-fetch as well as force-push. So:
Until now I was using
git fetch origin "refs/notes/*:refs/notes/*
to integrate remote notes changes to my local. With the forced push, the two histories are now disjoint. I want to throw away mine and take in theirs.
That would be a forced fetch. (Side note: there's a missing closing quote above.) To force a fetch, do the same thing you do with git push
: add the --force
flag, or prefix the refspec—the pair of names separated by a colon—with a plus sign. The latter is shorter (by at least one character) so that's the one I'll use here:1
git fetch origin " refs/notes/*:refs/notes/*"
or:
git fetch origin " refs/notes/commits:refs/notes/commits"
This will overwrite the current value (stored hash ID) of your refs/notes/commits
with the fetched value, provided they have a refs/notes/commits
; the variant with *
will overwrite all of your refs/notes/
names with theirs (creating any names they have that you didn't before).
1Note that
in front of a refspec sets the force flag for that one refspec, while --force
on the command line sets the force flag for all refspecs. That is:
git fetch origin refs/heads/br1:refs/heads/br1 refs/heads/br2:refs/heads/br2
fetches from origin's branch br1
to (local) branch br1
without forcing, but fetches from origin's br2
to br2
with forcing. Compare with:
git fetch --force origin refs/heads/br1:refs/heads/br1 refs/heads/br2:refs/heads/br2
which forces both updates. A forced update simply takes place even if Git's normal rules would reject the update.2
2For git push
, the other end can add additional, non-Git rules. That's how GitHub and others provide "protected branches", for instance. Since these are not Git's normal rules, the --force
or
flag does not override these rules. There's nothing equivalent for git fetch
, since that's into your own repository and you are assumed to know what you are doing.