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