Merge branch 'nd/cherry-pick-quit-fix'
[git] / t / t2024-checkout-dwim.sh
1 #!/bin/sh
2
3 test_description='checkout <branch>
4
5 Ensures 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"?
10 test_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"?
17 test_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
26 status_uno_is_clean () {
27         git status -uno --porcelain >status.actual &&
28         test_must_be_empty status.actual
29 }
30
31 test_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
58 test_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
68 test_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
78 test_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
96 test_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
108 test_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
119 test_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
130 test_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
140 test_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
170 test_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
181 test_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
192 test_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
204 test_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
216 test_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
228 test_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
242 test_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
255 test_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
276 test_done