Merge branch 'jk/perf-no-dups'
[git] / t / t2020-checkout-detach.sh
1 #!/bin/sh
2
3 test_description='checkout into detached HEAD state'
4 . ./test-lib.sh
5
6 check_detached () {
7         test_must_fail git symbolic-ref -q HEAD >/dev/null
8 }
9
10 check_not_detached () {
11         git symbolic-ref -q HEAD >/dev/null
12 }
13
14 PREV_HEAD_DESC='Previous HEAD position was'
15 check_orphan_warning() {
16         test_i18ngrep "you are leaving $2 behind" "$1" &&
17         test_i18ngrep ! "$PREV_HEAD_DESC" "$1"
18 }
19 check_no_orphan_warning() {
20         test_i18ngrep ! "you are leaving .* commit.*behind" "$1" &&
21         test_i18ngrep "$PREV_HEAD_DESC" "$1"
22 }
23
24 reset () {
25         git checkout master &&
26         check_not_detached
27 }
28
29 test_expect_success 'setup' '
30         test_commit one &&
31         test_commit two &&
32         test_commit three && git tag -d three &&
33         test_commit four && git tag -d four &&
34         git branch branch &&
35         git tag tag
36 '
37
38 test_expect_success 'checkout branch does not detach' '
39         reset &&
40         git checkout branch &&
41         check_not_detached
42 '
43
44 test_expect_success 'checkout tag detaches' '
45         reset &&
46         git checkout tag &&
47         check_detached
48 '
49
50 test_expect_success 'checkout branch by full name detaches' '
51         reset &&
52         git checkout refs/heads/branch &&
53         check_detached
54 '
55
56 test_expect_success 'checkout non-ref detaches' '
57         reset &&
58         git checkout branch^ &&
59         check_detached
60 '
61
62 test_expect_success 'checkout ref^0 detaches' '
63         reset &&
64         git checkout branch^0 &&
65         check_detached
66 '
67
68 test_expect_success 'checkout --detach detaches' '
69         reset &&
70         git checkout --detach branch &&
71         check_detached
72 '
73
74 test_expect_success 'checkout --detach without branch name' '
75         reset &&
76         git checkout --detach &&
77         check_detached
78 '
79
80 test_expect_success 'checkout --detach errors out for non-commit' '
81         reset &&
82         test_must_fail git checkout --detach one^{tree} &&
83         check_not_detached
84 '
85
86 test_expect_success 'checkout --detach errors out for extra argument' '
87         reset &&
88         git checkout master &&
89         test_must_fail git checkout --detach tag one.t &&
90         check_not_detached
91 '
92
93 test_expect_success 'checkout --detached and -b are incompatible' '
94         reset &&
95         test_must_fail git checkout --detach -b newbranch tag &&
96         check_not_detached
97 '
98
99 test_expect_success 'checkout --detach moves HEAD' '
100         reset &&
101         git checkout one &&
102         git checkout --detach two &&
103         git diff --exit-code HEAD &&
104         git diff --exit-code two
105 '
106
107 test_expect_success 'checkout warns on orphan commits' '
108         reset &&
109         git checkout --detach two &&
110         echo content >orphan &&
111         git add orphan &&
112         git commit -a -m orphan1 &&
113         echo new content >orphan &&
114         git commit -a -m orphan2 &&
115         orphan2=$(git rev-parse HEAD) &&
116         git checkout master 2>stderr
117 '
118
119 test_expect_success 'checkout warns on orphan commits: output' '
120         check_orphan_warning stderr "2 commits"
121 '
122
123 test_expect_success 'checkout warns orphaning 1 of 2 commits' '
124         git checkout "$orphan2" &&
125         git checkout HEAD^ 2>stderr
126 '
127
128 test_expect_success 'checkout warns orphaning 1 of 2 commits: output' '
129         check_orphan_warning stderr "1 commit"
130 '
131
132 test_expect_success 'checkout does not warn leaving ref tip' '
133         reset &&
134         git checkout --detach two &&
135         git checkout master 2>stderr
136 '
137
138 test_expect_success 'checkout does not warn leaving ref tip' '
139         check_no_orphan_warning stderr
140 '
141
142 test_expect_success 'checkout does not warn leaving reachable commit' '
143         reset &&
144         git checkout --detach HEAD^ &&
145         git checkout master 2>stderr
146 '
147
148 test_expect_success 'checkout does not warn leaving reachable commit' '
149         check_no_orphan_warning stderr
150 '
151
152 cat >expect <<'EOF'
153 Your branch is behind 'master' by 1 commit, and can be fast-forwarded.
154   (use "git pull" to update your local branch)
155 EOF
156 test_expect_success 'tracking count is accurate after orphan check' '
157         reset &&
158         git branch child master^ &&
159         git config branch.child.remote . &&
160         git config branch.child.merge refs/heads/master &&
161         git checkout child^ &&
162         git checkout child >stdout &&
163         test_i18ncmp expect stdout
164 '
165
166 test_expect_success 'no advice given for explicit detached head state' '
167         # baseline
168         test_config advice.detachedHead true &&
169         git checkout child && git checkout HEAD^0 >expect.advice 2>&1 &&
170         test_config advice.detachedHead false &&
171         git checkout child && git checkout HEAD^0 >expect.no-advice 2>&1 &&
172         test_unconfig advice.detachedHead &&
173         # without configuration, the advice.* variables default to true
174         git checkout child && git checkout HEAD^0 >actual 2>&1 &&
175         test_cmp expect.advice actual &&
176
177         # with explicit --detach
178         # no configuration
179         test_unconfig advice.detachedHead &&
180         git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
181         test_cmp expect.no-advice actual &&
182
183         # explicitly decline advice
184         test_config advice.detachedHead false &&
185         git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
186         test_cmp expect.no-advice actual
187 '
188
189 # Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (new format)
190 test_expect_success 'describe_detached_head prints no SHA-1 ellipsis when not asked to' "
191
192         commit=$(git rev-parse --short=12 master^) &&
193         commit2=$(git rev-parse --short=12 master~2) &&
194         commit3=$(git rev-parse --short=12 master~3) &&
195
196         # The first detach operation is more chatty than the following ones.
197         cat >1st_detach <<-EOF &&
198         Note: switching to 'HEAD^'.
199
200         You are in 'detached HEAD' state. You can look around, make experimental
201         changes and commit them, and you can discard any commits you make in this
202         state without impacting any branches by switching back to a branch.
203
204         If you want to create a new branch to retain commits you create, you may
205         do so (now or later) by using -c with the switch command. Example:
206
207           git switch -c <new-branch-name>
208
209         Or undo this operation with:
210
211           git switch -
212
213         Turn off this advice by setting config variable advice.detachedHead to false
214
215         HEAD is now at \$commit three
216         EOF
217
218         # The remaining ones just show info about previous and current HEADs.
219         cat >2nd_detach <<-EOF &&
220         Previous HEAD position was \$commit three
221         HEAD is now at \$commit2 two
222         EOF
223
224         cat >3rd_detach <<-EOF &&
225         Previous HEAD position was \$commit2 two
226         HEAD is now at \$commit3 one
227         EOF
228
229         reset &&
230         check_not_detached &&
231
232         # Various ways of *not* asking for ellipses
233
234         sane_unset GIT_PRINT_SHA1_ELLIPSIS &&
235         git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
236         check_detached &&
237         test_i18ncmp 1st_detach actual &&
238
239         GIT_PRINT_SHA1_ELLIPSIS="no" git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
240         check_detached &&
241         test_i18ncmp 2nd_detach actual &&
242
243         GIT_PRINT_SHA1_ELLIPSIS= git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
244         check_detached &&
245         test_i18ncmp 3rd_detach actual &&
246
247         sane_unset GIT_PRINT_SHA1_ELLIPSIS &&
248
249         # We only have four commits, but we can re-use them
250         reset &&
251         check_not_detached &&
252
253         # Make no mention of the env var at all
254         git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
255         check_detached &&
256         test_i18ncmp 1st_detach actual &&
257
258         GIT_PRINT_SHA1_ELLIPSIS='nope' &&
259         git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
260         check_detached &&
261         test_i18ncmp 2nd_detach actual &&
262
263         GIT_PRINT_SHA1_ELLIPSIS=nein &&
264         git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
265         check_detached &&
266         test_i18ncmp 3rd_detach actual &&
267
268         true
269 "
270
271 # Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (old format)
272 test_expect_success 'describe_detached_head does print SHA-1 ellipsis when asked to' "
273
274         commit=$(git rev-parse --short=12 master^) &&
275         commit2=$(git rev-parse --short=12 master~2) &&
276         commit3=$(git rev-parse --short=12 master~3) &&
277
278         # The first detach operation is more chatty than the following ones.
279         cat >1st_detach <<-EOF &&
280         Note: switching to 'HEAD^'.
281
282         You are in 'detached HEAD' state. You can look around, make experimental
283         changes and commit them, and you can discard any commits you make in this
284         state without impacting any branches by switching back to a branch.
285
286         If you want to create a new branch to retain commits you create, you may
287         do so (now or later) by using -c with the switch command. Example:
288
289           git switch -c <new-branch-name>
290
291         Or undo this operation with:
292
293           git switch -
294
295         Turn off this advice by setting config variable advice.detachedHead to false
296
297         HEAD is now at \$commit... three
298         EOF
299
300         # The remaining ones just show info about previous and current HEADs.
301         cat >2nd_detach <<-EOF &&
302         Previous HEAD position was \$commit... three
303         HEAD is now at \$commit2... two
304         EOF
305
306         cat >3rd_detach <<-EOF &&
307         Previous HEAD position was \$commit2... two
308         HEAD is now at \$commit3... one
309         EOF
310
311         reset &&
312         check_not_detached &&
313
314         # Various ways of asking for ellipses...
315         # The user can just use any kind of quoting (including none).
316
317         GIT_PRINT_SHA1_ELLIPSIS=yes git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
318         check_detached &&
319         test_i18ncmp 1st_detach actual &&
320
321         GIT_PRINT_SHA1_ELLIPSIS=Yes git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
322         check_detached &&
323         test_i18ncmp 2nd_detach actual &&
324
325         GIT_PRINT_SHA1_ELLIPSIS=YES git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
326         check_detached &&
327         test_i18ncmp 3rd_detach actual &&
328
329         true
330 "
331
332 test_done