Subject: Local tag killer

From: Michael Haggerty <[email-masked]>
Date: Fri, 13 Sep 2013 04:54:26 +0200

A colleague of mine discovered, the hard way, that

    git fetch --tags --prune $REMOTE

deletes all local tags that are not present on that particular remote.
To me this seems a dangerous and poorly-documented interaction of
features and arguably a bug.

Granted, it might not be such a good idea to use local tags, as it is
all to easy to push them inadvertently and then it is difficult to
remove them permanently from a shared upstream repository because other
people might have fetched them and in turn inadvertently re-push them.

But the fact that combining two options, each of which seems safe and
reasonable for daily use, results in the death of local tags unrelated
to the remote is unexpected [1].  Also remember that the "--prune"
feature can be turned on permanently via "git config" using
"fetch.prune" or "remote.$REMOTE.prune".

Moreover, the documentation is misleading on this point:

> -p::
> --prune::
> 	After fetching, remove any remote-tracking branches which
> 	no longer exist	on the remote.

It is a stretch for references under refs/tags/ to be called
"remote-tracking branches", even if they exist as the target of the
refspec "refs/tags/*:refs/tags/*" that is implicitly added by the --tags
option.

I suggest that --prune should not touch references under refs/tags/
regardless of whether they appear on the right side of explicit or
implicit refspecs.  If pruning tags is deemed to be essential, then
there should be a specific option ("--prune-tags"?) to request it.

When looking into this, I found a test in t5510 that appears to want to
verify this very behavior:

> test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
> 	cd "$D" &&
> 	git clone . prune-tags &&
> 	cd prune-tags &&
> 	git fetch origin refs/heads/master:refs/tags/sometag &&
> 
> 	git fetch --prune --tags origin &&
> 	git rev-parse origin/master &&
> 	test_must_fail git rev-parse somebranch
> '

However, the last line seems to contain a copy-paste error and should
presumably have s/somebranch/sometag/.

Michael

[1] It would be as if "git clean" had two options "--ammonia" and
"--bleach" :-)

-- 
Michael Haggerty
[email-masked]
http://softwareswirl.blogspot.com/