diff --git a/branch.c b/branch.c index 6ae6a4c321..beaf11d97c 100644 --- a/branch.c +++ b/branch.c @@ -197,6 +197,21 @@ int validate_new_branchname(const char *name, struct strbuf *ref, return 1; } +static int check_tracking_branch(struct remote *remote, void *cb_data) +{ + char *tracking_branch = cb_data; + struct refspec query; + memset(&query, 0, sizeof(struct refspec)); + query.dst = tracking_branch; + return !(remote_find_tracking(remote, &query) || + prefixcmp(query.src, "refs/heads/")); +} + +static int validate_remote_tracking_branch(char *ref) +{ + return !for_each_remote(check_tracking_branch, ref); +} + static const char upstream_not_branch[] = N_("Cannot setup tracking information; starting point '%s' is not a branch."); static const char upstream_missing[] = @@ -259,7 +274,7 @@ void create_branch(const char *head, case 1: /* Unique completion -- good, only if it is a real branch */ if (prefixcmp(real_ref, "refs/heads/") && - prefixcmp(real_ref, "refs/remotes/")) { + validate_remote_tracking_branch(real_ref)) { if (explicit_tracking) die(_(upstream_not_branch), start_name); else diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh index 31e3d47b80..dee55e428f 100755 --- a/t/t2024-checkout-dwim.sh +++ b/t/t2024-checkout-dwim.sh @@ -154,7 +154,7 @@ test_expect_success 'checkout of branch from a single remote succeeds #3' ' test_branch_upstream spam repo_c spam ' -test_expect_failure 'checkout of branch from a single remote succeeds #4' ' +test_expect_success 'checkout of branch from a single remote succeeds #4' ' git checkout -B master && test_might_fail git branch -D eggs && diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 1bfdadc969..44ec6a45f4 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -317,7 +317,7 @@ test_expect_success 'test tracking setup (non-wildcard, matching)' ' test $(git config branch.my4.merge) = refs/heads/master ' -test_expect_failure 'tracking setup fails on non-matching refspec' ' +test_expect_success 'tracking setup fails on non-matching refspec' ' git config remote.local.url . && git config remote.local.fetch refs/heads/s:refs/remotes/local/s && (git show-ref -q refs/remotes/local/master || git fetch local) &&