All of lore.kernel.org
 help / color / mirror / Atom feed
* error: src refspec refs/heads/master matches more than one.
@ 2014-02-14 11:31 Josef Wolf
  2014-02-14 12:45 ` Andreas Schwab
  0 siblings, 1 reply; 21+ messages in thread
From: Josef Wolf @ 2014-02-14 11:31 UTC (permalink / raw)
  To: git

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 11:31 error: src refspec refs/heads/master matches more than one Josef Wolf
@ 2014-02-14 12:45 ` Andreas Schwab
  2014-02-14 12:59   ` Duy Nguyen
  0 siblings, 1 reply; 21+ messages in thread
From: Andreas Schwab @ 2014-02-14 12:45 UTC (permalink / raw)
  To: Josef Wolf; +Cc: git

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 12:45 ` Andreas Schwab
@ 2014-02-14 12:59   ` Duy Nguyen
  2014-02-14 15:16     ` Josef Wolf
  2014-02-14 16:32     ` Junio C Hamano
  0 siblings, 2 replies; 21+ messages in thread
From: Duy Nguyen @ 2014-02-14 12:59 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Josef Wolf, Git Mailing List

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 12:59   ` Duy Nguyen
@ 2014-02-14 15:16     ` Josef Wolf
  2014-02-14 15:35       ` David Kastrup
  2014-02-14 16:32     ` Junio C Hamano
  1 sibling, 1 reply; 21+ messages in thread
From: Josef Wolf @ 2014-02-14 15:16 UTC (permalink / raw)
  To: Git Mailing List

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.

-- 
Josef Wolf
jw@raven.inka.de

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 15:16     ` Josef Wolf
@ 2014-02-14 15:35       ` David Kastrup
  2014-02-14 16:52         ` Josef Wolf
  0 siblings, 1 reply; 21+ messages in thread
From: David Kastrup @ 2014-02-14 15:35 UTC (permalink / raw)
  To: Josef Wolf; +Cc: Git Mailing List

Josef Wolf <jw@raven.inka.de> writes:

> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 12:59   ` Duy Nguyen
  2014-02-14 15:16     ` Josef Wolf
@ 2014-02-14 16:32     ` Junio C Hamano
  2014-02-14 16:52       ` David Kastrup
                         ` (2 more replies)
  1 sibling, 3 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-02-14 16:32 UTC (permalink / raw)
  To: Duy Nguyen; +Cc: Andreas Schwab, Josef Wolf, Git Mailing List

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 15:35       ` David Kastrup
@ 2014-02-14 16:52         ` Josef Wolf
  0 siblings, 0 replies; 21+ messages in thread
From: Josef Wolf @ 2014-02-14 16:52 UTC (permalink / raw)
  To: Git Mailing List

On Fri, Feb 14, 2014 at 04:35:14PM +0100, David Kastrup wrote:
> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 16:32     ` Junio C Hamano
@ 2014-02-14 16:52       ` David Kastrup
  2014-02-14 19:10         ` Junio C Hamano
  2014-02-14 22:53       ` Josef Wolf
  2014-02-15  8:53       ` Duy Nguyen
  2 siblings, 1 reply; 21+ messages in thread
From: David Kastrup @ 2014-02-14 16:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

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

> 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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 16:52       ` David Kastrup
@ 2014-02-14 19:10         ` Junio C Hamano
  0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-02-14 19:10 UTC (permalink / raw)
  To: David Kastrup; +Cc: Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

David Kastrup <dak@gnu.org> writes:

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 16:32     ` Junio C Hamano
  2014-02-14 16:52       ` David Kastrup
@ 2014-02-14 22:53       ` Josef Wolf
  2014-02-15  8:53       ` Duy Nguyen
  2 siblings, 0 replies; 21+ messages in thread
From: Josef Wolf @ 2014-02-14 22:53 UTC (permalink / raw)
  To: Git Mailing List

On Fri, Feb 14, 2014 at 08:32:07AM -0800, Junio C Hamano wrote:
>  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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-14 16:32     ` Junio C Hamano
  2014-02-14 16:52       ` David Kastrup
  2014-02-14 22:53       ` Josef Wolf
@ 2014-02-15  8:53       ` Duy Nguyen
  2014-02-17 14:25         ` Ingo Rohloff
  2014-02-18 19:03         ` Junio C Hamano
  2 siblings, 2 replies; 21+ messages in thread
From: Duy Nguyen @ 2014-02-15  8:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Andreas Schwab, Josef Wolf, Git Mailing List

On Fri, Feb 14, 2014 at 08:32:07AM -0800, Junio C Hamano wrote:
> 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< --

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-15  8:53       ` Duy Nguyen
@ 2014-02-17 14:25         ` Ingo Rohloff
  2014-02-18 19:03         ` Junio C Hamano
  1 sibling, 0 replies; 21+ messages in thread
From: Ingo Rohloff @ 2014-02-17 14:25 UTC (permalink / raw)
  To: git

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-15  8:53       ` Duy Nguyen
  2014-02-17 14:25         ` Ingo Rohloff
@ 2014-02-18 19:03         ` Junio C Hamano
  2014-02-18 19:35           ` John Keeping
                             ` (2 more replies)
  1 sibling, 3 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-02-18 19:03 UTC (permalink / raw)
  To: Duy Nguyen; +Cc: Andreas Schwab, Josef Wolf, Git Mailing List

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.

So...

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-18 19:03         ` Junio C Hamano
@ 2014-02-18 19:35           ` John Keeping
  2014-02-18 19:51             ` Junio C Hamano
  2014-02-18 19:37           ` David Kastrup
  2016-03-23 11:17           ` Duy Nguyen
  2 siblings, 1 reply; 21+ messages in thread
From: John Keeping @ 2014-02-18 19:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

On Tue, Feb 18, 2014 at 11:03:10AM -0800, Junio C Hamano wrote:
> 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.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-18 19:03         ` Junio C Hamano
  2014-02-18 19:35           ` John Keeping
@ 2014-02-18 19:37           ` David Kastrup
  2014-02-18 21:47             ` Junio C Hamano
  2016-03-23 11:17           ` Duy Nguyen
  2 siblings, 1 reply; 21+ messages in thread
From: David Kastrup @ 2014-02-18 19:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

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.

-- 
David Kastrup

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-18 19:35           ` John Keeping
@ 2014-02-18 19:51             ` Junio C Hamano
  2014-02-18 20:01               ` John Keeping
  2014-02-20  4:17               ` Michael Haggerty
  0 siblings, 2 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-02-18 19:51 UTC (permalink / raw)
  To: John Keeping; +Cc: Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

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.

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-18 19:51             ` Junio C Hamano
@ 2014-02-18 20:01               ` John Keeping
  2014-02-20  4:17               ` Michael Haggerty
  1 sibling, 0 replies; 21+ messages in thread
From: John Keeping @ 2014-02-18 20:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

On Tue, Feb 18, 2014 at 11:51:05AM -0800, Junio C Hamano wrote:
> 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.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-18 19:37           ` David Kastrup
@ 2014-02-18 21:47             ` Junio C Hamano
  0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-02-18 21:47 UTC (permalink / raw)
  To: David Kastrup; +Cc: Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

David Kastrup <dak@gnu.org> writes:

> 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 ;-)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-18 19:51             ` Junio C Hamano
  2014-02-18 20:01               ` John Keeping
@ 2014-02-20  4:17               ` Michael Haggerty
  2014-02-20 18:22                 ` Junio C Hamano
  1 sibling, 1 reply; 21+ messages in thread
From: Michael Haggerty @ 2014-02-20  4:17 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: John Keeping, Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

On 02/18/2014 08:51 PM, Junio C Hamano wrote:
> 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/

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-20  4:17               ` Michael Haggerty
@ 2014-02-20 18:22                 ` Junio C Hamano
  0 siblings, 0 replies; 21+ messages in thread
From: Junio C Hamano @ 2014-02-20 18:22 UTC (permalink / raw)
  To: Michael Haggerty
  Cc: John Keeping, Duy Nguyen, Andreas Schwab, Josef Wolf, Git Mailing List

Michael Haggerty <mhagger@alum.mit.edu> writes:

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: error: src refspec refs/heads/master matches more than one.
  2014-02-18 19:03         ` Junio C Hamano
  2014-02-18 19:35           ` John Keeping
  2014-02-18 19:37           ` David Kastrup
@ 2016-03-23 11:17           ` Duy Nguyen
  2 siblings, 0 replies; 21+ messages in thread
From: Duy Nguyen @ 2016-03-23 11:17 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Andreas Schwab, Josef Wolf, Git Mailing List, Michael Haggerty,
	John Keeping

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2016-03-23 11:17 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-14 11:31 error: src refspec refs/heads/master matches more than one Josef Wolf
2014-02-14 12:45 ` Andreas Schwab
2014-02-14 12:59   ` Duy Nguyen
2014-02-14 15:16     ` Josef Wolf
2014-02-14 15:35       ` David Kastrup
2014-02-14 16:52         ` Josef Wolf
2014-02-14 16:32     ` Junio C Hamano
2014-02-14 16:52       ` David Kastrup
2014-02-14 19:10         ` Junio C Hamano
2014-02-14 22:53       ` Josef Wolf
2014-02-15  8:53       ` Duy Nguyen
2014-02-17 14:25         ` Ingo Rohloff
2014-02-18 19:03         ` Junio C Hamano
2014-02-18 19:35           ` John Keeping
2014-02-18 19:51             ` Junio C Hamano
2014-02-18 20:01               ` John Keeping
2014-02-20  4:17               ` Michael Haggerty
2014-02-20 18:22                 ` Junio C Hamano
2014-02-18 19:37           ` David Kastrup
2014-02-18 21:47             ` Junio C Hamano
2016-03-23 11:17           ` Duy Nguyen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.