3 test_description
='checkout <branch>
5 Ensures that checkout on an unborn branch does what the user expects'
9 # Is the current branch "refs/heads/$1"?
11 printf "%s\n" "refs/heads/$1" >expect.HEAD
&&
12 git symbolic-ref HEAD
>actual.HEAD
&&
13 test_cmp expect.HEAD actual.HEAD
16 # Is branch "refs/heads/$1" set to pull from "$2/$3"?
17 test_branch_upstream
() {
18 printf "%s\n" "$2" "refs/heads/$3" >expect.upstream
&&
20 git config
"branch.$1.remote" &&
21 git config
"branch.$1.merge"
23 test_cmp expect.upstream actual.upstream
26 status_uno_is_clean
() {
27 git status
-uno --porcelain >status.actual
&&
28 test_must_be_empty status.actual
31 test_expect_success
'setup' '
32 test_commit my_main &&
37 git checkout -b foo &&
39 git checkout -b bar &&
41 git checkout -b ambiguous_branch_and_file &&
42 test_commit a_ambiguous_branch_and_file
48 git checkout -b foo &&
50 git checkout -b baz &&
52 git checkout -b ambiguous_branch_and_file &&
53 test_commit b_ambiguous_branch_and_file
55 git remote add repo_a repo_a &&
56 git remote add repo_b repo_b &&
57 git config remote.repo_b.fetch \
58 "+refs/heads/*:refs/remotes/other_b/*" &&
62 test_expect_success
'checkout of non-existing branch fails' '
63 git checkout -B main &&
64 test_might_fail git branch -D xyzzy &&
66 test_must_fail git checkout xyzzy &&
67 status_uno_is_clean &&
68 test_must_fail git rev-parse --verify refs/heads/xyzzy &&
72 test_expect_success
'checkout of branch from multiple remotes fails #1' '
73 git checkout -B main &&
74 test_might_fail git branch -D foo &&
76 test_must_fail git checkout foo &&
77 status_uno_is_clean &&
78 test_must_fail git rev-parse --verify refs/heads/foo &&
82 test_expect_success
'when arg matches multiple remotes, do not fallback to interpreting as pathspec' '
83 # create a file with name matching remote branch name
84 git checkout -b t_ambiguous_branch_and_file &&
85 >ambiguous_branch_and_file &&
86 git add ambiguous_branch_and_file &&
87 git commit -m "ambiguous_branch_and_file" &&
89 # modify file to verify that it will not be touched by checkout
90 test_when_finished "git checkout -- ambiguous_branch_and_file" &&
91 echo "file contents" >ambiguous_branch_and_file &&
92 cp ambiguous_branch_and_file expect &&
94 test_must_fail git checkout ambiguous_branch_and_file 2>err &&
96 test_i18ngrep "matched multiple (2) remote tracking branches" err &&
98 # file must not be altered
99 test_cmp expect ambiguous_branch_and_file
102 test_expect_success
'checkout of branch from multiple remotes fails with advice' '
103 git checkout -B main &&
104 test_might_fail git branch -D foo &&
105 test_must_fail git checkout foo 2>stderr &&
107 status_uno_is_clean &&
108 test_i18ngrep "^hint: " stderr &&
109 test_must_fail git -c advice.checkoutAmbiguousRemoteBranchName=false \
110 checkout foo 2>stderr &&
112 status_uno_is_clean &&
113 test_i18ngrep ! "^hint: " stderr
116 test_expect_success PERL
'checkout -p with multiple remotes does not print advice' '
117 git checkout -B main &&
118 test_might_fail git branch -D foo &&
120 git checkout -p foo 2>stderr &&
121 test_i18ngrep ! "^hint: " stderr &&
125 test_expect_success
'checkout of branch from multiple remotes succeeds with checkout.defaultRemote #1' '
126 git checkout -B main &&
127 status_uno_is_clean &&
128 test_might_fail git branch -D foo &&
130 git -c checkout.defaultRemote=repo_a checkout foo &&
131 status_uno_is_clean &&
133 test_cmp_rev remotes/repo_a/foo HEAD &&
134 test_branch_upstream foo repo_a foo
137 test_expect_success
'checkout of branch from a single remote succeeds #1' '
138 git checkout -B main &&
139 test_might_fail git branch -D bar &&
142 status_uno_is_clean &&
144 test_cmp_rev remotes/repo_a/bar HEAD &&
145 test_branch_upstream bar repo_a bar
148 test_expect_success
'checkout of branch from a single remote succeeds #2' '
149 git checkout -B main &&
150 test_might_fail git branch -D baz &&
153 status_uno_is_clean &&
155 test_cmp_rev remotes/other_b/baz HEAD &&
156 test_branch_upstream baz repo_b baz
159 test_expect_success
'--no-guess suppresses branch auto-vivification' '
160 git checkout -B main &&
161 status_uno_is_clean &&
162 test_might_fail git branch -D bar &&
164 test_must_fail git checkout --no-guess bar &&
165 test_must_fail git rev-parse --verify refs/heads/bar &&
169 test_expect_success
'checkout.guess = false suppresses branch auto-vivification' '
170 git checkout -B main &&
171 status_uno_is_clean &&
172 test_might_fail git branch -D bar &&
174 test_config checkout.guess false &&
175 test_must_fail git checkout bar &&
176 test_must_fail git rev-parse --verify refs/heads/bar &&
180 test_expect_success
'setup more remotes with unconventional refspecs' '
181 git checkout -B main &&
182 status_uno_is_clean &&
186 test_commit c_main &&
187 git checkout -b bar &&
189 git checkout -b spam &&
195 test_commit d_main &&
196 git checkout -b baz &&
198 git checkout -b eggs &&
201 git remote add repo_c repo_c &&
202 git config remote.repo_c.fetch \
203 "+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*" &&
204 git remote add repo_d repo_d &&
205 git config remote.repo_d.fetch \
206 "+refs/heads/*:refs/repo_d/*" &&
210 test_expect_success
'checkout of branch from multiple remotes fails #2' '
211 git checkout -B main &&
212 status_uno_is_clean &&
213 test_might_fail git branch -D bar &&
215 test_must_fail git checkout bar &&
216 status_uno_is_clean &&
217 test_must_fail git rev-parse --verify refs/heads/bar &&
221 test_expect_success
'checkout of branch from multiple remotes fails #3' '
222 git checkout -B main &&
223 status_uno_is_clean &&
224 test_might_fail git branch -D baz &&
226 test_must_fail git checkout baz &&
227 status_uno_is_clean &&
228 test_must_fail git rev-parse --verify refs/heads/baz &&
232 test_expect_success
'checkout of branch from a single remote succeeds #3' '
233 git checkout -B main &&
234 status_uno_is_clean &&
235 test_might_fail git branch -D spam &&
238 status_uno_is_clean &&
240 test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
241 test_branch_upstream spam repo_c spam
244 test_expect_success
'checkout of branch from a single remote succeeds #4' '
245 git checkout -B main &&
246 status_uno_is_clean &&
247 test_might_fail git branch -D eggs &&
250 status_uno_is_clean &&
252 test_cmp_rev refs/repo_d/eggs HEAD &&
253 test_branch_upstream eggs repo_d eggs
256 test_expect_success
'checkout of branch with a file having the same name fails' '
257 git checkout -B main &&
258 status_uno_is_clean &&
259 test_might_fail git branch -D spam &&
262 test_must_fail git checkout spam &&
263 status_uno_is_clean &&
264 test_must_fail git rev-parse --verify refs/heads/spam &&
268 test_expect_success
'checkout of branch with a file in subdir having the same name fails' '
269 git checkout -B main &&
270 status_uno_is_clean &&
271 test_might_fail git branch -D spam &&
276 test_must_fail git -C sub checkout spam &&
277 status_uno_is_clean &&
278 test_must_fail git rev-parse --verify refs/heads/spam &&
282 test_expect_success
'checkout <branch> -- succeeds, even if a file with the same name exists' '
283 git checkout -B main &&
284 status_uno_is_clean &&
285 test_might_fail git branch -D spam &&
288 git checkout spam -- &&
289 status_uno_is_clean &&
291 test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
292 test_branch_upstream spam repo_c spam
295 test_expect_success
'loosely defined local base branch is reported correctly' '
298 status_uno_is_clean &&
301 git commit --allow-empty -m "a bit more" &&
303 test_config branch.strict.remote . &&
304 test_config branch.loose.remote . &&
305 test_config branch.strict.merge refs/heads/main &&
306 test_config branch.loose.merge main &&
308 git checkout strict >expect.raw 2>&1 &&
309 sed -e "s/strict/BRANCHNAME/g" <expect.raw >expect &&
310 status_uno_is_clean &&
311 git checkout loose >actual.raw 2>&1 &&
312 sed -e "s/loose/BRANCHNAME/g" <actual.raw >actual &&
313 status_uno_is_clean &&
314 grep BRANCHNAME actual &&
316 test_cmp expect actual
319 test_expect_success
'reject when arg could be part of dwim branch' '
320 git remote add foo file://non-existent-place &&
321 git update-ref refs/remotes/foo/dwim-arg HEAD &&
322 echo foo >dwim-arg &&
324 echo bar >dwim-arg &&
325 test_must_fail git checkout dwim-arg &&
326 test_must_fail git rev-parse refs/heads/dwim-arg -- &&
330 test_expect_success
'disambiguate dwim branch and checkout path (1)' '
331 git update-ref refs/remotes/foo/dwim-arg1 HEAD &&
332 echo foo >dwim-arg1 &&
334 echo bar >dwim-arg1 &&
335 git checkout -- dwim-arg1 &&
336 test_must_fail git rev-parse refs/heads/dwim-arg1 -- &&
340 test_expect_success
'disambiguate dwim branch and checkout path (2)' '
341 git update-ref refs/remotes/foo/dwim-arg2 HEAD &&
342 echo foo >dwim-arg2 &&
344 echo bar >dwim-arg2 &&
345 git checkout dwim-arg2 -- &&
346 git rev-parse refs/heads/dwim-arg2 -- &&