threads / discuss / 35867

error: src refspec refs/heads/master matches more than one.

Subject: error: src refspec refs/heads/master matches more than one.

## tl;dr

21 messages between Feb 14, 2014 and Mar 23, 2016.

replies: 20people: 8as markdown or json

Josef Wolf· Feb 14, 2014, 11:31 UTC · lore
Hello folks,

after some commits to my master branch, I tried to push to the bare upstream repository and got this error message:

  error: src refspec refs/heads/master matches more than one.
A quick check shows that there's indeed something wrong:
  jw@kiste:/git/scan$ git branch -a | grep master
  * master
    refs/heads/master
    remotes/origin/HEAD -> origin/master
    remotes/origin/master
  jw@kiste:/git/scan$ find .git -name master
  .git/refs/heads/master
  .git/logs/refs/remotes/origin/master
  .git/logs/refs/heads/master
  .git/logs/refs/heads/refs/heads/master
  jw@kiste:/git/scan$ find .git -name master
  .git/refs/heads
  .git/refs/heads/refs/heads
  .git/logs/refs/heads
  .git/logs/refs/heads/refs/heads
  jw@kiste:/git/scan$ find .git -name master
Notice the refs/heads _within_ refs/heads!

Now I wonder how I managed to get into this situation and what's the best way to recover?

Any ideas?
PS: this is git-1.8.1.4.
-- 
Josef Wolf
jw@raven.inka.de
Andreas Schwab· Feb 14, 2014, 12:45 UTC · re: Josef Wolf · lore

Re: error: src refspec refs/heads/master matches more than one.

Josef Wolf <jw@raven.inka.de> writes:
> Notice the refs/heads _within_ refs/heads!
>
> Now I wonder how I managed to get into this situation and what's the best way
> to recover?

Probably you did something like "git branch refs/heads/master". You can remove it again with "git branch -d refs/heads/master".

Andreas.
-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Duy Nguyen· Feb 14, 2014, 12:59 UTC · re: Andreas Schwab · lore

Re: error: src refspec refs/heads/master matches more than one.

On Fri, Feb 14, 2014 at 7:45 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
Show 9 quoted lines
> Josef Wolf <jw@raven.inka.de> writes:
>
>> Notice the refs/heads _within_ refs/heads!
>>
>> Now I wonder how I managed to get into this situation and what's the best way
>> to recover?
>
> Probably you did something like "git branch refs/heads/master".  You can
> remove it again with "git branch -d refs/heads/master".

As a porcelain, "git branch" should prevent (or at least warn) users from creating such refs, I think.

-- 
Duy
Josef Wolf· Feb 14, 2014, 15:16 UTC · re: Duy Nguyen · lore

Re: error: src refspec refs/heads/master matches more than one.

On Fri, Feb 14, 2014 at 07:59:18PM +0700, Duy Nguyen wrote:
Show 8 quoted lines
> On Fri, Feb 14, 2014 at 7:45 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> > Josef Wolf <jw@raven.inka.de> writes:
> >
> >> Notice the refs/heads _within_ refs/heads!
> > Probably you did something like "git branch refs/heads/master".  You can
> > remove it again with "git branch -d refs/heads/master".
> As a porcelain, "git branch" should prevent (or at least warn) users
> from creating such refs, I think.

I don't think I did it the way Andreas thinks. This repository is maintained by a script, I don't create branches manually. The only command in this script that uses "heads" is

  git symbolic-ref HEAD "refs/heads/$new_branch"

to create new branches without any ancestry. And I double-checked that this command is _not_ resposible for those ghost branches.

BTW: I see such ghost branches reappearing again and again, so it must be
     something systematic.
-- 
Josef Wolf
jw@raven.inka.de
David Kastrup· Feb 14, 2014, 15:35 UTC · re: Josef Wolf · lore

Re: error: src refspec refs/heads/master matches more than one.

Josef Wolf <jw@raven.inka.de> writes:
Show 21 quoted lines
> On Fri, Feb 14, 2014 at 07:59:18PM +0700, Duy Nguyen wrote:
>> On Fri, Feb 14, 2014 at 7:45 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>> > Josef Wolf <jw@raven.inka.de> writes:
>> >
>> >> Notice the refs/heads _within_ refs/heads!
>> > Probably you did something like "git branch refs/heads/master".  You can
>> > remove it again with "git branch -d refs/heads/master".
>> As a porcelain, "git branch" should prevent (or at least warn) users
>> from creating such refs, I think.
>
> I don't think I did it the way Andreas thinks. This repository is maintained
> by a script, I don't create branches manually. The only command in this script
> that uses "heads" is
>
>   git symbolic-ref HEAD "refs/heads/$new_branch"
>
> to create new branches without any ancestry. And I double-checked that this
> command is _not_ resposible for those ghost branches.
>
> BTW: I see such ghost branches reappearing again and again, so it must be
>      something systematic.

You probably should check how $new_branch comes about. Also, once a directory refs/heads/refs/heads exists, "refs/heads/$new_branch" may possibly be resolved as a branch with the name refs/heads/$new_branch.

-- 
David Kastrup
Josef Wolf· Feb 14, 2014, 16:52 UTC · re: David Kastrup · lore

Re: error: src refspec refs/heads/master matches more than one.

On Fri, Feb 14, 2014 at 04:35:14PM +0100, David Kastrup wrote:
Show 6 quoted lines
> Josef Wolf <jw@raven.inka.de> writes:
> > The only command in this script that uses "heads" is
> >
> >   git symbolic-ref HEAD "refs/heads/$new_branch"
> >
> You probably should check how $new_branch comes about.
This is the line of code where $new_branch is comes to live:
    my (undef, $new_branch, @new_path) = split ("/", $new_item);
So it is impossible that it might contain any slashes.

In any other situation, this script cares only about branches which start with the string "scan-file-XXXX":

    sub local_branches  { grep {m+^scan-file-+} &all_branches; }
    sub remote_branches { grep {m+^remotes/origin/scan-file-+} &all_branches; }
This is hard-coded, so I can't see any way for the user to inject "refs/heads"
> Also, once a
> directory refs/heads/refs/heads exists, "refs/heads/$new_branch" may
> possibly be resolved as a branch with the name refs/heads/$new_branch.
Can you elobarte on this? I don't get what you are trying to say.

As I already said, this happens on opensuse with git-1.8.1.4. I have not yet seen this problem on ubuntu with git-1.7.9.5.

-- 
Josef Wolf
jw@raven.inka.de
Junio C Hamano· Feb 14, 2014, 16:32 UTC · re: Duy Nguyen · lore

Re: error: src refspec refs/heads/master matches more than one.

Duy Nguyen <pclouds@gmail.com> writes:
Show 13 quoted lines
> On Fri, Feb 14, 2014 at 7:45 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>> Josef Wolf <jw@raven.inka.de> writes:
>>
>>> Notice the refs/heads _within_ refs/heads!
>>>
>>> Now I wonder how I managed to get into this situation and what's the best way
>>> to recover?
>>
>> Probably you did something like "git branch refs/heads/master".  You can
>> remove it again with "git branch -d refs/heads/master".
>
> As a porcelain, "git branch" should prevent (or at least warn) users
> from creating such refs, I think.
"warn", possibly, but I do not see a reason to *prevent*.
 A. You are not allowed to call your branch with a string that begins with
    'refs/heads/'.
 B. Why?
 A. Because it will confuse you.
 B. I know what I am doing.
 A. ???
David Kastrup· Feb 14, 2014, 16:52 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

Junio C Hamano <gitster@pobox.com> writes:
Show 24 quoted lines
> Duy Nguyen <pclouds@gmail.com> writes:
>
>> On Fri, Feb 14, 2014 at 7:45 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
>>> Josef Wolf <jw@raven.inka.de> writes:
>>>
>>>> Notice the refs/heads _within_ refs/heads!
>>>>
>>>> Now I wonder how I managed to get into this situation and what's the best way
>>>> to recover?
>>>
>>> Probably you did something like "git branch refs/heads/master".  You can
>>> remove it again with "git branch -d refs/heads/master".
>>
>> As a porcelain, "git branch" should prevent (or at least warn) users
>> from creating such refs, I think.
>
> "warn", possibly, but I do not see a reason to *prevent*.
>
>  A. You are not allowed to call your branch with a string that begins with
>     'refs/heads/'.
>  B. Why?
>  A. Because it will confuse you.
>  B. I know what I am doing.
>  A. ???

A. But maybe Git will no longer know what you are doing. Its standard way of resolving references will mean that once a branch refs/heads/wibble exists, referring to a branch wibble will become extra hard. For example, stuff like

push origin HEAD:refs/heads/wibble

will maybe create or update a new branch wibble, or maybe it will just push to the existing branch refs/heads/wibble.

-- 
David Kastrup
Junio C Hamano· Feb 14, 2014, 19:10 UTC · re: David Kastrup · lore

Re: error: src refspec refs/heads/master matches more than one.

David Kastrup <dak@gnu.org> writes:
Show 15 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
> ...
>>  A. Because it will confuse you.
>>  B. I know what I am doing.
>>  A. ???
>
> A. But maybe Git will no longer know what you are doing.  Its standard
> way of resolving references will mean that once a branch
> refs/heads/wibble exists, referring to a branch wibble will become extra
> hard.  For example, stuff like
>
> push origin HEAD:refs/heads/wibble
>
> will maybe create or update a new branch wibble, or maybe it will just
> push to the existing branch refs/heads/wibble.

I suspect that is a bad example (do refs on _our_ side influence how RHS of the colon that names refs on the other side is interpreted), but I think I know what you are trying to say. But Git never knows what you are doing---it just does what you tell it to, so it comes back to "It will confuse you to the point that you would not be able to guess what Git will do matches your expectation". Whenever I tell them that, a counterpoint B. makes is still "I know what I am doing.", which is stubborn, rather obvious, and unfortunate.

How much of the namespace are we willing to carve out if we were to go this route anyway? Things we use, i.e. refs/heads and refs/tags, would be no-brainers, but do we also forbid refs/review, which we ourselves do not use but some people may have in their repositories? Anything that begins with refs/? Anything that begins with refs/ and has more than two slashes in it?

Josef Wolf· Feb 14, 2014, 22:53 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

On Fri, Feb 14, 2014 at 08:32:07AM -0800, Junio C Hamano wrote:
Show 6 quoted lines
>  A. You are not allowed to call your branch with a string that begins with
>     'refs/heads/'.
>  B. Why?
>  A. Because it will confuse you.
>  B. I know what I am doing.
>  A. ???

Your reply in http://git.661346.n2.nabble.com/1-8-0-git-checkout-refs-heads-foo-checks-out-branch-foo-td5999936.html suggests that one should explicitly use the refs/heads prefix to to work around ambiguities in some situations.

Are there any best-practices sugestions out there about when to use the refs/heads prefix and when not? It looks like git delibaretly cuts off this prefix in some situations.

I don't think my problem stems from something like "git branch refs/heads/master" Anyway, some clarifications about the usage of this prefix would be great!

-- 
Josef Wolf
jw@raven.inka.de
Duy Nguyen· Feb 15, 2014, 08:53 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

On Fri, Feb 14, 2014 at 08:32:07AM -0800, Junio C Hamano wrote:
Show 24 quoted lines
> Duy Nguyen <pclouds@gmail.com> writes:
> 
> > On Fri, Feb 14, 2014 at 7:45 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> >> Josef Wolf <jw@raven.inka.de> writes:
> >>
> >>> Notice the refs/heads _within_ refs/heads!
> >>>
> >>> Now I wonder how I managed to get into this situation and what's the best way
> >>> to recover?
> >>
> >> Probably you did something like "git branch refs/heads/master".  You can
> >> remove it again with "git branch -d refs/heads/master".
> >
> > As a porcelain, "git branch" should prevent (or at least warn) users
> > from creating such refs, I think.
> 
> "warn", possibly, but I do not see a reason to *prevent*.
> 
>  A. You are not allowed to call your branch with a string that begins with
>     'refs/heads/'.
>  B. Why?
>  A. Because it will confuse you.
>  B. I know what I am doing.
>  A. ???

Prevent is a strong word. I meant we only do it if they force it. Something like this..

-- 8< --
diff --git a/branch.c b/branch.c
index 723a36b..3f0540f 100644
--- a/branch.c
+++ b/branch.c
@@ -251,6 +251,11 @@ void create_branch(const char *head,
 			forcing = 1;
 	}
 
+	if (!force && dwim_ref(name, strlen(name), sha1, &real_ref))
+		die(_("creating ref refs/heads/%s makes %s ambiguous.\n"
+		      "Use -f to create it anyway."),
+		    name, name);
+
 	real_ref = NULL;
 	if (get_sha1(start_name, sha1)) {
 		if (explicit_tracking) {
-- 8< --
Ingo Rohloff· Feb 17, 2014, 14:25 UTC · re: Duy Nguyen · lore

Re: error: src refspec refs/heads/master matches more than one.

Duy Nguyen <pclouds <at> gmail.com> writes:
> Prevent is a strong word. I meant we only do it if they force
> it. Something like this..
> 
I would propose to make this even stronger:
Forbid to create any branches which start with any of:
- "refs/"
- "heads/"
- "remotes/"
- "tags/"
as long as you do not use the "force" option.

The idea here is that you also will not get ambiguities later when you pull new branches into your repository.

so long
  Ingo
Junio C Hamano· Feb 18, 2014, 19:03 UTC · re: Duy Nguyen · lore

Re: error: src refspec refs/heads/master matches more than one.

Duy Nguyen <pclouds@gmail.com> writes:
Show 16 quoted lines
> Prevent is a strong word. I meant we only do it if they force
> it. Something like this..
>
> -- 8< --
> diff --git a/branch.c b/branch.c
> index 723a36b..3f0540f 100644
> --- a/branch.c
> +++ b/branch.c
> @@ -251,6 +251,11 @@ void create_branch(const char *head,
>  			forcing = 1;
>  	}
>  
> +	if (!force && dwim_ref(name, strlen(name), sha1, &real_ref))
> +		die(_("creating ref refs/heads/%s makes %s ambiguous.\n"
> +		      "Use -f to create it anyway."),
> +		    name, name);

Does this check still allow you to create a branch "refs/heads/next" and then later create a branch "next"? The latter will introduce an ambiguity without any prevention, even though the prevention would trigger if the order in which these two branches are created is swapped--- the end result has ambiguity but the safety covers only one avenue to the confusing situation.

And the only way I can think of to avoid that kind of confusion is to forbid creation of a subset of possible names by reserving a set of known (but arbitrary) prefixes---which I am not sure is a good way to go. At least not yet.

So...
John Keeping· Feb 18, 2014, 19:35 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

On Tue, Feb 18, 2014 at 11:03:10AM -0800, Junio C Hamano wrote:
Show 30 quoted lines
> Duy Nguyen <pclouds@gmail.com> writes:
> 
> > Prevent is a strong word. I meant we only do it if they force
> > it. Something like this..
> >
> > -- 8< --
> > diff --git a/branch.c b/branch.c
> > index 723a36b..3f0540f 100644
> > --- a/branch.c
> > +++ b/branch.c
> > @@ -251,6 +251,11 @@ void create_branch(const char *head,
> >  			forcing = 1;
> >  	}
> >  
> > +	if (!force && dwim_ref(name, strlen(name), sha1, &real_ref))
> > +		die(_("creating ref refs/heads/%s makes %s ambiguous.\n"
> > +		      "Use -f to create it anyway."),
> > +		    name, name);
> 
> Does this check still allow you to create a branch "refs/heads/next"
> and then later create a branch "next"?  The latter will introduce an
> ambiguity without any prevention, even though the prevention would
> trigger if the order in which these two branches are created is
> swapped--- the end result has ambiguity but the safety covers only
> one avenue to the confusing situation.
> 
> And the only way I can think of to avoid that kind of confusion is
> to forbid creation of a subset of possible names by reserving a set
> of known (but arbitrary) prefixes---which I am not sure is a good
> way to go.  At least not yet.

There's already the arbitrary set of prefixes in refs.c::prettify_refname() and refs.c::ref_rev_parse_rules(). I can see how a user might think that since "git log refs/heads/name" is equivalent to "git log master" then "git branch refs/heads/name" should be equivalent to "git branch name".

I don't think requiring "--force" for these branch names that overlap with these special namespaces is a big leap from supporting them for inspection commands. Although I'm not sure how sensible it is to examine every remote name to catch something like "git branch origin/master". Perhaps Duy's ambiguity check is the best thing for that case.

Junio C Hamano· Feb 18, 2014, 19:51 UTC · re: John Keeping · lore

Re: error: src refspec refs/heads/master matches more than one.

John Keeping <john@keeping.me.uk> writes:
Show 5 quoted lines
> There's already the arbitrary set of prefixes in
> refs.c::prettify_refname() and refs.c::ref_rev_parse_rules().  I can see
> how a user might think that since "git log refs/heads/name" is
> equivalent to "git log master" then "git branch refs/heads/name" should
> be equivalent to "git branch name".

Not quite, I am afraid. Branch names used for "git branch <name>" and "git checkout <name>" are like the Lvalue of an assignment, as opposed to extended SHA-1 expressions to express any commit (e.g. 'master^0', 'refs/heads/master', or 'master') that correspond to the Rvalues used in an expression. Because "git checkout" can take a branch name or an arbitrary commit object name, there needs a way for the users to disambiguate.

Saying that "git checkout refs/heads/name" must be equivalent to "git checkout name" is like arguing that assignment "value+0 = x" should be valid because "value+0" is a valid value.

For the first parameter to "git branch", there is no ambiguity---it must be the name of a branch and cannot be an arbitrary commit object name, so special casing "git branch refs/heads/master" to mean "git branch master" may not be too bad. But then we need to either start rejecting "git branch refs/tags/v1.0" or keep allowing it to create a ref refs/heads/refs/tags/v1.0 to denote the branch of that exact name given---neither of which is more consistent, so...

John Keeping· Feb 18, 2014, 20:01 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

On Tue, Feb 18, 2014 at 11:51:05AM -0800, Junio C Hamano wrote:
Show 19 quoted lines
> John Keeping <john@keeping.me.uk> writes:
> 
> > There's already the arbitrary set of prefixes in
> > refs.c::prettify_refname() and refs.c::ref_rev_parse_rules().  I can see
> > how a user might think that since "git log refs/heads/name" is
> > equivalent to "git log master" then "git branch refs/heads/name" should
> > be equivalent to "git branch name".
> 
> Not quite, I am afraid.  Branch names used for "git branch <name>"
> and "git checkout <name>" are like the Lvalue of an assignment, as
> opposed to extended SHA-1 expressions to express any commit
> (e.g. 'master^0', 'refs/heads/master', or 'master') that correspond
> to the Rvalues used in an expression.  Because "git checkout" can
> take a branch name or an arbitrary commit object name, there needs a
> way for the users to disambiguate.
> 
> Saying that "git checkout refs/heads/name" must be equivalent to
> "git checkout name" is like arguing that assignment "value+0 = x"
> should be valid because "value+0" is a valid value.

That isn't my argument. I agree that the "create" and "view" operations are distinct. The problem appears to be that not all users expect this and it caused them confusion because they are able to create refs like refs/heads/refs/heads/master.

I don't think we should apply the mapping, but I also do not think that using a set of known (but arbitrary) constraints to prevent the creation of potentially confusing branch names is a particularly big leap from applying a similar set of rules in prettify_ref() and dwim_ref(). Especially if there's an escape hatch via '--force' or 'git update-ref' for those who know what they're doing.

Michael Haggerty· Feb 20, 2014, 04:17 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

On 02/18/2014 08:51 PM, Junio C Hamano wrote:
Show 19 quoted lines
> John Keeping <john@keeping.me.uk> writes:
> 
>> There's already the arbitrary set of prefixes in
>> refs.c::prettify_refname() and refs.c::ref_rev_parse_rules().  I can see
>> how a user might think that since "git log refs/heads/name" is
>> equivalent to "git log master" then "git branch refs/heads/name" should
>> be equivalent to "git branch name".
> 
> Not quite, I am afraid.  Branch names used for "git branch <name>"
> and "git checkout <name>" are like the Lvalue of an assignment, as
> opposed to extended SHA-1 expressions to express any commit
> (e.g. 'master^0', 'refs/heads/master', or 'master') that correspond
> to the Rvalues used in an expression.  Because "git checkout" can
> take a branch name or an arbitrary commit object name, there needs a
> way for the users to disambiguate.
> 
> Saying that "git checkout refs/heads/name" must be equivalent to
> "git checkout name" is like arguing that assignment "value+0 = x"
> should be valid because "value+0" is a valid value.

Your logic is impeccable...and yet the user's logic is also quite reasonable. I fell into this trap when I started using Git, and so did most (all?) of my colleagues.

I think the problem is partly caused by the visual and semantic
similarity between references and Unix pathnames.  For pathnames, the
file that is called "filename.txt" in my current context has an
unambiguous, canonical name that might be "/home/mhagger/filename.txt".
 My first mental model of Git references was that "branch" and
"refs/heads/branch" are synonyms, and that the latter is somehow the
"unambiguous" and "canonical" way to write it.  I think this mental
model is what led me to make the universal beginner's mistake
    git branch refs/heads/mybranch

It took me a while to figure out how to fix the situation, and the whole experience was very frustrating.

I wonder whether we could give a way to specify a reference in an unambiguous, canonical fashion like I expected, for example by using a leading slash: "/refs/heads/mybranch". This could be a way for the user to ask for DWIMming to be turned off without having to resort to plumbing commands like update-ref. This wouldn't necessarily solve the problem, but it would at least lead the new user to type

    git branch /refs/heads/mybranch

instead of the ambiguous command above, which Git could either accept or reject in good conscience rather than having to speculate about what the user *really* meant. I think that supporting absolute reference names like this would also be useful for scripts, which otherwise probably often have subtle failure modes if the user has defined reference names that are ambiguous, modulo DWIM, with the reference that the script intended.

Michael
-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
Junio C Hamano· Feb 20, 2014, 18:22 UTC · re: Michael Haggerty · lore

Re: error: src refspec refs/heads/master matches more than one.

Michael Haggerty <mhagger@alum.mit.edu> writes:
Show 16 quoted lines
> I wonder whether we could give a way to specify a reference in an
> unambiguous, canonical fashion like I expected, for example by using a
> leading slash: "/refs/heads/mybranch".  This could be a way for the user
> to ask for DWIMming to be turned off without having to resort to
> plumbing commands like update-ref.  This wouldn't necessarily solve the
> problem, but it would at least lead the new user to type
>
>     git branch /refs/heads/mybranch
>
> instead of the ambiguous command above, which Git could either accept or
> reject in good conscience rather than having to speculate about what the
> user *really* meant.  I think that supporting absolute reference names
> like this would also be useful for scripts, which otherwise probably
> often have subtle failure modes if the user has defined reference names
> that are ambiguous, modulo DWIM, with the reference that the script
> intended.

I do agree that things start to become confusing to the end users when we tell refnames and object names apart and behave differently, e.g. "git checkout master" vs "git checkout master^0" (this example uses a disambiguation syntax that is related to but different from what you brought up).

For the <name> in "git branch <name> [<commit>]" (but not <commit>), I do not see much value in allowing the users to say "refs/heads/" in the first place---all the local branch refs are to be created in refs/heads/ anyway and "git branch /refs/tags/bar" (if we were to allow your notation to name an absolute ref) will have to be checked and signaled as an error.

Even though there is no reason to forbid a ref to be named in such a way at the lowest machinery level (read: at the sha1_name.c layer) [*1*], I would say it would be better to at least warn users when they create such a ref with Porcelain commands like "branch", "checkout -b", etc., or even outright forbid.

In other contexts, however, it _might_ make sense, but I am somewhat skeptical. For example, if you have a branch 'foo' (whose ref being refs/heads/foo) and a branch 'refs/heads/foo' (whose ref being refs/heads/refs/heads/foo) at the same time, you need some way to clarify that you mean the former, and one way to do so may be

	git branch newfoo /refs/heads/foo
and removing the latter would be
	git branch -D /refs/heads/refs/heads/foo

perhaps. But this starts to sound like a workaround to a problem that the user ended up having such a strangely named branch in the first place, not a useful feature.

[Footnote]
*1* The way refs are used and the specific meanings given to some of
    the hierarchies under refs/ by the core-git Porcelain is not
    fundamental to the data model of Git.  Git the SCM by convention
    uses refs/heads/ for branches, and it is perfectly fine for Git
    the SCM to enforce its own policy like that to its end users and
    forbid creating and using any ref outside that hierarchy as a
    local branch (e.g. checking it out), but I'd prefer it if we can
    keep the lower level "a general filesystem to build SCM on top"
    layer as separate from such policy decision as possible.
David Kastrup· Feb 18, 2014, 19:37 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

Junio C Hamano <gitster@pobox.com> writes:
Show 18 quoted lines
> Duy Nguyen <pclouds@gmail.com> writes:
>
>> +	if (!force && dwim_ref(name, strlen(name), sha1, &real_ref))
>> +		die(_("creating ref refs/heads/%s makes %s ambiguous.\n"
>> +		      "Use -f to create it anyway."),
>> +		    name, name);
>
> Does this check still allow you to create a branch "refs/heads/next"
> and then later create a branch "next"?  The latter will introduce an
> ambiguity without any prevention, even though the prevention would
> trigger if the order in which these two branches are created is
> swapped--- the end result has ambiguity but the safety covers only one
> avenue to the confusing situation.
>
> And the only way I can think of to avoid that kind of confusion is
> to forbid creation of a subset of possible names by reserving a set
> of known (but arbitrary) prefixes---which I am not sure is a good
> way to go.  At least not yet.

Just for the record: after seeing the respective arguments, I consider it the sanest way.

It's conceivable to give a configuration option for augmenting the set of reserved prefixes. That would allow to adapt the arbitrariness to match the policies or ref name choices of a particular project while keeping the set of references addressed by the standard git commands in check automagically.

-- 
David Kastrup
Junio C Hamano· Feb 18, 2014, 21:47 UTC · re: David Kastrup · lore

Re: error: src refspec refs/heads/master matches more than one.

David Kastrup <dak@gnu.org> writes:
Show 29 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
>
>> Duy Nguyen <pclouds@gmail.com> writes:
>>
>>> +	if (!force && dwim_ref(name, strlen(name), sha1, &real_ref))
>>> +		die(_("creating ref refs/heads/%s makes %s ambiguous.\n"
>>> +		      "Use -f to create it anyway."),
>>> +		    name, name);
>>
>> Does this check still allow you to create a branch "refs/heads/next"
>> and then later create a branch "next"?  The latter will introduce an
>> ambiguity without any prevention, even though the prevention would
>> trigger if the order in which these two branches are created is
>> swapped--- the end result has ambiguity but the safety covers only one
>> avenue to the confusing situation.
>>
>> And the only way I can think of to avoid that kind of confusion is
>> to forbid creation of a subset of possible names by reserving a set
>> of known (but arbitrary) prefixes---which I am not sure is a good
>> way to go.  At least not yet.
>
> Just for the record: after seeing the respective arguments, I consider
> it the sanest way.
>
> It's conceivable to give a configuration option for augmenting the set
> of reserved prefixes.  That would allow to adapt the arbitrariness to
> match the policies or ref name choices of a particular project while
> keeping the set of references addressed by the standard git commands in
> check automagically.

I am inclined to say that we should start by just giving a warning whenever "git branch", "git checkout -b", etc. tries to create a branch whose name begins with "refs/" and other potentially ambiguous ones that match ref_rev_parse_rules[]. I personally do not think people name their branch with a name that begins with "refs/" on purpose; I am not sure about other ones, like "heads" or "tags". Personally I think it also is unlikely to want to have these words immediately followed by a slash in the branch name, so it may not even be necessary to give them any way to turn off the warning, which in turn would mean we can promote that warning to an die() that can be overridable with "--force", but by going that "first warn and see if people are annoyed" route, we would hopefully find out soon enough that there may be some people who do want to name their branches in a funny way ;-)

Duy Nguyen· Mar 23, 2016, 11:17 UTC · re: Junio C Hamano · lore

Re: error: src refspec refs/heads/master matches more than one.

I'm digging this topic up from the ground because if it was fixed, I would not have spent many confusing (and a little bit panicking) minutes wondering how the hell I managed to push to "origin/master" which I did not have push access to begin with, which turned out to be the local branch, refs/heads/origin/master, not the remote branch refs/remotes/origin/master.

Summary until this point in the old thread, you can accidentally do "git branch refs/heads/next", which happily creates refs/heads/refs/heads/next. If you also have refs/heads/next, things can get confusing for commands that accepts both branch and non-branch refs. There were some more discussion about unambiguously specifying full ref in git-branch but it was getting nowhere.

On Wed, Feb 19, 2014 at 2:03 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 25 quoted lines
> Duy Nguyen <pclouds@gmail.com> writes:
>
>> Prevent is a strong word. I meant we only do it if they force
>> it. Something like this..
>>
>> -- 8< --
>> diff --git a/branch.c b/branch.c
>> index 723a36b..3f0540f 100644
>> --- a/branch.c
>> +++ b/branch.c
>> @@ -251,6 +251,11 @@ void create_branch(const char *head,
>>                       forcing = 1;
>>       }
>>
>> +     if (!force && dwim_ref(name, strlen(name), sha1, &real_ref))
>> +             die(_("creating ref refs/heads/%s makes %s ambiguous.\n"
>> +                   "Use -f to create it anyway."),
>> +                 name, name);
>
> Does this check still allow you to create a branch "refs/heads/next"
> and then later create a branch "next"?  The latter will introduce an
> ambiguity without any prevention, even though the prevention would
> trigger if the order in which these two branches are created is
> swapped--- the end result has ambiguity but the safety covers only
> one avenue to the confusing situation.

It could be fixed by checking all existing refs if any of them becomes ambiguous after refs/heads/next comes to life. We can filter and check only branch that shares the same base name (or starts with "refs/", "heads/", "tags/" or "remotes/"), so it's still expensive but not as much as checking all refs.

Even with covering only one avenue, it would definitely help my case (refs/remotes/origin/master exists and refs/heads/origin/master asked to be created).

Also in my case, if refs/heads/origin/master already exists then I think I should reject creating refs/remotes/origin/master, or warn loudly.

Sounds promising enough to start making patches?
> And the only way I can think of to avoid that kind of confusion is
> to forbid creation of a subset of possible names by reserving a set
> of known (but arbitrary) prefixes---which I am not sure is a good
> way to go.  At least not yet.
-- 
Duy

← back to recent threads