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