Code

branch/checkout --track: Ensure that upstream branch is indeed a branch
authorJohan Herland <johan@herland.net>
Wed, 16 Feb 2011 23:12:20 +0000 (00:12 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 17 Feb 2011 00:55:56 +0000 (16:55 -0800)
When creating a new branch using the --track option, we must make sure that
we don't try to set an upstream that does not make sense to follow (using
'git pull') or update (using 'git push'). The current code checks against
using HEAD as upstream (since tracking a symref doesn't make sense). However,
tracking a tag doesn't make sense either. Indeed, tracking _any_ ref that is
not a (local or remote) branch doesn't make sense, and should be disallowed.

This patch achieves this by checking that the ref we're trying to --track
resides within refs/heads/* or refs/remotes/*. This new check replaces the
previous check against HEAD.

A couple of testcases are also added, verifying that we cannot create
branches with tags as upstreams.

Finally, some selftests relying on using a non-branch as an upstream have
been reworked or removed:

- t6040: Reverse the meaning of two tests that depend on the ability to
use (lightweight and annotated) tags as upstreams. These two tests were
originally added in commits 1be570f and 57ffc5f, and this patch reverts the
intention of those two commits.

- t7201: Remove part of a test (introduced in 9188ed8) relying on a
non-branch as upstream.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
branch.c
t/t3200-branch.sh
t/t6040-tracking-info.sh
t/t7201-co.sh

index 93dc866f8c09a2da2308c4fd677178b043f2d4d5..da5c03e56545b79cb92dd850ed09e81c21f9162f 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -175,9 +175,14 @@ void create_branch(const char *head,
                        die("Cannot setup tracking information; starting point is not a branch.");
                break;
        case 1:
-               /* Unique completion -- good, only if it is a real ref */
-               if (explicit_tracking && !strcmp(real_ref, "HEAD"))
-                       die("Cannot setup tracking information; starting point is not a branch.");
+               /* Unique completion -- good, only if it is a real branch */
+               if (prefixcmp(real_ref, "refs/heads/") &&
+                   prefixcmp(real_ref, "refs/remotes/")) {
+                       if (explicit_tracking)
+                               die("Cannot setup tracking information; starting point is not a branch.");
+                       else
+                               real_ref = NULL;
+               }
                break;
        default:
                die("Ambiguous object name: '%s'.", start_name);
index f54a533456d74a3eb2f745dbc77c8ad5a5ae960f..55af032f2e325a0399186097fa3a59690a8a9449 100755 (executable)
@@ -212,6 +212,11 @@ test_expect_success \
     'branch from non-branch HEAD w/--track causes failure' \
     'test_must_fail git branch --track my10 HEAD^'
 
+test_expect_success \
+    'branch from tag w/--track causes failure' \
+    'git tag foobar &&
+     test_must_fail git branch --track my11 foobar'
+
 # Keep this test last, as it changes the current branch
 cat >expect <<EOF
 0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000     branch: Created from master
@@ -477,6 +482,15 @@ test_expect_success 'autosetuprebase always on an untracked remote branch' '
        test "z$(git config branch.myr20.rebase)" = z
 '
 
+test_expect_success 'autosetuprebase always on detached HEAD' '
+       git config branch.autosetupmerge always &&
+       test_when_finished git checkout master &&
+       git checkout HEAD^0 &&
+       git branch my11 &&
+       test -z "$(git config branch.my11.remote)" &&
+       test -z "$(git config branch.my11.merge)"
+'
+
 test_expect_success 'detect misconfigured autosetuprebase (bad value)' '
        git config branch.autosetuprebase garbage &&
        test_must_fail git branch
index 1785e178a4cb8fddd58d1b1db8062cf12825155e..10bf3dee3f538b72f4f98d59f180a771b728b996 100755 (executable)
@@ -74,20 +74,20 @@ test_expect_success 'status' '
        grep "have 1 and 1 different" actual
 '
 
-test_expect_success 'status when tracking lightweight tags' '
+test_expect_success 'fail to track lightweight tags' '
        git checkout master &&
        git tag light &&
-       git branch --track lighttrack light >actual &&
-       grep "set up to track" actual &&
-       git checkout lighttrack
+       test_must_fail git branch --track lighttrack light >actual &&
+       test_must_fail grep "set up to track" actual &&
+       test_must_fail git checkout lighttrack
 '
 
-test_expect_success 'status when tracking annotated tags' '
+test_expect_success 'fail to track annotated tags' '
        git checkout master &&
        git tag -m heavy heavy &&
-       git branch --track heavytrack heavy >actual &&
-       grep "set up to track" actual &&
-       git checkout heavytrack
+       test_must_fail git branch --track heavytrack heavy >actual &&
+       test_must_fail grep "set up to track" actual &&
+       test_must_fail git checkout heavytrack
 '
 
 test_expect_success 'setup tracking with branch --set-upstream on existing branch' '
index 1337fa5a2209d489c43f0a34c95a89053d3fd8bf..0c002ab6951752bbf1d466ff5d0a4668835ca57c 100755 (executable)
@@ -408,6 +408,15 @@ test_expect_success 'checkout w/--track from non-branch HEAD fails' '
     test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
 '
 
+test_expect_success 'checkout w/--track from tag fails' '
+    git checkout master^0 &&
+    test_must_fail git symbolic-ref HEAD &&
+    test_must_fail git checkout --track -b track frotz &&
+    test_must_fail git rev-parse --verify track &&
+    test_must_fail git symbolic-ref HEAD &&
+    test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
+'
+
 test_expect_success 'detach a symbolic link HEAD' '
     git checkout master &&
     git config --bool core.prefersymlinkrefs yes &&
@@ -423,7 +432,6 @@ test_expect_success 'detach a symbolic link HEAD' '
 test_expect_success \
     'checkout with --track fakes a sensible -b <name>' '
     git update-ref refs/remotes/origin/koala/bear renamer &&
-    git update-ref refs/new/koala/bear renamer &&
 
     git checkout --track origin/koala/bear &&
     test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
@@ -439,12 +447,6 @@ test_expect_success \
 
     git checkout --track remotes/origin/koala/bear &&
     test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
-    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
-
-    git checkout master && git branch -D koala/bear &&
-
-    git checkout --track refs/new/koala/bear &&
-    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
     test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
 '