git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH] checkout: report upstream correctly even with loosely defined branch.*.merge
Date: Tue, 14 Oct 2014 15:14:28 -0700	[thread overview]
Message-ID: <xmqqbnpexprv.fsf@gitster.dls.corp.google.com> (raw)
In-Reply-To: xmqqa9e67atv.fsf@gitster.dls.corp.google.com

When checking out a branch that is set to build on top of another
branch (often, a remote-tracking branch), "git checkout" reports how
your work relates to the other branch, e.g.

    Your branch is behind 'origin/master', and can be fast-forwarded.

Back when this feature was introduced, this was only done for
branches that build on remote-tracking branches, but 5e6e2b48 (Make
local branches behave like remote branches when --tracked,
2009-04-01) added support to give the same report for branches that
build on other local branches (i.e. branches whose branch.*.remote
variables are set to '.').  Unlike the support for the branches
building on remote-tracking branches, however, this did not take
into account the fact that branch.*.merge configuration is allowed
to record a shortened branch name.

When branch.*.merge is set to 'master' (not 'refs/heads/master'),
i.e. "my branch builds on the local 'master' branch", this caused
"git checkout" to report:

    Your branch is based on 'master', but the upstream is gone.

The upstream is our repository and is definitely not gone, so this
output is nonsense.

The fix is fairly obvious; just like the branch name is DWIMed when
"git pull" merges from the 'master' branch without complaint on such
a branch, the name of the branch the current branch builds upon
needs to be DWIMed the same way.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 remote.c                 | 34 +++++++++++++++++++++++-----------
 t/t2024-checkout-dwim.sh | 18 ++++++++++++++++++
 2 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/remote.c b/remote.c
index 0e9459c..ecbe363 100644
--- a/remote.c
+++ b/remote.c
@@ -1611,6 +1611,27 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
 	}
 }
 
+static void set_merge(struct branch *ret)
+{
+	char *ref;
+	unsigned char sha1[20];
+	int i;
+
+	ret->merge = xcalloc(ret->merge_nr, sizeof(*ret->merge));
+	for (i = 0; i < ret->merge_nr; i++) {
+		ret->merge[i] = xcalloc(1, sizeof(**ret->merge));
+		ret->merge[i]->src = xstrdup(ret->merge_name[i]);
+		if (!remote_find_tracking(ret->remote, ret->merge[i]) ||
+		    strcmp(ret->remote_name, "."))
+			continue;
+		if (dwim_ref(ret->merge_name[i], strlen(ret->merge_name[i]),
+			     sha1, &ref) == 1)
+			ret->merge[i]->dst = ref;
+		else
+			ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
+	}
+}
+
 struct branch *branch_get(const char *name)
 {
 	struct branch *ret;
@@ -1622,17 +1643,8 @@ struct branch *branch_get(const char *name)
 		ret = make_branch(name, 0);
 	if (ret && ret->remote_name) {
 		ret->remote = remote_get(ret->remote_name);
-		if (ret->merge_nr) {
-			int i;
-			ret->merge = xcalloc(ret->merge_nr, sizeof(*ret->merge));
-			for (i = 0; i < ret->merge_nr; i++) {
-				ret->merge[i] = xcalloc(1, sizeof(**ret->merge));
-				ret->merge[i]->src = xstrdup(ret->merge_name[i]);
-				if (remote_find_tracking(ret->remote, ret->merge[i])
-				    && !strcmp(ret->remote_name, "."))
-					ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
-			}
-		}
+		if (ret->merge_nr)
+			set_merge(ret);
 	}
 	return ret;
 }
diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh
index 6ecb559..468a000 100755
--- a/t/t2024-checkout-dwim.sh
+++ b/t/t2024-checkout-dwim.sh
@@ -185,4 +185,22 @@ test_expect_success 'checkout <branch> -- succeeds, even if a file with the same
 	test_branch_upstream spam repo_c spam
 '
 
+test_expect_success 'loosely defined local base branch is reported correctly' '
+
+	git checkout master &&
+	git branch strict &&
+	git branch loose &&
+	git commit --allow-empty -m "a bit more" &&
+
+	test_config branch.strict.remote . &&
+	test_config branch.loose.remote . &&
+	test_config branch.strict.merge refs/heads/master &&
+	test_config branch.loose.merge master &&
+
+	git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
+	git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
+
+	test_cmp expect actual
+'
+
 test_done
-- 
2.1.2-492-gf8d07d7

      parent reply	other threads:[~2014-10-14 22:14 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-04 22:49 [Bug] branch.*.merge interpreted too strictly by tracking logic Junio C Hamano
2014-02-05 20:50 ` Jeff King
2014-02-05 21:05   ` Junio C Hamano
2014-02-05 21:08     ` Jeff King
2014-02-05 21:10       ` Junio C Hamano
2014-10-14 22:14 ` Junio C Hamano [this message]

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=xmqqbnpexprv.fsf@gitster.dls.corp.google.com \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    /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).