git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Carlos Martín Nieto" <cmn@elego.de>
To: Jeff King <peff@peff.net>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] branch: make --set-upstream saner without an explicit starting point
Date: Thu, 05 Jul 2012 18:34:25 +0200	[thread overview]
Message-ID: <1341506065.10752.19.camel@flaca.cmartin.tk> (raw)
In-Reply-To: <20120705094213.GA29740@sigill.intra.peff.net>

On Thu, 2012-07-05 at 05:42 -0400, Jeff King wrote:
> On Thu, Jul 05, 2012 at 11:29:49AM +0200, Carlos Martín Nieto wrote:
> 
> > The branch command assumes HEAD as the starting point if none is
> > specified. This causes --set-upstream to behave unexpectedly if the
> > user types
> > 
> >     git branch --set-upstream origin/master
> > 
> > git-branch will assume a second argument of HEAD and create config
> > entries for a local branch origin/master to track the current
> > branch. This is rarely, if ever, what the user wants to do.
> > 
> > Catch invocations with --set-upstream and only one branch so the
> > command above sets up the current branch to track origin's master
> > branch.
> 
> I have been tempted to write this patch several times but was afraid
> that somebody was relying on the existing behavior. I think the behavior
> you propose is much saner.

Those two people who rely on the current behaviour will just have to
make a sacrifice for the good of the rest of the user community. I guess
we could introduce it in steps by first warning, but I doubt it would be
worth the effort.

> 
> > +# The unsets at the end is to leave the master config as we found it,
> > +# so later tests don't get confused
> > +
> > +test_expect_success 'set upstream with implicit HEAD as branch to modify' \
> > +    'git config remote.local.url . &&
> > +     git config remote.local.fetch refs/heads/master:refs/remotes/local/master &&
> > +     (git show-ref -q refs/remotes/local/master || git fetch local) &&
> > +     git branch --set-upstream local/master &&
> > +     test $(git config branch.master.remote) = local &&
> > +     test $(git config branch.master.merge) = refs/heads/master
> > +     git config --unset branch.master.remote &&
> > +     git config --unset branch.master.merge
> > +'
> 
> The unsets will not run if the test fails. Use test_when_finished to
> insert cleanup, or better yet use test_config which handles this case
> automagically (you are not setting them initially, but perhaps you
> should set them to some known value initially to make sure that your
> command changes them as expected).

Considering that the unset is there only because a later test does 'git
fetch' instead of specifying which remote we should fetch from, and this
setting confuses it (expecting to fetch from origin, but instead
fetching from local), I wonder if it wouldn't be better to simply make
the fetch explicit in line 712 so it reads 'git fetch origin'. This way
we can forget about undoing the configuration, because we're overriding
it anyway.
> 
> I don't understand the point of the show-ref call, though. Isn't the
> fetch idempotent, and you can just run it always?

That is a good point. I just copied what the --track tests are doing a
few tests up. Looking at more tests, it seems to be what most do. Maybe
something like this:

---8<---

Subject: branch: make --set-upstream saner without an explicit
 starting point

The branch command assumes HEAD as the starting point if none is
specified. This causes --set-upstream to behave unexpectedly if the
user types

    git branch --set-upstream origin/master

git-branch will assume a second argument of HEAD and create config
entries for a local branch origin/master to track the current
branch. This is rarely, if ever, what the user wants to do.

Catch invocations with --set-upstream and only one branch so the
command above sets up the current branch to track origin's master
branch.

Signed-off-by: Carlos Martín Nieto <cmn@elego.de>
---
 builtin/branch.c  | 16 ++++++++++++++--
 t/t3200-branch.sh | 20 +++++++++++++++++++-
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 0e060f2..6bbabda 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -853,10 +853,22 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		else
 			usage_with_options(builtin_branch_usage, options);
 	} else if (argc > 0 && argc <= 2) {
+		const char *branch, *upstream;
 		if (kinds != REF_LOCAL_BRANCH)
 			die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
-		create_branch(head, argv[0], (argc == 2) ? argv[1] : head,
-			      force_create, reflog, 0, quiet, track);
+
+		/* The usual way, make the branch point be HEAD of none is specified */
+		branch = argv[0];
+		upstream = (argc == 2) ? argv[1] : head;
+
+		/* If the command was 'git branch --set-upstream origin/master',
+		   make HEAD track origin/master, not the other way around */
+		if (track == BRANCH_TRACK_OVERRIDE && argc == 1) {
+			branch = head;
+			upstream = argv[0];
+		}
+
+		create_branch(head, branch, upstream, force_create, reflog, 0, quiet, track);
 	} else
 		usage_with_options(builtin_branch_usage, options);
 
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index a17f8b2..1b0a73c 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -369,6 +369,24 @@ test_expect_success \
     'git tag foobar &&
      test_must_fail git branch --track my11 foobar'
 
+test_expect_success 'set upstream with both branches explicit' \
+    'git config remote.local.url . &&
+     git config remote.local.fetch refs/heads/master:refs/remotes/local/master &&
+     git fetch local &&
+     git branch --no-track my12 &&
+     git branch --set-upstream my12 local/master &&
+     test $(git config branch.my12.remote) = local &&
+     test $(git config branch.my12.merge) = refs/heads/master'
+
+test_expect_success 'set upstream with implicit HEAD as branch to modify' \
+    'git config remote.local.url . &&
+     git config remote.local.fetch refs/heads/master:refs/remotes/local/master &&
+     git fetch local &&
+     git branch --set-upstream local/master &&
+     test $(git config branch.master.remote) = local &&
+     test $(git config branch.master.merge) = refs/heads/master
+'
+
 # Keep this test last, as it changes the current branch
 cat >expect <<EOF
 $_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000	branch: Created from master
@@ -686,7 +704,7 @@ test_expect_success 'use set-upstream on the current branch' '
 	git --bare init myupstream.git &&
 	git push myupstream.git master:refs/heads/frotz &&
 	git remote add origin myupstream.git &&
-	git fetch &&
+	git fetch origin &&
 	git branch --set-upstream master origin/frotz &&
 
 	test "z$(git config branch.master.remote)" = "zorigin" &&
-- 
1.7.11.1.104.ge7b44f1

  reply	other threads:[~2012-07-05 16:34 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-05  9:29 [PATCH] branch: make --set-upstream saner without an explicit starting point Carlos Martín Nieto
2012-07-05  9:42 ` Jeff King
2012-07-05 16:34   ` Carlos Martín Nieto [this message]
2012-07-05 17:03 ` Junio C Hamano
2012-07-05 17:44   ` Junio C Hamano
2012-07-06  7:18     ` Carlos Martín Nieto
2012-07-06  7:29       ` Junio C Hamano
2012-07-06  8:03         ` Carlos Martín Nieto
2012-07-18  5:56           ` Junio C Hamano
2012-07-18 15:33             ` Carlos Martín Nieto
2012-08-16 21:58               ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1341506065.10752.19.camel@flaca.cmartin.tk \
    --to=cmn@elego.de \
    --cc=git@vger.kernel.org \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).