git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] push: support remote branches in guess_ref DWIM
@ 2009-10-26 21:33 Jeff King
  2009-10-26 23:31 ` Junio C Hamano
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff King @ 2009-10-26 21:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

When we get an unqualified dest refspec like "foo", we try
to guess its full ref path (like "refs/heads/foo") based on
the source ref. Commit f8aae12 mapped local heads to remote
heads, and local tags to remote tags.

This commit maps local tracking branches under
"refs/remotes" to remote branch heads, so

  git push origin origin/branch:renamed-branch

pushes to refs/heads/renamed-branch.

Signed-off-by: Jeff King <peff@peff.net>
---
This came from a discussion on IRC. I don't see any reason not to do
this; would people really expect it to push into refs/remotes/ on the
other side (right now, it complains and dies)?

A related issue (which exists even without this patch) is that doing
this:

  master:remotes/incoming/master

will create "refs/heads/remotes/incoming/master". Perhaps we should DWYM
a little more and recognize "heads", "remotes", and "tags" as special.

 remote.c              |    2 +-
 t/t5516-fetch-push.sh |    9 +++++++++
 2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/remote.c b/remote.c
index 73d33f2..1a7c81e 100644
--- a/remote.c
+++ b/remote.c
@@ -998,7 +998,7 @@ static char *guess_ref(const char *name, struct ref *peer)
 	if (!r)
 		return NULL;
 
-	if (!prefixcmp(r, "refs/heads/"))
+	if (!prefixcmp(r, "refs/heads/") || !prefixcmp(r, "refs/remotes/"))
 		strbuf_addstr(&buf, "refs/heads/");
 	else if (!prefixcmp(r, "refs/tags/"))
 		strbuf_addstr(&buf, "refs/tags/");
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 6889a53..692c773 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -383,6 +383,15 @@ test_expect_success 'push tag with non-existant, incomplete dest' '
 
 '
 
+test_expect_success 'push remote branch with non-existant, incomplete dest' '
+
+	mk_test &&
+	git update-ref refs/remotes/foo/bar master &&
+	git push testrepo foo/bar:branch &&
+	check_push_result $the_commit heads/branch
+
+'
+
 test_expect_success 'push sha1 with non-existant, incomplete dest' '
 
 	mk_test &&
-- 
1.6.5.1.201.g7feba

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

* Re: [PATCH] push: support remote branches in guess_ref DWIM
  2009-10-26 21:33 [PATCH] push: support remote branches in guess_ref DWIM Jeff King
@ 2009-10-26 23:31 ` Junio C Hamano
  2009-10-27  1:45   ` Jeff King
  0 siblings, 1 reply; 5+ messages in thread
From: Junio C Hamano @ 2009-10-26 23:31 UTC (permalink / raw)
  To: Jeff King; +Cc: git

Jeff King <peff@peff.net> writes:

> When we get an unqualified dest refspec like "foo", we try
> to guess its full ref path (like "refs/heads/foo") based on
> the source ref. Commit f8aae12 mapped local heads to remote
> heads, and local tags to remote tags.
>
> This commit maps local tracking branches under
> "refs/remotes" to remote branch heads, so
>
>   git push origin origin/branch:renamed-branch
>
> pushes to refs/heads/renamed-branch.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> This came from a discussion on IRC. I don't see any reason not to do
> this; would people really expect it to push into refs/remotes/ on the
> other side (right now, it complains and dies)?

As _our_ origin can never be _their_ origin if we are clone of them, I do
not think anybody sane would expect it to push into refs/remotes/origin/
to begin with.

But "not in refs/remotes/" does not automatically mean "the only sensible
place is refs/heads", does it?  "We do not know what kind of mistake the
user is trying to make" could be more plausible answer, and in that case,
"complain and die" may be a more valid course of action.

For example,

    git push origin origin/master:refs/heads/master

is most likely to be a mistake.  The only situation something similar to
this makes sense is where you pushed out a bogus commit earlier and are
trying to correct it perhaps with

	git push origin +origin/master@{1}:refs/heads/master

but you need to force it and go back in the reflog.

I know you are doing this DWIM only when $dst does not exist over there,
and the "pushing old master back to master" above is a different scenario,
but if "git push origin origin/master:master" shouldn't update their local
master, "git push origin origin/master:naster" shouldn't update their
local naster, in order to avoid confusion arising from inconsistency, no?

Another possibility is to see the type (not refname) of $src and push all
commits to refs/heads/$dst and everything else (most likely tags) to
refs/tags/$dst, to simplify the rule to make it easier to explain and
remember, but there are lightweight tags that make this idea unworkable.

> A related issue (which exists even without this patch) is that doing
> this:
>
>   master:remotes/incoming/master
>
> will create "refs/heads/remotes/incoming/master". Perhaps we should DWYM
> a little more and recognize "heads", "remotes", and "tags" as special.

Yes, it is an independent issue; I think correcting this DWIM (or at least
"warning" if not refusing to create remotes/ under refs/heads/) might be a
good idea.

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

* Re: [PATCH] push: support remote branches in guess_ref DWIM
  2009-10-26 23:31 ` Junio C Hamano
@ 2009-10-27  1:45   ` Jeff King
  2009-10-27 22:33     ` Junio C Hamano
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff King @ 2009-10-27  1:45 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Mon, Oct 26, 2009 at 04:31:57PM -0700, Junio C Hamano wrote:

> As _our_ origin can never be _their_ origin if we are clone of them, I do
> not think anybody sane would expect it to push into refs/remotes/origin/
> to begin with.

OK, I agree.

> But "not in refs/remotes/" does not automatically mean "the only sensible
> place is refs/heads", does it?  "We do not know what kind of mistake the
> user is trying to make" could be more plausible answer, and in that case,
> "complain and die" may be a more valid course of action.

The thing is that I can't think of another sensible place. And this
sensible place is useful for one particular action: renaming a remote
branch, like this:

  $ git fetch ;# presumably gets origin/branch
  $ git push origin/branch:renamed-branch

which is much nicer than exposing clueless users to
":refs/heads/renamed-branch".

> For example,
> 
>     git push origin origin/master:refs/heads/master
> 
> is most likely to be a mistake.  The only situation something similar to
> this makes sense is where you pushed out a bogus commit earlier and are
> trying to correct it perhaps with

I'm not sure why it's likely to be a mistake. I've given the one use
case I can think of where you _do_ want to do it. But I'm not sure why
you would accidentally provide something in refs/remotes, or not want to
be pushing to refs/heads. Where _else_ do you push, except for tags?

Am I missing some part of your argument?

> > A related issue (which exists even without this patch) is that doing
> > this:
> >
> >   master:remotes/incoming/master
> >
> > will create "refs/heads/remotes/incoming/master". Perhaps we should DWYM
> > a little more and recognize "heads", "remotes", and "tags" as special.
> 
> Yes, it is an independent issue; I think correcting this DWIM (or at least
> "warning" if not refusing to create remotes/ under refs/heads/) might be a
> good idea.

OK, I'll try to work up a patch.

-Peff

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

* Re: [PATCH] push: support remote branches in guess_ref DWIM
  2009-10-27  1:45   ` Jeff King
@ 2009-10-27 22:33     ` Junio C Hamano
  2009-10-28  0:01       ` Jeff King
  0 siblings, 1 reply; 5+ messages in thread
From: Junio C Hamano @ 2009-10-27 22:33 UTC (permalink / raw)
  To: Jeff King; +Cc: git

Jeff King <peff@peff.net> writes:

> On Mon, Oct 26, 2009 at 04:31:57PM -0700, Junio C Hamano wrote:
>
>> As _our_ origin can never be _their_ origin if we are clone of them, I do
>> not think anybody sane would expect it to push into refs/remotes/origin/
>> to begin with.
>
> OK, I agree.
>
>> But "not in refs/remotes/" does not automatically mean "the only sensible
>> place is refs/heads", does it?  "We do not know what kind of mistake the
>> user is trying to make" could be more plausible answer, and in that case,
>> "complain and die" may be a more valid course of action.
>
> The thing is that I can't think of another sensible place. And this
> sensible place is useful for one particular action: renaming a remote
> branch, like this:
>
>   $ git fetch ;# presumably gets origin/branch
>   $ git push origin/branch:renamed-branch
>
> which is much nicer than exposing clueless users to
> ":refs/heads/renamed-branch".

You would need to expose ":refs/heads/branch" to make this a rename, not a
copy, wouldn't you?

>> For example,
>> 
>>     git push origin origin/master:refs/heads/master
>> 
>> is most likely to be a mistake.  The only situation something similar to
>> this makes sense is where you pushed out a bogus commit earlier and are
>> trying to correct it perhaps with
>
> I'm not sure why it's likely to be a mistake.
> ...
> Am I missing some part of your argument?

I do not see much point (other than your "rename" example) in pushing what
you got from the other end without changing anything yourself back to the
same remote.

There was a thread in which people argued that the primary thing that is
dangerous in this sequence

    $ git checkout origin/next; work-commit; work-commit; ...

is when you leave the detached HEAD state without saving it to a local
branch.  I think what is more dangerous is that it will not give the user
a solid understanding that these commits do _not_ change origin/next in
any way.  After doing the above, it is understandable that a novice would
mistakenly think: "I started from origin/next and built some, let's push
the result".

	Side note: This is the reason why I think Dscho's "git checkout
        next" that dwims to "-t -b next origin/next" is OK (perhaps on the
        right side of the borderline), because it is more clear that this
        is about creating and using your own "next", compared to the
        existing "-t origin/next" shorthand.  The latter risks imprinting
        a misconception on an uninitiated that we are somehow working on
        origin/next.

With such a misconception, you will see the likely mistake here, too:

    $ git push origin origin/next:refs/heads/next

If "rename" is the _only_ valid reason you might want to push what you got
from there back to the same remote, _and_ if "rename" is something very
often needed, I think we would prefer to have a way to support that
operation directly, instead of more general DWIM that would risk passing
mistakes like the above unwarned.

> ...  But I'm not sure why
> you would accidentally provide something in refs/remotes, or not want to
> be pushing to refs/heads. Where _else_ do you push, except for tags?

The above "checking out origin/next" illustrates the mistake on the $src
side, not on the $dst side.  That's why my alternative solution in the
previous message was to see the type of $src and push commits to local
branches, exactly because "where else do you push".  

IOW, it's between "prevent push with dubious $src from happening in the
first place" vs "give them rope".  Historically I always sided with the
latter camp, but I am trying to play a devil's advocate for a change ;-).

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

* Re: [PATCH] push: support remote branches in guess_ref DWIM
  2009-10-27 22:33     ` Junio C Hamano
@ 2009-10-28  0:01       ` Jeff King
  0 siblings, 0 replies; 5+ messages in thread
From: Jeff King @ 2009-10-28  0:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Tue, Oct 27, 2009 at 03:33:16PM -0700, Junio C Hamano wrote:

> >   $ git fetch ;# presumably gets origin/branch
> >   $ git push origin/branch:renamed-branch
> >
> > which is much nicer than exposing clueless users to
> > ":refs/heads/renamed-branch".
> 
> You would need to expose ":refs/heads/branch" to make this a rename, not a
> copy, wouldn't you?

Yeah, you're right. This was based on an actual user request, and I
didn't think too closely about the other steps. But since the deletion
is of an existing branch, you should be able to do that without
refs/heads. So:

  $ git push origin origin/branch:renamed-branch
  $ git push origin :branch

Which of course you could do in one command if you wanted to live
(more) dangerously.

> > Am I missing some part of your argument?
> 
> I do not see much point (other than your "rename" example) in pushing what
> you got from the other end without changing anything yourself back to the
> same remote.

I don't either; my hope was that we can make that case a little bit
easier without creating undue hardship for anybody else.

> There was a thread in which people argued that the primary thing that is
> dangerous in this sequence
> 
>     $ git checkout origin/next; work-commit; work-commit; ...
> 
> is when you leave the detached HEAD state without saving it to a local
> branch.  I think what is more dangerous is that it will not give the user
> a solid understanding that these commits do _not_ change origin/next in
> any way.  After doing the above, it is understandable that a novice would
> mistakenly think: "I started from origin/next and built some, let's push
> the result".

I suppose it's possible. I don't have any evidence that users actually
think that way.

> With such a misconception, you will see the likely mistake here, too:
> 
>     $ git push origin origin/next:refs/heads/next
> 
> If "rename" is the _only_ valid reason you might want to push what you got
> from there back to the same remote, _and_ if "rename" is something very
> often needed, I think we would prefer to have a way to support that
> operation directly, instead of more general DWIM that would risk passing
> mistakes like the above unwarned.

OK, I can buy that. It would be much nicer even to support explicit
renaming (in fact, the user request started with that, and I just didn't
want to give them an answer that involved refs/heads/, which I think is
unnecessarily scary to users).

> IOW, it's between "prevent push with dubious $src from happening in the
> first place" vs "give them rope".  Historically I always sided with the
> latter camp, but I am trying to play a devil's advocate for a change ;-).

Heh. Thanks for explaining your thinking.

Let's scrap this for now, then. Remote rename doesn't actually come up
very often, and I agree that it would be nice to have an actual atomic
movement, which is what people really want.

-Peff

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

end of thread, other threads:[~2009-10-28  0:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-26 21:33 [PATCH] push: support remote branches in guess_ref DWIM Jeff King
2009-10-26 23:31 ` Junio C Hamano
2009-10-27  1:45   ` Jeff King
2009-10-27 22:33     ` Junio C Hamano
2009-10-28  0:01       ` Jeff King

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).