cat-file: support "unordered" output for --batch-all-objects
[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         >status.expect &&
28         git status -uno --porcelain >status.actual &&
29         test_cmp status.expect status.actual
30 }
31
32 test_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
59 test_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
69 test_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
79 test_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         # Make sure the likes of checkout -p do not print this hint
92         git checkout -p foo 2>stderr &&
93         test_i18ngrep ! "^hint: " stderr &&
94         status_uno_is_clean
95 '
96
97 test_expect_success 'checkout of branch from multiple remotes succeeds with checkout.defaultRemote #1' '
98         git checkout -B master &&
99         status_uno_is_clean &&
100         test_might_fail git branch -D foo &&
101
102         git -c checkout.defaultRemote=repo_a checkout foo &&
103         status_uno_is_clean &&
104         test_branch foo &&
105         test_cmp_rev remotes/repo_a/foo HEAD &&
106         test_branch_upstream foo repo_a foo
107 '
108
109 test_expect_success 'checkout of branch from a single remote succeeds #1' '
110         git checkout -B master &&
111         test_might_fail git branch -D bar &&
112
113         git checkout bar &&
114         status_uno_is_clean &&
115         test_branch bar &&
116         test_cmp_rev remotes/repo_a/bar HEAD &&
117         test_branch_upstream bar repo_a bar
118 '
119
120 test_expect_success 'checkout of branch from a single remote succeeds #2' '
121         git checkout -B master &&
122         test_might_fail git branch -D baz &&
123
124         git checkout baz &&
125         status_uno_is_clean &&
126         test_branch baz &&
127         test_cmp_rev remotes/other_b/baz HEAD &&
128         test_branch_upstream baz repo_b baz
129 '
130
131 test_expect_success '--no-guess suppresses branch auto-vivification' '
132         git checkout -B master &&
133         status_uno_is_clean &&
134         test_might_fail git branch -D bar &&
135
136         test_must_fail git checkout --no-guess bar &&
137         test_must_fail git rev-parse --verify refs/heads/bar &&
138         test_branch master
139 '
140
141 test_expect_success 'setup more remotes with unconventional refspecs' '
142         git checkout -B master &&
143         status_uno_is_clean &&
144         git init repo_c &&
145         (
146                 cd repo_c &&
147                 test_commit c_master &&
148                 git checkout -b bar &&
149                 test_commit c_bar &&
150                 git checkout -b spam &&
151                 test_commit c_spam
152         ) &&
153         git init repo_d &&
154         (
155                 cd repo_d &&
156                 test_commit d_master &&
157                 git checkout -b baz &&
158                 test_commit d_baz &&
159                 git checkout -b eggs &&
160                 test_commit d_eggs
161         ) &&
162         git remote add repo_c repo_c &&
163         git config remote.repo_c.fetch \
164                 "+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*" &&
165         git remote add repo_d repo_d &&
166         git config remote.repo_d.fetch \
167                 "+refs/heads/*:refs/repo_d/*" &&
168         git fetch --all
169 '
170
171 test_expect_success 'checkout of branch from multiple remotes fails #2' '
172         git checkout -B master &&
173         status_uno_is_clean &&
174         test_might_fail git branch -D bar &&
175
176         test_must_fail git checkout bar &&
177         status_uno_is_clean &&
178         test_must_fail git rev-parse --verify refs/heads/bar &&
179         test_branch master
180 '
181
182 test_expect_success 'checkout of branch from multiple remotes fails #3' '
183         git checkout -B master &&
184         status_uno_is_clean &&
185         test_might_fail git branch -D baz &&
186
187         test_must_fail git checkout baz &&
188         status_uno_is_clean &&
189         test_must_fail git rev-parse --verify refs/heads/baz &&
190         test_branch master
191 '
192
193 test_expect_success 'checkout of branch from a single remote succeeds #3' '
194         git checkout -B master &&
195         status_uno_is_clean &&
196         test_might_fail git branch -D spam &&
197
198         git checkout spam &&
199         status_uno_is_clean &&
200         test_branch spam &&
201         test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
202         test_branch_upstream spam repo_c spam
203 '
204
205 test_expect_success 'checkout of branch from a single remote succeeds #4' '
206         git checkout -B master &&
207         status_uno_is_clean &&
208         test_might_fail git branch -D eggs &&
209
210         git checkout eggs &&
211         status_uno_is_clean &&
212         test_branch eggs &&
213         test_cmp_rev refs/repo_d/eggs HEAD &&
214         test_branch_upstream eggs repo_d eggs
215 '
216
217 test_expect_success 'checkout of branch with a file having the same name fails' '
218         git checkout -B master &&
219         status_uno_is_clean &&
220         test_might_fail git branch -D spam &&
221
222         >spam &&
223         test_must_fail git checkout spam &&
224         status_uno_is_clean &&
225         test_must_fail git rev-parse --verify refs/heads/spam &&
226         test_branch master
227 '
228
229 test_expect_success 'checkout of branch with a file in subdir having the same name fails' '
230         git checkout -B master &&
231         status_uno_is_clean &&
232         test_might_fail git branch -D spam &&
233
234         >spam &&
235         mkdir sub &&
236         mv spam sub/spam &&
237         test_must_fail git -C sub checkout spam &&
238         status_uno_is_clean &&
239         test_must_fail git rev-parse --verify refs/heads/spam &&
240         test_branch master
241 '
242
243 test_expect_success 'checkout <branch> -- succeeds, even if a file with the same name exists' '
244         git checkout -B master &&
245         status_uno_is_clean &&
246         test_might_fail git branch -D spam &&
247
248         >spam &&
249         git checkout spam -- &&
250         status_uno_is_clean &&
251         test_branch spam &&
252         test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
253         test_branch_upstream spam repo_c spam
254 '
255
256 test_expect_success 'loosely defined local base branch is reported correctly' '
257
258         git checkout master &&
259         status_uno_is_clean &&
260         git branch strict &&
261         git branch loose &&
262         git commit --allow-empty -m "a bit more" &&
263
264         test_config branch.strict.remote . &&
265         test_config branch.loose.remote . &&
266         test_config branch.strict.merge refs/heads/master &&
267         test_config branch.loose.merge master &&
268
269         git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
270         status_uno_is_clean &&
271         git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
272         status_uno_is_clean &&
273
274         test_cmp expect actual
275 '
276
277 test_done