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