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