Re: [BUG] git remote prune removes local tags, depending on fetch config
- From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- Date
- Jan 16, 2018, 00:38 UTC
- Message-ID
- <87tvvmiqn7.fsf@evledraar.gmail.com>
- In-Reply-To
- <CACi5S_39wNrbfjLfn0xhCY+uewtFN2YmnAcRc86z6pjUTjWPHQ@mail.gmail.com>
On Mon, Jan 15 2018, Michael Giuffrida jotted:
Show 25 quoted lines
> `git remote prune <name>` should "delete all stale remote-tracking > branches under <name>". I was surprised to discover, after some > troubleshooting, that it also deletes *all* local tags that don't > exist on the remote, if the following refspec is included in the > remote's fetch config: > > +refs/tags/*:refs/tags/* > > So, if `remote.origin.fetch` is configured to fetch all tags from the > remote, any tags I create locally will be deleted when running `git > remote prune origin`. This is not intuitive [1], nor is is it > explained in the docs [2]. Is this behavior obvious to someone with a > better understanding of Git internals? > > I did find a better way to automatically fetch tags (using tagopt > instead of adding the fetch refspec). However, the refspec doesn't > seem "wrong" in itself; in particular, `git fetch --tags` used to be > considered equivalent to specifying the refspec > "refs/tags/*:refs/tags/*" -- implying that this is a sensible refspec > [3]. So I wouldn't expect it to "break" the behavior of another > command. > > [1] https://stackoverflow.com/q/34687657/1327867 > [2] https://git-scm.com/docs/git-remote.html#git-remote-empruneem > [3] https://github.com/git/git/commit/c5a84e92a2fe9e8748e32341c344d7a6c0f52a50
These docs are really confusing, but it is working as intended, and really should be re-documented.
The `git remote prune` subcommand just ends up piggy-backing on git-fetch, whose behavior is explained here: https://git-scm.com/docs/git-fetch.html#git-fetch---prune
It's worked this way since at least v1.8.5.6, maybe at some distant point in the past it only did this for branches when invoked via git-remote as the documentation says.
RELATED:
I've actually had the reverse problem with this. I want some way to turn this behavior on without explicitly hacking the refspec, so I can do it globally in /etc/gitconfig or in ~/.gitconfig without screwing with the config of each checkout on certain machines.
You can set fetch.prune=true, but that only prunes the branches, you need to inject remote.origin.fetch into each checkout, unless I've missed some way of doing this.
I wanted to add fetch.pruneTags that would make it as if you had refs/tags/*:refs/tags/* in the fetch spec, but I haven't hacked that up yet, if anyone can see any inherent issue with that plan I'd like to know about it.