# Local tag killer

23 messages from 2013-09-13 to 2013-10-01. Participants: Michael Haggerty, Junio C Hamano, John Szakmeister, Jeff King, Marc Branchaud, Nicolas Pitre, Johan Herland.
Thread: https://gitlist.dev/t/34923

## Michael Haggerty, 2013-09-13 02:54

Subject: Local tag killer
Message-ID: <52327E62.2040301@alum.mit.edu>
URL: https://gitlist.dev/e/52327E62.2040301%40alum.mit.edu

```
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
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

```

## Junio C Hamano, 2013-09-13 04:03

Subject: Re: Local tag killer
Message-ID: <CAPc5daXvCf90WYoUWC+DxRyZEQhXGL7Bd_ZJKwfoqxeKt8TADQ@mail.gmail.com>
URL: https://gitlist.dev/e/CAPc5daXvCf90WYoUWC%2BDxRyZEQhXGL7Bd_ZJKwfoqxeKt8TADQ%40mail.gmail.com
In-Reply-To: <52327E62.2040301@alum.mit.edu>

```
> 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' '

The title tells me that it wants to make sure when pruning tags it does
not touch remote-tracking branches under refs/remotes/origin/, I think.

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

I agree that somebranch must be sometag, as it wants to make sure
that --prune --tags removes the tag the other side does not have.

I also agree that the documentation is misstated; "remote-tracking branch"
may have been a convenient and well understood phrase for whoever wrote
that part, but the --prune is designed to cull extra refs in the
hierarchies into
which refs would be fetched if counterparts existed on the other side, so
culling tags that do not exist on the remote side should also be described.

```

## Junio C Hamano, 2013-09-20 22:51

Subject: Re: Local tag killer
Message-ID: <xmqqd2o3p0nk.fsf@gitster.dls.corp.google.com>
URL: https://gitlist.dev/e/xmqqd2o3p0nk.fsf%40gitster.dls.corp.google.com
In-Reply-To: <CAPc5daXvCf90WYoUWC+DxRyZEQhXGL7Bd_ZJKwfoqxeKt8TADQ@mail.gmail.com>

```
Junio C Hamano <gitster-vger@pobox.com> writes:

> I also agree that the documentation is misstated; "remote-tracking branch"
> may have been a convenient and well understood phrase for whoever wrote
> that part, but the --prune is designed to cull extra refs in the
> hierarchies into
> which refs would be fetched if counterparts existed on the other side, so
> culling tags that do not exist on the remote side should also be described.

(gleaning-leftovers mode)


 Documentation/fetch-options.txt | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index ba1fe49..a6c581b 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -41,8 +41,20 @@ ifndef::git-pull[]
 
 -p::
 --prune::
-	After fetching, remove any remote-tracking branches which
-	no longer exist	on the remote.
+
+	After fetching, remove any local ref that was not updated
+	only because the remote ref that was supposed to update it
+	was missing.
++
+For example, `git fetch origin refs/heads/*:refs/remotes/origin/*`
+tries to update local `refs/remotes/origin/frotz` if `origin` has
+`refs/heads/frotz`.  With this option, `refs/remotes/origin/frotz`
+will be removed from our repository if `origin` does not have
+`refs/heads/frotz`.
++
+This is used to remove remote-tracking branches which no longer
+exist on the remote.
+
 endif::git-pull[]
 
 ifdef::git-pull[]

```

## Michael Haggerty, 2013-09-21 06:42

Subject: Re: Local tag killer
Message-ID: <523D3FD2.4090002@alum.mit.edu>
URL: https://gitlist.dev/e/523D3FD2.4090002%40alum.mit.edu
In-Reply-To: <xmqqd2o3p0nk.fsf@gitster.dls.corp.google.com>

```
On 09/21/2013 12:51 AM, Junio C Hamano wrote:
> Junio C Hamano <gitster-vger@pobox.com> writes:
> 
>> I also agree that the documentation is misstated; "remote-tracking branch"
>> may have been a convenient and well understood phrase for whoever wrote
>> that part, but the --prune is designed to cull extra refs in the
>> hierarchies into
>> which refs would be fetched if counterparts existed on the other side, so
>> culling tags that do not exist on the remote side should also be described.
> 
> (gleaning-leftovers mode)

Thanks for following up on this with your proposed documentation patch.
 I have been researching and experimenting, and still find the use of
fetch confusing with respect to tags.  I think the problem is primarily
that the behavior is awkward, and that it would be better to change the
behavior than to document the awkward behavior.

I must have read an old version of the documentation, from which it
seemed that "git fetch --tags" fetches all tags from the remote *in
addition to* the references and tags that would otherwise be fetched.
This seems like a handy and safe feature, and I wish that this were
indeed the effect of "--tags".

But I see that the documentation for "--tags" has been changed and now
states explicitly that "--tags" is equivalent to specifying
"refs/tags/*:refs/tags/*" on the command line, overriding any configured
refspecs.  This doesn't seem like useful behavior; why would I want to
fetch tags from a remote without also updating the configured refspecs?
 And contrariwise, how can I fetch the configured refspecs *and* all
tags at the same time in a single fetch?

OK, one way to do it is to configure an explicit refspec for fetching
the tags:

[remote "origin"]
	url = [...]
	fetch = +refs/heads/*:refs/remotes/origin/*
	fetch = refs/tags/*:refs/tags/*

[Here is one oddity: even if the tags refspec doesn't have a "+" prefix,
"git fetch" will do non-ff updates to tags, presumably because of the
implicit tag-fetching behavior.]

But if I use this configuration and type "git fetch --prune", then any
local tags that are not present on the remote will be killed.

In short, when local tags are in use, or tags that are in one remote but
not another [1], then the current Git implementation makes it impossible to

- Configure "fetch.prune" or "remote.$REMOTE.prune" without preventing
the use of "fetch --tags"

- Configure default fetching of all tags (via a refspec or via
remote.$REMOTE.tagopt) without preventing the use of "fetch --prune"

- Configure "fetch.prune" or "remote.$REMOTE.prune" and the default
fetching of all tags (via a refspec or via remote.$REMOTE.tagopt) at the
same time.

This is unfortunate.

I think it would be preferable if "--prune" would *not* affect tags, and
if there were an extra option like "--prune-tags" that would have to be
used explicitly to cause tags to be pruned.  Would somebody object to
such a change?

Michael

[1] In fact, the scenario that bit my colleague was as follows: he had
just built a software release, which creates a new commit and a release
tag.  When he tried to push the commit, there was a non-ff failure due
to an upstream change.  So he ran "git fetch --prune" to get the
upstream change, and this caused the release tag (which hadn't been
pushed yet) to be lost.

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

```

## John Szakmeister, 2013-09-21 12:28

Subject: Re: Local tag killer
Message-ID: <CAEBDL5UVZERxHF5FwR66HummgjoczWGwzXwiHZtFKZGBLt6c+A@mail.gmail.com>
URL: https://gitlist.dev/e/CAEBDL5UVZERxHF5FwR66HummgjoczWGwzXwiHZtFKZGBLt6c%2BA%40mail.gmail.com
In-Reply-To: <523D3FD2.4090002@alum.mit.edu>

```
On Sat, Sep 21, 2013 at 2:42 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
> On 09/21/2013 12:51 AM, Junio C Hamano wrote:
>> Junio C Hamano <gitster-vger@pobox.com> writes:
>>
>>> I also agree that the documentation is misstated; "remote-tracking branch"
>>> may have been a convenient and well understood phrase for whoever wrote
>>> that part, but the --prune is designed to cull extra refs in the
>>> hierarchies into
>>> which refs would be fetched if counterparts existed on the other side, so
>>> culling tags that do not exist on the remote side should also be described.
>>
>> (gleaning-leftovers mode)
>
> Thanks for following up on this with your proposed documentation patch.
>  I have been researching and experimenting, and still find the use of
> fetch confusing with respect to tags.  I think the problem is primarily
> that the behavior is awkward, and that it would be better to change the
> behavior than to document the awkward behavior.

I agree with this sentiment.  I've never liked how `--tags` operates.

> I must have read an old version of the documentation, from which it
> seemed that "git fetch --tags" fetches all tags from the remote *in
> addition to* the references and tags that would otherwise be fetched.
> This seems like a handy and safe feature, and I wish that this were
> indeed the effect of "--tags".

Me too.

> But I see that the documentation for "--tags" has been changed and now
> states explicitly that "--tags" is equivalent to specifying
> "refs/tags/*:refs/tags/*" on the command line, overriding any configured
> refspecs.  This doesn't seem like useful behavior; why would I want to
> fetch tags from a remote without also updating the configured refspecs?
>  And contrariwise, how can I fetch the configured refspecs *and* all
> tags at the same time in a single fetch?
>
> OK, one way to do it is to configure an explicit refspec for fetching
> the tags:
>
> [remote "origin"]
>         url = [...]
>         fetch = +refs/heads/*:refs/remotes/origin/*
>         fetch = refs/tags/*:refs/tags/*
>
> [Here is one oddity: even if the tags refspec doesn't have a "+" prefix,
> "git fetch" will do non-ff updates to tags, presumably because of the
> implicit tag-fetching behavior.]
>
> But if I use this configuration and type "git fetch --prune", then any
> local tags that are not present on the remote will be killed.
>
> In short, when local tags are in use, or tags that are in one remote but
> not another [1], then the current Git implementation makes it impossible to
>
> - Configure "fetch.prune" or "remote.$REMOTE.prune" without preventing
> the use of "fetch --tags"
>
> - Configure default fetching of all tags (via a refspec or via
> remote.$REMOTE.tagopt) without preventing the use of "fetch --prune"
>
> - Configure "fetch.prune" or "remote.$REMOTE.prune" and the default
> fetching of all tags (via a refspec or via remote.$REMOTE.tagopt) at the
> same time.
>
> This is unfortunate.
>
> I think it would be preferable if "--prune" would *not* affect tags, and
> if there were an extra option like "--prune-tags" that would have to be
> used explicitly to cause tags to be pruned.  Would somebody object to
> such a change?

I, personally, think what you outline makes more sense.  Also, I'm
curious if `git remote update -p $REMOTE` suffers from the same
problem, if the remote was added with the `--tags` option.

-John

```

## Jeff King, 2013-09-24 07:51

Subject: Re: Local tag killer
Message-ID: <20130924075119.GD7257@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20130924075119.GD7257%40sigill.intra.peff.net
In-Reply-To: <523D3FD2.4090002@alum.mit.edu>

```
On Sat, Sep 21, 2013 at 08:42:26AM +0200, Michael Haggerty wrote:

> I think it would be preferable if "--prune" would *not* affect tags, and
> if there were an extra option like "--prune-tags" that would have to be
> used explicitly to cause tags to be pruned.  Would somebody object to
> such a change?

I think most of this problem is the way that we fetch tags straight into
the refs/tags hierarchy. You would not do:

  [remote "origin"]
  fetch = +refs/heads/*:refs/heads/*
  prune = true

unless you wanted to be a pure-mirror, because you would hose your local
changes any time you fetched. But that is _exactly_ what we do with a
refs/tags/*:refs/tags/* fetch.

If we instead moved to a default fetch refspec more like:

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

Then everything would Just Work. If you prune what the other side has
locally, that's fine. All you're doing is pruning your view of what he
has, not anything you've done locally.

The tricky part is tweaking the lookup rules so that "origin/master"
still works, and that looking for "v1.0" checks both refs/tags and
refs/remotes/*/refs/tags. And of course managing backwards
compatibility. :)

In the meantime, I'd almost be tempted to say that "--prune" should
refuse to work when we are touching anything outside of refs/remotes/.
But that would make true mirrors fail, who do want to munge their local
refs/heads/. You'd need some way to say "no, really, it's OK to prune".
Maybe let remote.*.prune be "remotes", "always", or "none", and "true"
maps to "remotes"? That's not backwards compatible, but it would be much
safer.

-Peff

```

## Marc Branchaud, 2013-09-24 13:22

Subject: Re: Local tag killer
Message-ID: <52419218.3020902@xiplink.com>
URL: https://gitlist.dev/e/52419218.3020902%40xiplink.com
In-Reply-To: <20130924075119.GD7257@sigill.intra.peff.net>

```
On 13-09-24 03:51 AM, Jeff King wrote:
> On Sat, Sep 21, 2013 at 08:42:26AM +0200, Michael Haggerty wrote:
>
>> I think it would be preferable if "--prune" would *not* affect tags, and
>> if there were an extra option like "--prune-tags" that would have to be
>> used explicitly to cause tags to be pruned.  Would somebody object to
>> such a change?
>
> I think most of this problem is the way that we fetch tags straight into
> the refs/tags hierarchy. You would not do:
>
>    [remote "origin"]
>    fetch = +refs/heads/*:refs/heads/*
>    prune = true
>
> unless you wanted to be a pure-mirror, because you would hose your local
> changes any time you fetched. But that is _exactly_ what we do with a
> refs/tags/*:refs/tags/* fetch.
>
> If we instead moved to a default fetch refspec more like:
>
>    [remote "origin"]
>    fetch = +refs/*:refs/remotes/origin/refs/*

I'm all for such a change.

You no doubt recall the lengthy discussion about remote ref namespaces 
back in 2011 [1].  That arose while planning for 1.8, but my feeble 
recollection is that the change was considered too disruptive.  It seems 
2.0 would be a better home for such work.

		M.

[1] 
http://thread.gmane.org/gmane.comp.version-control.git/165799/focus=166729

```

## Jeff King, 2013-09-25 08:22

Subject: Re: Local tag killer
Message-ID: <20130925082251.GB23238@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20130925082251.GB23238%40sigill.intra.peff.net
In-Reply-To: <52419218.3020902@xiplink.com>

```
On Tue, Sep 24, 2013 at 09:22:32AM -0400, Marc Branchaud wrote:

> >If we instead moved to a default fetch refspec more like:
> >
> >   [remote "origin"]
> >   fetch = +refs/*:refs/remotes/origin/refs/*
> 
> I'm all for such a change.
> 
> You no doubt recall the lengthy discussion about remote ref
> namespaces back in 2011 [1].  That arose while planning for 1.8, but
> my feeble recollection is that the change was considered too
> disruptive.  It seems 2.0 would be a better home for such work.

I do recall the discussion, though I did not review all of the
complications before writing this most recent mail.

I assume there are backwards compatibility issues lurking, and we may
even need a config switch to flip between old-style and new-style modes
(and leave it set to old-style at first, wait a while for people to have
a git that understands both, and then flip the default to new-style).

However, none of that is for Git 2.0. I do not think we have an exact
date set for Git 2.0, but we already have several switches ready to be
flipped.  I think Junio's plan was to do it sooner rather than later,
and not try to cram a bunch of last-minute compatibility breakages in.

-Peff

```

## Nicolas Pitre, 2013-09-25 22:54

Subject: Re: Local tag killer
Message-ID: <alpine.LFD.2.03.1309251834210.312@syhkavp.arg>
URL: https://gitlist.dev/e/alpine.LFD.2.03.1309251834210.312%40syhkavp.arg
In-Reply-To: <20130924075119.GD7257@sigill.intra.peff.net>

```
On Tue, 24 Sep 2013, Jeff King wrote:

> On Sat, Sep 21, 2013 at 08:42:26AM +0200, Michael Haggerty wrote:
> 
> > I think it would be preferable if "--prune" would *not* affect tags, and
> > if there were an extra option like "--prune-tags" that would have to be
> > used explicitly to cause tags to be pruned.  Would somebody object to
> > such a change?
> 
> I think most of this problem is the way that we fetch tags straight into
> the refs/tags hierarchy. You would not do:
> 
>   [remote "origin"]
>   fetch = +refs/heads/*:refs/heads/*
>   prune = true
> 
> unless you wanted to be a pure-mirror, because you would hose your local
> changes any time you fetched. But that is _exactly_ what we do with a
> refs/tags/*:refs/tags/* fetch.
> 
> If we instead moved to a default fetch refspec more like:
> 
>   [remote "origin"]
>   fetch = +refs/*:refs/remotes/origin/refs/*
> 
> Then everything would Just Work. If you prune what the other side has
> locally, that's fine. All you're doing is pruning your view of what he
> has, not anything you've done locally.
> 
> The tricky part is tweaking the lookup rules so that "origin/master"
> still works, and that looking for "v1.0" checks both refs/tags and
> refs/remotes/*/refs/tags. And of course managing backwards
> compatibility. :)

Cheers !!!

I remember participating to a discussion about this like 2.5 years ago:

http://news.gmane.org/group/gmane.comp.version-control.git/thread=165799

The flat tag namespace remains my major annoyance with git IMHO.


Nicolas

```

## Michael Haggerty, 2013-09-28 12:20

Subject: Re: Local tag killer
Message-ID: <5246C975.1050504@alum.mit.edu>
URL: https://gitlist.dev/e/5246C975.1050504%40alum.mit.edu
In-Reply-To: <alpine.LFD.2.03.1309251834210.312@syhkavp.arg>

```
On 09/26/2013 12:54 AM, Nicolas Pitre wrote:
> On Tue, 24 Sep 2013, Jeff King wrote:
>> I think most of this problem is the way that we fetch tags straight into
>> the refs/tags hierarchy. You would not do:
>>
>>   [remote "origin"]
>>   fetch = +refs/heads/*:refs/heads/*
>>   prune = true
>>
>> unless you wanted to be a pure-mirror, because you would hose your local
>> changes any time you fetched. But that is _exactly_ what we do with a
>> refs/tags/*:refs/tags/* fetch.
>>
>> If we instead moved to a default fetch refspec more like:
>>
>>   [remote "origin"]
>>   fetch = +refs/*:refs/remotes/origin/refs/*
>>
>> Then everything would Just Work. [...]
> 
> I remember participating to a discussion about this like 2.5 years ago:
> 
> http://news.gmane.org/group/gmane.comp.version-control.git/thread=165799
> 
> The flat tag namespace remains my major annoyance with git IMHO.

I just reviewed that old thread to determine its relevance to the
present discussion.  For the benefit of the other readers, here is a
summary of the main points that I got out of it.

The main proposal under discussion was that of Johan Herland:

    http://article.gmane.org/gmane.comp.version-control.git/165885

Nicolas made the two best arguments for the necessity of
separate tag namespaces per remote in *some* form:

> The extraordinary misfeature of the tag namespace at the moment
> comes from the fact that whenever you add a remote repo to fetch,
> and do fetch it, then your flat tag namespace gets polluted with all
> the tags the remote might have.  If you decide to delete some of
> those remote branches, the tags that came with it are still there
> and indistinguishable from other tags making it a real pain to sort
> out.
>
> -- http://article.gmane.org/gmane.comp.version-control.git/166108

and

> Let's take the OpenOffice vs LibreOffice as an example.  What if I
> want both in my repository so I can easily perform diffs between
> those independent branches?  They may certainly end up producing
> releases with the same version numbers (same tag name) but different
> content (different tag references).
>
> -- http://article.gmane.org/gmane.comp.version-control.git/166749

Other discussion and open issues regarding a ref namespace reorg:

* What exactly would be the ambiguity rules for references with the same
  name that appear in multiple remotes' namespaces?

  * Are references to two annotated tags considered the same if they
    refer to the same SHA-1, even if the annotated tags are different?
    What about an annotated vs an unannotated tag?  The consensus
    seemed to be "no".

  * Do they depend on how the reference is being used?  Yes, sometimes
    only a SHA-1 is needed, in which case multiple agreeing references
    shouldn't be a problem.  Other times the DWIM caller needs the
    full refname (e.g., "git push" pushes to different locations
    depending on whether the source is a branch or tag), in which case
    the rules would have to be more nuanced.

  * Should the same ambiguity rules be applied to other references
    (e.g., branches)?

  * What if a branch and a tag have the same name?

    * Nicolas Pitre suggested that usually they should be accepted if
      they have the same value, and if the refname matters then the
      branch should take precedence (with a warning).

    * Peff pointed out that currently dwim_ref prefers tags, but that
      Junio has said that that behavior was arbitrary [and by
      implication could be changed].  He suggested:

      > For dwim_ref, it prefers the tag and issues a warning. For
      > git-push, it complains about the ambiguity and dies. For git
      > checkout, we prefer the head. For git-tag, we prefer the tag
      > (though I think that only matters for "git tag -d").
      >
      > -- http://article.gmane.org/gmane.comp.version-control.git/166290

* What should "name-rev", "describe", "--decorate" output?  See
  discussion here:

      http://article.gmane.org/gmane.comp.version-control.git/165911

* "fetch" should probably warn if it ends up fetching a tag with the
  same name (according to the refname disambiguation rules) but value
  that conflicts with an existing tag in a different namespace.

* Do we need some pathspec modifier (e.g., "~") to specify that the
  corresponding references should be auto-followed in the manner
  currently done for refs/tags/*?  Or is auto-following maybe not
  needed at all anymore?:

      http://article.gmane.org/gmane.comp.version-control.git/160726

  Junio thought, and Johan agreed, that tag auto-following should still
  be done for repositories that use the old ref namespace format.  But
  perhaps this could be special-cased via a config setting rather than
  built into the refspec syntax.

* How would somebody (e.g., an interim maintainer) suck down tags from
  a project into his own refs/tags/* namespace?  (Would it even be
  necessary?)  Should there be a tool for this?  [It seems to me that
  something like

      git fetch . refs/remotes/origin/tags/*:refs/tags/*

  would do the trick, as long as pruning were turned off.]

* What special handling (if any) is required for
  refs/remotes/$REMOTE/HEAD?

  * According to Junio, HEAD is meant to indicate which branch is the
    "main" branch of the remote.  It is not transferred via the
    protocol, but rather guessed at by the client's "clone" process:

        http://article.gmane.org/gmane.comp.version-control.git/166694
        http://article.gmane.org/gmane.comp.version-control.git/166740

* How would this help somebody who wants to fetch content from multiple
  projects (e.g., git, gitk, gitgui) into a single repo?  There might
  be tags with the same names but very different meanings, and it would
  be awkward if there were ambiguity warnings all over the place.
  [Would it work to configure the fetching repo something like

  [remote "gitk-origin"]
          fetch = refs/tags/*:refs/remotes/gitk-origin/tags/gitk/*

  and to refer to a hypothetical gitk tag "v1.2.3" as "gitk/1.2.3"?
  Admittedly this is somewhat ambiguous with the proposed DWIM pattern
  <REMOTE>/<TAGNAME>.]

* It might be nice to have a command like

      git push $REMOTE --interactive

  that allows the user to choose interactively which branches/tags to
  push

  -- http://article.gmane.org/gmane.comp.version-control.git/166700

I hope that saves somebody the time of reading the whole thread
(though admittedly my summary is not especially short either).


As far as I can tell, the division of tags into remote-specific
namespaces would be another way of preventing the problem of tags being
pruned too aggressively.  But given that such a big change would be a
huge development effort, implementing something like the following
might be a quicker fix and would not conflict with a hypothetical
future ref namespace reorganization:

1. Limit "git fetch --prune" to only pruning references that are under
   refs/remotes/*

2. Add a new option --prune-tags that removes the above limitation

3. And the above two changes would make this one possible: Change the
   meaning of the --tags option to mean "fetch all tags *in addition
   to* (rather than *instead of*) the references that would otherwise
   be fetched".

Comments?

@Johan, I know that you were working on the ref-namespace issue at
GitMerge.  Did your work get anywhere?  Are you still working on it?
Have you documented somewhere any new insights that you have gained
about the problem space?

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

```

## Johan Herland, 2013-09-28 21:42

Subject: Re: Local tag killer
Message-ID: <CALKQrgeJn1J4ntE_2Lr7Et+Oao=vB1FE6nLfaFJOvLHJLzG9tA@mail.gmail.com>
URL: https://gitlist.dev/e/CALKQrgeJn1J4ntE_2Lr7Et%2BOao%3DvB1FE6nLfaFJOvLHJLzG9tA%40mail.gmail.com
In-Reply-To: <5246C975.1050504@alum.mit.edu>

```
On Sat, Sep 28, 2013 at 2:20 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
> I just reviewed that old thread to determine its relevance to the
> present discussion.  For the benefit of the other readers, here is a
> summary of the main points that I got out of it.

I want to thank you immensely for the summary below. It really helps me
clear my own thoughts on this topic, and is an excellent base for
discussing how to advance on it.

> The main proposal under discussion was that of Johan Herland:
>
>     http://article.gmane.org/gmane.comp.version-control.git/165885
>
> Nicolas made the two best arguments for the necessity of
> separate tag namespaces per remote in *some* form:
>
>> The extraordinary misfeature of the tag namespace at the moment
>> comes from the fact that whenever you add a remote repo to fetch,
>> and do fetch it, then your flat tag namespace gets polluted with all
>> the tags the remote might have.  If you decide to delete some of
>> those remote branches, the tags that came with it are still there
>> and indistinguishable from other tags making it a real pain to sort
>> out.
>>
>> -- http://article.gmane.org/gmane.comp.version-control.git/166108
>
> and
>
>> Let's take the OpenOffice vs LibreOffice as an example.  What if I
>> want both in my repository so I can easily perform diffs between
>> those independent branches?  They may certainly end up producing
>> releases with the same version numbers (same tag name) but different
>> content (different tag references).
>>
>> -- http://article.gmane.org/gmane.comp.version-control.git/166749

I'd also like to mention my initial motivation for the proposal: a
natural way to organize other types of remote refs (notes, replace
refs, etc.). The separate tag namespace came about as a natural
(and IMHO quite useful) consequence of the proposed reorganization
of refs/remotes/*.

> Other discussion and open issues regarding a ref namespace reorg:
>
> * What exactly would be the ambiguity rules for references with the same
>   name that appear in multiple remotes' namespaces?
>
>   * Are references to two annotated tags considered the same if they
>     refer to the same SHA-1, even if the annotated tags are different?
>     What about an annotated vs an unannotated tag?  The consensus
>     seemed to be "no".
>
>   * Do they depend on how the reference is being used?  Yes, sometimes
>     only a SHA-1 is needed, in which case multiple agreeing references
>     shouldn't be a problem.  Other times the DWIM caller needs the
>     full refname (e.g., "git push" pushes to different locations
>     depending on whether the source is a branch or tag), in which case
>     the rules would have to be more nuanced.

Could we try to classify all ref lookups as either ref _name_ lookups
(in which case only a single, matching full refname is acceptable), or
ref _value_ lookups (in which case multiple matching names are allowed,
as long as they all point to the same SHA-1)? There are some complicated
cases (e.g. describe) which needs more thought, but if we can agree on
a mechanism for dealing with all the simpler cases, that might help
inform how to deal with the complicated ones.

>   * Should the same ambiguity rules be applied to other references
>     (e.g., branches)?

IMHO, yes.

>   * What if a branch and a tag have the same name?

IMHO, it depends on the context of the lookup. Some commands (e.g.
branch, tag) are clearly only interested in one ref type, and should
not care about other ref types at all.

For other lookups (e.g. rev-list, rev-parse), IMHO it depends on
whether they're looking up ref _names_ or ref _values_. In the former
case, ambiguity is always an error, while in the latter case it's not,
provided they agree on the SHA-1 (although maybe warning about
ambiguity might be appropriate in some contexts).

>     * Nicolas Pitre suggested that usually they should be accepted if
>       they have the same value, and if the refname matters then the
>       branch should take precedence (with a warning).
>
>     * Peff pointed out that currently dwim_ref prefers tags, but that
>       Junio has said that that behavior was arbitrary [and by
>       implication could be changed].  He suggested:
>
>       > For dwim_ref, it prefers the tag and issues a warning. For
>       > git-push, it complains about the ambiguity and dies. For git
>       > checkout, we prefer the head. For git-tag, we prefer the tag
>       > (though I think that only matters for "git tag -d").
>       >
>       > -- http://article.gmane.org/gmane.comp.version-control.git/166290
>
> * What should "name-rev", "describe", "--decorate" output?  See
>   discussion here:
>
>       http://article.gmane.org/gmane.comp.version-control.git/165911

AFAICS, "name-rev" and "--decorate" are the simple cases: Use the
shortest possible name which is still completely unambiguous in the
current repo.

For "describe", we want to use a tag name with no prefix (i.e. only
"$tag", not "$remote/$tag" or "$remote/tags/$tag" etc.). We also
probably want to prefer tags from some remotes over tags from other
remotes. Maybe something like:

  git describe --tags-from $remote

where the default behavior (i.e. given no --tags-from) would be to
assume

  --tags-from $(branch.$current.remote)
  --tags-from origin
  --tags-from . # local tags

or some combination of those.

> * "fetch" should probably warn if it ends up fetching a tag with the
>   same name (according to the refname disambiguation rules) but value
>   that conflicts with an existing tag in a different namespace.
>
> * Do we need some pathspec modifier (e.g., "~") to specify that the
>   corresponding references should be auto-followed in the manner
>   currently done for refs/tags/*?  Or is auto-following maybe not
>   needed at all anymore?:
>
>       http://article.gmane.org/gmane.comp.version-control.git/160726
>
>   Junio thought, and Johan agreed, that tag auto-following should still
>   be done for repositories that use the old ref namespace format.  But
>   perhaps this could be special-cased via a config setting rather than
>   built into the refspec syntax.

When using separate remote tag namespaces, I believe tag auto-following
is no longer needed. Instead the default refspec would simply fetch all
tags into the remote tag namespace.

As for the config setting, I have thought much about whether it is
possible to introduce remote ref namespaces while retaining backwards
compatibility, all _without_ having an explicit config switch. However,
I have more or less arrived at the conclusion that a "clean break" with
a config switch that selects either old or new ref layouts (and
associated semantics/behavior) is preferable.

> * How would somebody (e.g., an interim maintainer) suck down tags from
>   a project into his own refs/tags/* namespace?  (Would it even be
>   necessary?)

I'm not convinced it would be necessary. I have yet to see a case where
a (suitably unambiguous) remote tag would not fulfill the same purpose
as the equivalent local tag. The only exception is for dealing with
ambiguous remote tags, where a local tag could be created to serve as a
tie-breaker.

>   Should there be a tool for this?  [It seems to me that something like
>
>       git fetch . refs/remotes/origin/tags/*:refs/tags/*
>
>   would do the trick, as long as pruning were turned off.]

AFAICS, that fetch command should work (and should IMHO be unaffected
by fetch.prune or remote.$remote.prune in the configuration).

> * What special handling (if any) is required for
>   refs/remotes/$REMOTE/HEAD?
>
>   * According to Junio, HEAD is meant to indicate which branch is the
>     "main" branch of the remote.  It is not transferred via the
>     protocol, but rather guessed at by the client's "clone" process:
>
>         http://article.gmane.org/gmane.comp.version-control.git/166694
>         http://article.gmane.org/gmane.comp.version-control.git/166740

IMHO, if we want HEAD to accurately represent the "main" branch of the
remote, then we must also extend the protocol to contain it, so that it
does not go stale or suffer at the mercy of "guesswork".

> * How would this help somebody who wants to fetch content from multiple
>   projects (e.g., git, gitk, gitgui) into a single repo?  There might
>   be tags with the same names but very different meanings, and it would
>   be awkward if there were ambiguity warnings all over the place.
>   [Would it work to configure the fetching repo something like
>
>   [remote "gitk-origin"]
>           fetch = refs/tags/*:refs/remotes/gitk-origin/tags/gitk/*
>
>   and to refer to a hypothetical gitk tag "v1.2.3" as "gitk/1.2.3"?
>   Admittedly this is somewhat ambiguous with the proposed DWIM pattern
>   <REMOTE>/<TAGNAME>.]

Only if you also had a remote called "gitk". ;)

An alternative way to solve the problem of many ambiguity warnings:
If we define the rules so that local tags always override remote tags,
you could simply fetch the tags from your preferred remote into your
local tag namespace (as discussed above).

Personally, I would rather set up the configuration like this:

  [remote "gitk"]
          fetch = refs/tags/*:refs/remotes/gitk/tags/*

(i.e. keeping the default refspec) and then use "gitk/v1.2.3",
"git/v.1.2.3", "gitgui/v1.2.3" to disambiguate between the tags.

> * It might be nice to have a command like
>
>       git push $REMOTE --interactive
>
>   that allows the user to choose interactively which branches/tags to
>   push
>
>   -- http://article.gmane.org/gmane.comp.version-control.git/166700

I like that idea, but I think it's somewhat peripheral to the ref
namespace discussion.

> I hope that saves somebody the time of reading the whole thread
> (though admittedly my summary is not especially short either).
>
>
> As far as I can tell, the division of tags into remote-specific
> namespaces would be another way of preventing the problem of tags being
> pruned too aggressively.  But given that such a big change would be a
> huge development effort, implementing something like the following
> might be a quicker fix and would not conflict with a hypothetical
> future ref namespace reorganization:
>
> 1. Limit "git fetch --prune" to only pruning references that are under
>    refs/remotes/*
>
> 2. Add a new option --prune-tags that removes the above limitation
>
> 3. And the above two changes would make this one possible: Change the
>    meaning of the --tags option to mean "fetch all tags *in addition
>    to* (rather than *instead of*) the references that would otherwise
>    be fetched".

Agreed. The ref namespace topic clearly dwarfs the issue that started
this thread.

> @Johan, I know that you were working on the ref-namespace issue at
> GitMerge.  Did your work get anywhere? Are you still working on it?

I posted a couple of patch series dealing with _some_ preliminary
issues and adding some initial behavior changes. The first one was
parked in 'pu':

  https://git.kernel.org/cgit/git/git.git/commit/?h=pu&id=07e56ed

but has since been stuck in limbo, since we decided to roll it into
the larger series:

  http://article.gmane.org/gmane.comp.version-control.git/225137

The larger series was last posted here:

  http://thread.gmane.org/gmane.comp.version-control.git/223981

Since then, regrettably, not much has happened. I've now rebased the
series (still unfinished) onto v1.8.4 (no conflicts, still passes all
tests), and pushed it to my GitHub account:

  https://github.com/jherland/git/commits/peers-resurrect

That said, there are probably things in that series I'd like to revise,
e.g. introducing the config switch controlling new vs. old behavior as
early as possible, and reverting back to using refs/remotes/* instead
of refs/peers/*.

> Have you documented somewhere any new insights that you have gained
> about the problem space?

I think this (hideously long) reply should cover it...


Have fun! :)

...Johan

--
Johan Herland, <johan@herland.net>
www.herland.net

```

## Michael Haggerty, 2013-09-29 04:29

Subject: Re: Local tag killer
Message-ID: <5247ACB9.40208@alum.mit.edu>
URL: https://gitlist.dev/e/5247ACB9.40208%40alum.mit.edu
In-Reply-To: <CALKQrgeJn1J4ntE_2Lr7Et+Oao=vB1FE6nLfaFJOvLHJLzG9tA@mail.gmail.com>

```
On 09/28/2013 11:42 PM, Johan Herland wrote:
> On Sat, Sep 28, 2013 at 2:20 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
>> [...]
>> Nicolas made the two best arguments for the necessity of
>> separate tag namespaces per remote in *some* form:
>> [...]
> 
> I'd also like to mention my initial motivation for the proposal: a
> natural way to organize other types of remote refs (notes, replace
> refs, etc.). The separate tag namespace came about as a natural
> (and IMHO quite useful) consequence of the proposed reorganization
> of refs/remotes/*.

ACK.

>> Other discussion and open issues regarding a ref namespace reorg:
>>
>> * What exactly would be the ambiguity rules for references with the same
>>   name that appear in multiple remotes' namespaces?
>>
>>   * Are references to two annotated tags considered the same if they
>>     refer to the same SHA-1, even if the annotated tags are different?
>>     What about an annotated vs an unannotated tag?  The consensus
>>     seemed to be "no".
>>
>>   * Do they depend on how the reference is being used?  Yes, sometimes
>>     only a SHA-1 is needed, in which case multiple agreeing references
>>     shouldn't be a problem.  Other times the DWIM caller needs the
>>     full refname (e.g., "git push" pushes to different locations
>>     depending on whether the source is a branch or tag), in which case
>>     the rules would have to be more nuanced.
> 
> Could we try to classify all ref lookups as either ref _name_ lookups
> (in which case only a single, matching full refname is acceptable), or
> ref _value_ lookups (in which case multiple matching names are allowed,
> as long as they all point to the same SHA-1)? There are some complicated
> cases (e.g. describe) which needs more thought, but if we can agree on
> a mechanism for dealing with all the simpler cases, that might help
> inform how to deal with the complicated ones.

Yes, name vs. value lookups is a useful distinction.

> [...]
>> * How would somebody (e.g., an interim maintainer) suck down tags from
>>   a project into his own refs/tags/* namespace?  (Would it even be
>>   necessary?)
> 
> I'm not convinced it would be necessary. I have yet to see a case where
> a (suitably unambiguous) remote tag would not fulfill the same purpose
> as the equivalent local tag. The only exception is for dealing with
> ambiguous remote tags, where a local tag could be created to serve as a
> tie-breaker.

I guess I was wondering how the interim maintainer would get Junio's
tags into his public repo (which he would want to do, so that users can
get everything from a single clone).

I think that the new version of "git push --tags" should *not* push all
tags from all remotes; it should push only refs/tags, like now.  So I
was thinking that the interim maintainer would want to import Junio's
tags into his own namespace, then

    git push --tags $URL

But I guess it would be cleaner just to push using an explicit refspec:

    git push $URL 'refs/remotes/origin/tags/*:refs/tags/*'

>> [...]
>> * How would this help somebody who wants to fetch content from multiple
>>   projects (e.g., git, gitk, gitgui) into a single repo?  There might
>>   be tags with the same names but very different meanings, and it would
>>   be awkward if there were ambiguity warnings all over the place.
>>   [Would it work to configure the fetching repo something like
>>
>>   [remote "gitk-origin"]
>>           fetch = refs/tags/*:refs/remotes/gitk-origin/tags/gitk/*
>>
>>   and to refer to a hypothetical gitk tag "v1.2.3" as "gitk/1.2.3"?
>>   Admittedly this is somewhat ambiguous with the proposed DWIM pattern
>>   <REMOTE>/<TAGNAME>.]
> 
> Only if you also had a remote called "gitk". ;)

True.

> An alternative way to solve the problem of many ambiguity warnings:
> If we define the rules so that local tags always override remote tags,
> you could simply fetch the tags from your preferred remote into your
> local tag namespace (as discussed above).
> 
> Personally, I would rather set up the configuration like this:
> 
>   [remote "gitk"]
>           fetch = refs/tags/*:refs/remotes/gitk/tags/*
> 
> (i.e. keeping the default refspec) and then use "gitk/v1.2.3",
> "git/v.1.2.3", "gitgui/v1.2.3" to disambiguate between the tags.

But if there were more than one remote providing gitk tags, it would be
difficult to grab a tag without caring where it came from.  And where
would I create a local gitk-scope tag?

I wonder whether remotes.group could sensibly be used to group remotes
into logical groups for value lookups:

    [remotes]
            gitk = gitk-origin
            gitk = second-gitk-repo

Then DWIM could be taught to seek "gitk/foo" under
"refs/remotes/gitk-origin/tags/foo" and
"refs/remotes/second-gitk-repo/tags/foo" in addition to
"refs/tags/gitk/foo" (insisting, of course, that if more than one of
these are present that they are all consistent).

Remote groups might also be used to configure the remotes that describe
considers when describing a commit:

    [remotes]
            describe = junio
            describe = jrn

or maybe (using the above config)

    git describe --remote-group=gitk

>> [...]
>> @Johan, I know that you were working on the ref-namespace issue at
>> GitMerge.  Did your work get anywhere? Are you still working on it?
> 
> I posted [...]

Thanks for your comments, and for the status update!

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

```

## Johan Herland, 2013-09-29 09:30

Subject: Re: Local tag killer
Message-ID: <CALKQrgdG3FzA=8A9TyuGGumqWJ05zYK1r2uaAOrhNaAUju-6jw@mail.gmail.com>
URL: https://gitlist.dev/e/CALKQrgdG3FzA%3D8A9TyuGGumqWJ05zYK1r2uaAOrhNaAUju-6jw%40mail.gmail.com
In-Reply-To: <5247ACB9.40208@alum.mit.edu>

```
On Sun, Sep 29, 2013 at 6:29 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
> I wonder whether remotes.group could sensibly be used to group remotes
> into logical groups for value lookups:
>
>     [remotes]
>             gitk = gitk-origin
>             gitk = second-gitk-repo
>
> Then DWIM could be taught to seek "gitk/foo" under
> "refs/remotes/gitk-origin/tags/foo" and
> "refs/remotes/second-gitk-repo/tags/foo" in addition to
> "refs/tags/gitk/foo" (insisting, of course, that if more than one of
> these are present that they are all consistent).

This is an interesting idea. AFAICS, remotes.<group> is currently only
used by "git remote update" and "git fetch". According to git-remote(1)
it's used like this:

    [git remote] update
        Fetch updates for a named set of remotes in the repository
        as defined by remotes.<group>. If a named group is not
        specified on the command line, the configuration parameter
        remotes.default will be used; if remotes.default is not
        defined, all remotes which do not have the configuration
        parameter remote.<name>.skipDefaultUpdate set to true will
        be updated. (See git-config(1)).

I believe this would work well when extended to ref lookup as well:

 - Defining remotes.$group allows you to lookup refs across the grouped
   remotes by using the "$group/<ref>" syntax, as you describe above.

 - If remotes.default is defined, ref lookup happens by default across
   only those remotes, i.e. "$tag" will be sought under refs/tags/$tag
   and then refs/remotes/$remote/tags/$tag for each $remote in
   remotes.default.

 - If remotes.default is not defined, ref lookup happens across all
   remotes. This is analogous to what happens with tags today; they
   are all dumped into refs/tags/* and lookup considers all of them.

> Remote groups might also be used to configure the remotes that describe
> considers when describing a commit:
>
>     [remotes]
>             describe = junio
>             describe = jrn
>
> or maybe (using the above config)
>
>     git describe --remote-group=gitk

Hmm. I'd like to apply the same rules here, to stay consistent:

 - "git describe --from=$remote1 --from=$remote2" considers tags
   from refs/remotes/$remote1/tags/* and refs/remotes/$remote2/tags/*

 - "git describe --from=$group" considers tags from
   refs/remotes/$remote/tags/* for each $remote in $group

 - "git describe" considers tags from all remotes mentioned in
   remotes.default, or _all_ remotes is remotes.default is unset.

Additionally:

 - "git describe" (without --from) also considers (and prefers?) local
   tags.

 - "git describe --from=foo" does NOT consider local tags, but will
   also consider them if "--from=." is used.


...Johan

--
Johan Herland, <johan@herland.net>
www.herland.net

```

## Marc Branchaud, 2013-09-30 15:24

Subject: Re: Local tag killer
Message-ID: <52499797.9030100@xiplink.com>
URL: https://gitlist.dev/e/52499797.9030100%40xiplink.com
In-Reply-To: <5247ACB9.40208@alum.mit.edu>

```
On 13-09-29 12:29 AM, Michael Haggerty wrote:
> On 09/28/2013 11:42 PM, Johan Herland wrote:
>> On Sat, Sep 28, 2013 at 2:20 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
>> [...]
>>> * How would somebody (e.g., an interim maintainer) suck down tags from
>>>   a project into his own refs/tags/* namespace?  (Would it even be
>>>   necessary?)
>>
>> I'm not convinced it would be necessary. I have yet to see a case where
>> a (suitably unambiguous) remote tag would not fulfill the same purpose
>> as the equivalent local tag. The only exception is for dealing with
>> ambiguous remote tags, where a local tag could be created to serve as a
>> tie-breaker.
> 
> I guess I was wondering how the interim maintainer would get Junio's
> tags into his public repo (which he would want to do, so that users can
> get everything from a single clone).
> 
> I think that the new version of "git push --tags" should *not* push all
> tags from all remotes; it should push only refs/tags, like now.  So I
> was thinking that the interim maintainer would want to import Junio's
> tags into his own namespace, then
> 
>     git push --tags $URL
> 
> But I guess it would be cleaner just to push using an explicit refspec:
> 
>     git push $URL 'refs/remotes/origin/tags/*:refs/tags/*'

(Thanks for the awesome summary!)

You seem to be considering the case of an interim maintainer who, prior to
becoming the maintainer, has his own clone of the "official" repo and now
wants to make his clone the "official" repo, perhaps only temporarily.

But what if the interim maintainer has his own tags in his clone?  What if,
after he is no longer the interim maintainer, he wants to remove the
"official" tags from his clone's local namespace?  The interim maintainer
might also have his own branches in his clone, which shouldn't be part of an
"official" repo.

It seems to me that an interim maintainer would be wise to simply mirror the
"official" repo and publish with that mirror.  So the gymnastics you're
contemplating don't seem necessary to me.

>>> [...]
>>> * How would this help somebody who wants to fetch content from multiple
>>>   projects (e.g., git, gitk, gitgui) into a single repo?  There might
>>>   be tags with the same names but very different meanings, and it would
>>>   be awkward if there were ambiguity warnings all over the place.

Why would there be ambiguity warnings?  The fetch command shouldn't issue any
warnings, since all the remotes' names get safely tucked away in distinct
namespaces.

Are we talking about DWIM warnings?  Aside from git-describe I don't see why
such warnings would be a problem.  To DWIM-resolve a tag name look in
refs/tags/* and refs/remotes/*/tags/* -- much like it's done for branches
already.  If a tag name has multiple matches then it's ambiguous.  Git could
be clever and check for matching SHA1 values, but why bother?  It almost
seems like a disservice to silently disambiguate such names.  I would think a
user would prefer to know about any possible ambiguities, rather than have
some suddenly appear (and maybe also disappear).

And as for git-describe, I think it should only consider remote namespaces
when asked to via a command-line option or configuration setting (again
following the behaviour of git-branch).  Let whoever implements such an
option define whatever disambiguation rules they like.  Although I'd suggest
that the first implementation be very simple so that we can learn how people
expect it to work.  We may just find that users don't want git-describe to
consider remote namespaces at all.

Aside from that, I guess I just don't see a problem with using the existing
branch name disambiguation rules.  Am I missing something?

		M.

```

## Nicolas Pitre, 2013-09-30 15:52

Subject: Re: Local tag killer
Message-ID: <alpine.LFD.2.03.1309301138200.6331@syhkavp.arg>
URL: https://gitlist.dev/e/alpine.LFD.2.03.1309301138200.6331%40syhkavp.arg
In-Reply-To: <52499797.9030100@xiplink.com>

```
On Mon, 30 Sep 2013, Marc Branchaud wrote:

> Why would there be ambiguity warnings?  The fetch command shouldn't issue any
> warnings, since all the remotes' names get safely tucked away in distinct
> namespaces.
> 
> Are we talking about DWIM warnings?  Aside from git-describe I don't see why
> such warnings would be a problem.  To DWIM-resolve a tag name look in
> refs/tags/* and refs/remotes/*/tags/* -- much like it's done for branches
> already.  If a tag name has multiple matches then it's ambiguous.  Git could
> be clever and check for matching SHA1 values, but why bother?  It almost
> seems like a disservice to silently disambiguate such names.  I would think a
> user would prefer to know about any possible ambiguities, rather than have
> some suddenly appear (and maybe also disappear).

Consider that I have in my Linux kernel tree:

- a remote branch corresponding to Linus' master tree

- multiple remote branches corresponding to Linux stable branches

- a remote for linux-next which is a repo constantly being rebased

Now all those repositories share the mainline tags from Linus' repo and 
they add some more of they own which are not shared.  So if they all 
have a v3.11 tag that resolve to the same SHA1, then there is 
effectively no ambiguity at all and git should not warn at all.

*However* if one of those v3.11 tags does not agree with the others 
_then_ I want to be warned about it.

So having multiple matching tags that do resolve to the same SHA1 across 
different remote repositories _is_ the norm and should work 
transparently.


Nicolas

```

## Marc Branchaud, 2013-09-30 19:16

Subject: Re: Local tag killer
Message-ID: <5249CDF7.4050904@xiplink.com>
URL: https://gitlist.dev/e/5249CDF7.4050904%40xiplink.com
In-Reply-To: <alpine.LFD.2.03.1309301138200.6331@syhkavp.arg>

```
On 13-09-30 11:52 AM, Nicolas Pitre wrote:
> On Mon, 30 Sep 2013, Marc Branchaud wrote:
> 
>> Why would there be ambiguity warnings?  The fetch command shouldn't issue any
>> warnings, since all the remotes' names get safely tucked away in distinct
>> namespaces.
>>
>> Are we talking about DWIM warnings?  Aside from git-describe I don't see why
>> such warnings would be a problem.  To DWIM-resolve a tag name look in
>> refs/tags/* and refs/remotes/*/tags/* -- much like it's done for branches
>> already.  If a tag name has multiple matches then it's ambiguous.  Git could
>> be clever and check for matching SHA1 values, but why bother?  It almost
>> seems like a disservice to silently disambiguate such names.  I would think a
>> user would prefer to know about any possible ambiguities, rather than have
>> some suddenly appear (and maybe also disappear).
> 
> Consider that I have in my Linux kernel tree:
> 
> - a remote branch corresponding to Linus' master tree
> 
> - multiple remote branches corresponding to Linux stable branches
> 
> - a remote for linux-next which is a repo constantly being rebased
> 
> Now all those repositories share the mainline tags from Linus' repo and 
> they add some more of they own which are not shared.  So if they all 
> have a v3.11 tag that resolve to the same SHA1, then there is 
> effectively no ambiguity at all and git should not warn at all.

Thanks, this example helps very much.

> *However* if one of those v3.11 tags does not agree with the others 
> _then_ I want to be warned about it.

Hmmm.  What behaviour would you like if you also had some non-Linux remote,
say for some driver code or something, that also had a v3.11 tag?  I presume
you want commands like
	git checkout -b my-topic v3.11
to do the Right Thing, but what's the right thing for you here?

> So having multiple matching tags that do resolve to the same SHA1 across 
> different remote repositories _is_ the norm and should work 
> transparently.

My suggestion for your example is that if some remote's tags are so
important/useful then you're better off importing them into your local tag
namespace (e.g. "git fetch Linus refs/tags/*:refs/tags/*").  By making the
remote's tags local, you're expressly telling git that they should be
considered for DWIMery, git-describe, etc.

I feel this approach lets us avoid having to somehow teach git which remote's
"v3.11" tags are important enough to merit an ambiguity warning and which
aren't.  Plus you get what I think you want, which is the current behaviour.

If this works for you, maybe it gives us a way forward:  All the DWIM
machinery should only consider the local namespace, perhaps with options to
explicitly ask it to expand its search, and we leave it up to the user to
specify which remotes' namespaces should be imported into the local namespace?

		M.

```

## Nicolas Pitre, 2013-09-30 20:08

Subject: Re: Local tag killer
Message-ID: <alpine.LFD.2.03.1309301527270.6331@syhkavp.arg>
URL: https://gitlist.dev/e/alpine.LFD.2.03.1309301527270.6331%40syhkavp.arg
In-Reply-To: <5249CDF7.4050904@xiplink.com>

```
On Mon, 30 Sep 2013, Marc Branchaud wrote:

> On 13-09-30 11:52 AM, Nicolas Pitre wrote:
> > Consider that I have in my Linux kernel tree:
> > 
> > - a remote branch corresponding to Linus' master tree
> > 
> > - multiple remote branches corresponding to Linux stable branches
> > 
> > - a remote for linux-next which is a repo constantly being rebased
> > 
> > Now all those repositories share the mainline tags from Linus' repo and 
> > they add some more of they own which are not shared.  So if they all 
> > have a v3.11 tag that resolve to the same SHA1, then there is 
> > effectively no ambiguity at all and git should not warn at all.
> 
> Thanks, this example helps very much.
> 
> > *However* if one of those v3.11 tags does not agree with the others 
> > _then_ I want to be warned about it.
> 
> Hmmm.  What behaviour would you like if you also had some non-Linux remote,
> say for some driver code or something, that also had a v3.11 tag?

I want git to complain and bail out, maybe suggesting that I should use 
"driver_something/tag/v3.11" to disambiguate the tag.

> I presume
> you want commands like
> 	git checkout -b my-topic v3.11
> to do the Right Thing, but what's the right thing for you here?

git itself can't know it.  So the best git could do is to list 
conflicting tags with the shortest path that makes them unambiguous and 
suggest that I try again with one of them.

> > So having multiple matching tags that do resolve to the same SHA1 across 
> > different remote repositories _is_ the norm and should work 
> > transparently.
> 
> My suggestion for your example is that if some remote's tags are so
> important/useful then you're better off importing them into your local tag
> namespace (e.g. "git fetch Linus refs/tags/*:refs/tags/*").  By making the
> remote's tags local, you're expressly telling git that they should be
> considered for DWIMery, git-describe, etc.

Sure, it is probably a good thing semantically to give priority to local 
tags when they exist. However...

> I feel this approach lets us avoid having to somehow teach git which remote's
> "v3.11" tags are important enough to merit an ambiguity warning and which
> aren't.  Plus you get what I think you want, which is the current behaviour.

But I disagree here.  Most people simply won't care about local tags 
since the remote tags are sufficient for what they need.  And if they 
have multiple remotes in their repository then it is most likely to be 
different forks of the same project sharing mostly the same tags, and 
where those tags diverge then they're most likely to have different tag 
names as well.  So in the large majority of the cases, this v3.11 tag 
will come from one or more remotes and they will refer to the same SHA1, 
so it ought to just work without any special fetch.  Also, if I refer to 
v3.11.1 which is a tag that only exists in one of the remote branches 
and not in Linus' remote then it ought to just work as well.  That is 
more inline with the current _usage_ behavior even if the flat namespace 
is otherwise a nightmare to sort out when managing remotes.

Furthermore, git already has some code to detect refname ambiguities:

$ git init && echo "foo" > foo.txt && git add foo.txt
$ git commit -m "foo" && git tag foo && git branch foo && git log foo
warning: refname 'foo' is ambiguous.

So adding the extra step to lookup all possible tags and make sure they 
resolve to the same SHA1 should be a logical extension to what's already 
there.

Again, in the cases where there is actually a SHA1 conflict between all 
possible tags that match a tag short-end then listing them and asking the 
user to be more explicit is the right thing to do.  But that should be a 
very rare case in practice, and designing for making this case easy is 
the wrong approach.

Instead, the common case of multiple remotes with duplicated tag names 
referring to the same thing _and/or_ multiple remotes with distinct tags 
names is what should be made easy to use with no extra steps.


Nicolas

```

## Marc Branchaud, 2013-09-30 21:14

Subject: Re: Local tag killer
Message-ID: <5249E9C8.1070700@xiplink.com>
URL: https://gitlist.dev/e/5249E9C8.1070700%40xiplink.com
In-Reply-To: <alpine.LFD.2.03.1309301527270.6331@syhkavp.arg>

```
On 13-09-30 04:08 PM, Nicolas Pitre wrote:
> On Mon, 30 Sep 2013, Marc Branchaud wrote:
> 
>> On 13-09-30 11:52 AM, Nicolas Pitre wrote:
>>> Consider that I have in my Linux kernel tree:
>>>
>>> - a remote branch corresponding to Linus' master tree
>>>
>>> - multiple remote branches corresponding to Linux stable branches
>>>
>>> - a remote for linux-next which is a repo constantly being rebased
>>>
>>> Now all those repositories share the mainline tags from Linus' repo and 
>>> they add some more of they own which are not shared.  So if they all 
>>> have a v3.11 tag that resolve to the same SHA1, then there is 
>>> effectively no ambiguity at all and git should not warn at all.
>>
>> Thanks, this example helps very much.
>>
>>> *However* if one of those v3.11 tags does not agree with the others 
>>> _then_ I want to be warned about it.
>>
>> Hmmm.  What behaviour would you like if you also had some non-Linux remote,
>> say for some driver code or something, that also had a v3.11 tag?
> 
> I want git to complain and bail out, maybe suggesting that I should use 
> "driver_something/tag/v3.11" to disambiguate the tag.
> 
>> I presume
>> you want commands like
>> 	git checkout -b my-topic v3.11
>> to do the Right Thing, but what's the right thing for you here?
> 
> git itself can't know it.  So the best git could do is to list 
> conflicting tags with the shortest path that makes them unambiguous and 
> suggest that I try again with one of them.
> 
>>> So having multiple matching tags that do resolve to the same SHA1 across 
>>> different remote repositories _is_ the norm and should work 
>>> transparently.
>>
>> My suggestion for your example is that if some remote's tags are so
>> important/useful then you're better off importing them into your local tag
>> namespace (e.g. "git fetch Linus refs/tags/*:refs/tags/*").  By making the
>> remote's tags local, you're expressly telling git that they should be
>> considered for DWIMery, git-describe, etc.
> 
> Sure, it is probably a good thing semantically to give priority to local 
> tags when they exist. However...
> 
>> I feel this approach lets us avoid having to somehow teach git which remote's
>> "v3.11" tags are important enough to merit an ambiguity warning and which
>> aren't.  Plus you get what I think you want, which is the current behaviour.
> 
> But I disagree here.  Most people simply won't care about local tags 
> since the remote tags are sufficient for what they need.

Good point -- I see where my suggestion was wrong.  I think it's worthwhile
to make sure that bare tag names "just work" after a simple clone.  Git's
DWIM code already does this for branch names, and it makes sense to extend
that to other ref types in remote namespaces.

> And if they 
> have multiple remotes in their repository then it is most likely to be 
> different forks of the same project sharing mostly the same tags, and 
> where those tags diverge then they're most likely to have different tag 
> names as well.

I disagree about the "most likely" part, but it's only a niggle.  I agree
with the overall point that disambiguation through SHA1 comparison makes sense.

> So in the large majority of the cases, this v3.11 tag 
> will come from one or more remotes and they will refer to the same SHA1, 
> so it ought to just work without any special fetch.  Also, if I refer to 
> v3.11.1 which is a tag that only exists in one of the remote branches 
> and not in Linus' remote then it ought to just work as well.  That is 
> more inline with the current _usage_ behavior even if the flat namespace 
> is otherwise a nightmare to sort out when managing remotes.

Agreed.

> Furthermore, git already has some code to detect refname ambiguities:
> 
> $ git init && echo "foo" > foo.txt && git add foo.txt
> $ git commit -m "foo" && git tag foo && git branch foo && git log foo
> warning: refname 'foo' is ambiguous.
> 
> So adding the extra step to lookup all possible tags and make sure they 
> resolve to the same SHA1 should be a logical extension to what's already 
> there.
> 
> Again, in the cases where there is actually a SHA1 conflict between all 
> possible tags that match a tag short-end then listing them and asking the 
> user to be more explicit is the right thing to do.  But that should be a 
> very rare case in practice, and designing for making this case easy is 
> the wrong approach.
> 
> Instead, the common case of multiple remotes with duplicated tag names 
> referring to the same thing _and/or_ multiple remotes with distinct tags 
> names is what should be made easy to use with no extra steps.

Again, I don't think that's the common case.  I think it's just as likely for
there to be multiple remotes with duplicate tag names that refer to different
objects.  However, SHA1-disambiguation covers all these cases.

		M.

```

## Nicolas Pitre, 2013-09-30 22:44

Subject: Re: Local tag killer
Message-ID: <alpine.LFD.2.03.1309301839080.6331@syhkavp.arg>
URL: https://gitlist.dev/e/alpine.LFD.2.03.1309301839080.6331%40syhkavp.arg
In-Reply-To: <5249E9C8.1070700@xiplink.com>

```
On Mon, 30 Sep 2013, Marc Branchaud wrote:

> On 13-09-30 04:08 PM, Nicolas Pitre wrote:
> > Again, in the cases where there is actually a SHA1 conflict between all 
> > possible tags that match a tag short-end then listing them and asking the 
> > user to be more explicit is the right thing to do.  But that should be a 
> > very rare case in practice, and designing for making this case easy is 
> > the wrong approach.
> > 
> > Instead, the common case of multiple remotes with duplicated tag names 
> > referring to the same thing _and/or_ multiple remotes with distinct tags 
> > names is what should be made easy to use with no extra steps.
> 
> Again, I don't think that's the common case.  I think it's just as likely for
> there to be multiple remotes with duplicate tag names that refer to different
> objects.

Why do you say so?  I'm curious to know what kind of work flow would do 
that in practice.

At least for typical Linux kernel workflows what I said above is true.


Nicolas

```

## Jeff King, 2013-09-30 23:18

Subject: Re: Local tag killer
Message-ID: <20130930231803.GA23218@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20130930231803.GA23218%40sigill.intra.peff.net
In-Reply-To: <alpine.LFD.2.03.1309301839080.6331@syhkavp.arg>

```
On Mon, Sep 30, 2013 at 06:44:09PM -0400, Nicolas Pitre wrote:

> > Again, I don't think that's the common case.  I think it's just as likely for
> > there to be multiple remotes with duplicate tag names that refer to different
> > objects.
> 
> Why do you say so?  I'm curious to know what kind of work flow would do 
> that in practice.
> 
> At least for typical Linux kernel workflows what I said above is true.

I could image if you are fetching from a bunch of coworkers that several
people might reuse a common name like "start" or "tmp" for different
purposes.

But I think the behavior you've described handles that quite naturally.
If there is one "start", or if they all match, it is unambiguous. If
there are multiple matches, git says "which one did you mean?" and you
can say "bob/start" or "alice/start" to disambiguate. Anything else
would be a guess.

If _you_ have a refs/tags/start, then I think that should unambiguously
take precedence over that of your coworkers. That way your coworkers
cannot pollute the lookup of items in your own namespace.

-Peff

```

## Marc Branchaud, 2013-10-01 03:04

Subject: Re: Local tag killer
Message-ID: <524A3BB6.9060808@xiplink.com>
URL: https://gitlist.dev/e/524A3BB6.9060808%40xiplink.com
In-Reply-To: <alpine.LFD.2.03.1309301839080.6331@syhkavp.arg>

```
On 13-09-30 06:44 PM, Nicolas Pitre wrote:
> On Mon, 30 Sep 2013, Marc Branchaud wrote:
>
>> On 13-09-30 04:08 PM, Nicolas Pitre wrote:
>>> Again, in the cases where there is actually a SHA1 conflict between all
>>> possible tags that match a tag short-end then listing them and asking the
>>> user to be more explicit is the right thing to do.  But that should be a
>>> very rare case in practice, and designing for making this case easy is
>>> the wrong approach.
>>>
>>> Instead, the common case of multiple remotes with duplicated tag names
>>> referring to the same thing _and/or_ multiple remotes with distinct tags
>>> names is what should be made easy to use with no extra steps.
>>
>> Again, I don't think that's the common case.  I think it's just as likely for
>> there to be multiple remotes with duplicate tag names that refer to different
>> objects.
>
> Why do you say so?  I'm curious to know what kind of work flow would do
> that in practice.

The use case I have in mind is where a project makes use of other 
projects, for example an application that uses some libraries.  The 
application's repository could contain the full histories of the 
libraries, each subtree-merged into a different directory.

So maybe that's not so common these days, but the current flat tag 
namespace makes it pretty much impractical.

		M.

```

## Nicolas Pitre, 2013-10-01 03:28

Subject: Re: Local tag killer
Message-ID: <alpine.LFD.2.03.1309302323190.6331@syhkavp.arg>
URL: https://gitlist.dev/e/alpine.LFD.2.03.1309302323190.6331%40syhkavp.arg
In-Reply-To: <524A3BB6.9060808@xiplink.com>

```
On Mon, 30 Sep 2013, Marc Branchaud wrote:

> On 13-09-30 06:44 PM, Nicolas Pitre wrote:
> > On Mon, 30 Sep 2013, Marc Branchaud wrote:
> > 
> > > On 13-09-30 04:08 PM, Nicolas Pitre wrote:
> > > > Again, in the cases where there is actually a SHA1 conflict between all
> > > > possible tags that match a tag short-end then listing them and asking
> > > > the
> > > > user to be more explicit is the right thing to do.  But that should be a
> > > > very rare case in practice, and designing for making this case easy is
> > > > the wrong approach.
> > > > 
> > > > Instead, the common case of multiple remotes with duplicated tag names
> > > > referring to the same thing _and/or_ multiple remotes with distinct tags
> > > > names is what should be made easy to use with no extra steps.
> > > 
> > > Again, I don't think that's the common case.  I think it's just as likely
> > > for
> > > there to be multiple remotes with duplicate tag names that refer to
> > > different
> > > objects.
> > 
> > Why do you say so?  I'm curious to know what kind of work flow would do
> > that in practice.
> 
> The use case I have in mind is where a project makes use of other projects,
> for example an application that uses some libraries.  The application's
> repository could contain the full histories of the libraries, each
> subtree-merged into a different directory.
> 
> So maybe that's not so common these days, but the current flat tag namespace
> makes it pretty much impractical.

But with my proposal, you'd get a message saying that the tag "baz" is 
ambigous, and that you'd have to use either "libfoo/baz" or 
"libbar/baz".

The current flat namespace makes many things virtually impractical 
indeed, even with the kernel workflow I described.


Nicolas

```

## Marc Branchaud, 2013-10-01 12:45

Subject: Re: Local tag killer
Message-ID: <524AC405.3040209@xiplink.com>
URL: https://gitlist.dev/e/524AC405.3040209%40xiplink.com
In-Reply-To: <alpine.LFD.2.03.1309302323190.6331@syhkavp.arg>

```
On 13-09-30 11:28 PM, Nicolas Pitre wrote:
>
> But with my proposal, you'd get a message saying that the tag "baz" is
> ambigous, and that you'd have to use either "libfoo/baz" or
> "libbar/baz".

Yes, and that's good.  I agree with your proposal.  Sorry if that wasn't 
clear.

		M.

```
