t / t2024-checkout-dwim.shon commit Merge branch 'nd/no-the-index' (dc0f6f9)
   1#!/bin/sh
   2
   3test_description='checkout <branch>
   4
   5Ensures that checkout on an unborn branch does what the user expects'
   6
   7. ./test-lib.sh
   8
   9# Is the current branch "refs/heads/$1"?
  10test_branch () {
  11        printf "%s\n" "refs/heads/$1" >expect.HEAD &&
  12        git symbolic-ref HEAD >actual.HEAD &&
  13        test_cmp expect.HEAD actual.HEAD
  14}
  15
  16# Is branch "refs/heads/$1" set to pull from "$2/$3"?
  17test_branch_upstream () {
  18        printf "%s\n" "$2" "refs/heads/$3" >expect.upstream &&
  19        {
  20                git config "branch.$1.remote" &&
  21                git config "branch.$1.merge"
  22        } >actual.upstream &&
  23        test_cmp expect.upstream actual.upstream
  24}
  25
  26status_uno_is_clean () {
  27        git status -uno --porcelain >status.actual &&
  28        test_must_be_empty status.actual
  29}
  30
  31test_expect_success 'setup' '
  32        test_commit my_master &&
  33        git init repo_a &&
  34        (
  35                cd repo_a &&
  36                test_commit a_master &&
  37                git checkout -b foo &&
  38                test_commit a_foo &&
  39                git checkout -b bar &&
  40                test_commit a_bar
  41        ) &&
  42        git init repo_b &&
  43        (
  44                cd repo_b &&
  45                test_commit b_master &&
  46                git checkout -b foo &&
  47                test_commit b_foo &&
  48                git checkout -b baz &&
  49                test_commit b_baz
  50        ) &&
  51        git remote add repo_a repo_a &&
  52        git remote add repo_b repo_b &&
  53        git config remote.repo_b.fetch \
  54                "+refs/heads/*:refs/remotes/other_b/*" &&
  55        git fetch --all
  56'
  57
  58test_expect_success 'checkout of non-existing branch fails' '
  59        git checkout -B master &&
  60        test_might_fail git branch -D xyzzy &&
  61
  62        test_must_fail git checkout xyzzy &&
  63        status_uno_is_clean &&
  64        test_must_fail git rev-parse --verify refs/heads/xyzzy &&
  65        test_branch master
  66'
  67
  68test_expect_success 'checkout of branch from multiple remotes fails #1' '
  69        git checkout -B master &&
  70        test_might_fail git branch -D foo &&
  71
  72        test_must_fail git checkout foo &&
  73        status_uno_is_clean &&
  74        test_must_fail git rev-parse --verify refs/heads/foo &&
  75        test_branch master
  76'
  77
  78test_expect_success 'checkout of branch from multiple remotes fails with advice' '
  79        git checkout -B master &&
  80        test_might_fail git branch -D foo &&
  81        test_must_fail git checkout foo 2>stderr &&
  82        test_branch master &&
  83        status_uno_is_clean &&
  84        test_i18ngrep "^hint: " stderr &&
  85        test_must_fail git -c advice.checkoutAmbiguousRemoteBranchName=false \
  86                checkout foo 2>stderr &&
  87        test_branch master &&
  88        status_uno_is_clean &&
  89        test_i18ngrep ! "^hint: " stderr &&
  90        # Make sure the likes of checkout -p do not print this hint
  91        git checkout -p foo 2>stderr &&
  92        test_i18ngrep ! "^hint: " stderr &&
  93        status_uno_is_clean
  94'
  95
  96test_expect_success 'checkout of branch from multiple remotes succeeds with checkout.defaultRemote #1' '
  97        git checkout -B master &&
  98        status_uno_is_clean &&
  99        test_might_fail git branch -D foo &&
 100
 101        git -c checkout.defaultRemote=repo_a checkout foo &&
 102        status_uno_is_clean &&
 103        test_branch foo &&
 104        test_cmp_rev remotes/repo_a/foo HEAD &&
 105        test_branch_upstream foo repo_a foo
 106'
 107
 108test_expect_success 'checkout of branch from a single remote succeeds #1' '
 109        git checkout -B master &&
 110        test_might_fail git branch -D bar &&
 111
 112        git checkout bar &&
 113        status_uno_is_clean &&
 114        test_branch bar &&
 115        test_cmp_rev remotes/repo_a/bar HEAD &&
 116        test_branch_upstream bar repo_a bar
 117'
 118
 119test_expect_success 'checkout of branch from a single remote succeeds #2' '
 120        git checkout -B master &&
 121        test_might_fail git branch -D baz &&
 122
 123        git checkout baz &&
 124        status_uno_is_clean &&
 125        test_branch baz &&
 126        test_cmp_rev remotes/other_b/baz HEAD &&
 127        test_branch_upstream baz repo_b baz
 128'
 129
 130test_expect_success '--no-guess suppresses branch auto-vivification' '
 131        git checkout -B master &&
 132        status_uno_is_clean &&
 133        test_might_fail git branch -D bar &&
 134
 135        test_must_fail git checkout --no-guess bar &&
 136        test_must_fail git rev-parse --verify refs/heads/bar &&
 137        test_branch master
 138'
 139
 140test_expect_success 'setup more remotes with unconventional refspecs' '
 141        git checkout -B master &&
 142        status_uno_is_clean &&
 143        git init repo_c &&
 144        (
 145                cd repo_c &&
 146                test_commit c_master &&
 147                git checkout -b bar &&
 148                test_commit c_bar &&
 149                git checkout -b spam &&
 150                test_commit c_spam
 151        ) &&
 152        git init repo_d &&
 153        (
 154                cd repo_d &&
 155                test_commit d_master &&
 156                git checkout -b baz &&
 157                test_commit d_baz &&
 158                git checkout -b eggs &&
 159                test_commit d_eggs
 160        ) &&
 161        git remote add repo_c repo_c &&
 162        git config remote.repo_c.fetch \
 163                "+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*" &&
 164        git remote add repo_d repo_d &&
 165        git config remote.repo_d.fetch \
 166                "+refs/heads/*:refs/repo_d/*" &&
 167        git fetch --all
 168'
 169
 170test_expect_success 'checkout of branch from multiple remotes fails #2' '
 171        git checkout -B master &&
 172        status_uno_is_clean &&
 173        test_might_fail git branch -D bar &&
 174
 175        test_must_fail git checkout bar &&
 176        status_uno_is_clean &&
 177        test_must_fail git rev-parse --verify refs/heads/bar &&
 178        test_branch master
 179'
 180
 181test_expect_success 'checkout of branch from multiple remotes fails #3' '
 182        git checkout -B master &&
 183        status_uno_is_clean &&
 184        test_might_fail git branch -D baz &&
 185
 186        test_must_fail git checkout baz &&
 187        status_uno_is_clean &&
 188        test_must_fail git rev-parse --verify refs/heads/baz &&
 189        test_branch master
 190'
 191
 192test_expect_success 'checkout of branch from a single remote succeeds #3' '
 193        git checkout -B master &&
 194        status_uno_is_clean &&
 195        test_might_fail git branch -D spam &&
 196
 197        git checkout spam &&
 198        status_uno_is_clean &&
 199        test_branch spam &&
 200        test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
 201        test_branch_upstream spam repo_c spam
 202'
 203
 204test_expect_success 'checkout of branch from a single remote succeeds #4' '
 205        git checkout -B master &&
 206        status_uno_is_clean &&
 207        test_might_fail git branch -D eggs &&
 208
 209        git checkout eggs &&
 210        status_uno_is_clean &&
 211        test_branch eggs &&
 212        test_cmp_rev refs/repo_d/eggs HEAD &&
 213        test_branch_upstream eggs repo_d eggs
 214'
 215
 216test_expect_success 'checkout of branch with a file having the same name fails' '
 217        git checkout -B master &&
 218        status_uno_is_clean &&
 219        test_might_fail git branch -D spam &&
 220
 221        >spam &&
 222        test_must_fail git checkout spam &&
 223        status_uno_is_clean &&
 224        test_must_fail git rev-parse --verify refs/heads/spam &&
 225        test_branch master
 226'
 227
 228test_expect_success 'checkout of branch with a file in subdir having the same name fails' '
 229        git checkout -B master &&
 230        status_uno_is_clean &&
 231        test_might_fail git branch -D spam &&
 232
 233        >spam &&
 234        mkdir sub &&
 235        mv spam sub/spam &&
 236        test_must_fail git -C sub checkout spam &&
 237        status_uno_is_clean &&
 238        test_must_fail git rev-parse --verify refs/heads/spam &&
 239        test_branch master
 240'
 241
 242test_expect_success 'checkout <branch> -- succeeds, even if a file with the same name exists' '
 243        git checkout -B master &&
 244        status_uno_is_clean &&
 245        test_might_fail git branch -D spam &&
 246
 247        >spam &&
 248        git checkout spam -- &&
 249        status_uno_is_clean &&
 250        test_branch spam &&
 251        test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
 252        test_branch_upstream spam repo_c spam
 253'
 254
 255test_expect_success 'loosely defined local base branch is reported correctly' '
 256
 257        git checkout master &&
 258        status_uno_is_clean &&
 259        git branch strict &&
 260        git branch loose &&
 261        git commit --allow-empty -m "a bit more" &&
 262
 263        test_config branch.strict.remote . &&
 264        test_config branch.loose.remote . &&
 265        test_config branch.strict.merge refs/heads/master &&
 266        test_config branch.loose.merge master &&
 267
 268        git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
 269        status_uno_is_clean &&
 270        git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
 271        status_uno_is_clean &&
 272
 273        test_cmp expect actual
 274'
 275
 276test_done