1

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/*?

1 Answer 1

2

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. 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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.