Sync with 'master'
[alt-git.git] / t / t2020-checkout-detach.sh
blob8d90d0285045294b3f39233957ea4487bc7929e0
1 #!/bin/sh
3 test_description='checkout into detached HEAD state'
4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7 TEST_PASSES_SANITIZE_LEAK=true
8 . ./test-lib.sh
10 check_detached () {
11 test_must_fail git symbolic-ref -q HEAD >/dev/null
14 check_not_detached () {
15 git symbolic-ref -q HEAD >/dev/null
18 PREV_HEAD_DESC='Previous HEAD position was'
19 check_orphan_warning() {
20 test_grep "you are leaving $2 behind" "$1" &&
21 test_grep ! "$PREV_HEAD_DESC" "$1"
23 check_no_orphan_warning() {
24 test_grep ! "you are leaving .* commit.*behind" "$1" &&
25 test_grep "$PREV_HEAD_DESC" "$1"
28 reset () {
29 git checkout main &&
30 check_not_detached
33 test_expect_success 'setup' '
34 test_commit one &&
35 test_commit two &&
36 test_commit three && git tag -d three &&
37 test_commit four && git tag -d four &&
38 git branch branch &&
39 git tag tag
42 test_expect_success 'checkout branch does not detach' '
43 reset &&
44 git checkout branch &&
45 check_not_detached
48 for opt in "HEAD" "@"
50 test_expect_success "checkout $opt no-op/don't detach" '
51 reset &&
52 cat .git/HEAD >expect &&
53 git checkout $opt &&
54 cat .git/HEAD >actual &&
55 check_not_detached &&
56 test_cmp expect actual
58 done
60 test_expect_success 'checkout tag detaches' '
61 reset &&
62 git checkout tag &&
63 check_detached
66 test_expect_success 'checkout branch by full name detaches' '
67 reset &&
68 git checkout refs/heads/branch &&
69 check_detached
72 test_expect_success 'checkout non-ref detaches' '
73 reset &&
74 git checkout branch^ &&
75 check_detached
78 test_expect_success 'checkout ref^0 detaches' '
79 reset &&
80 git checkout branch^0 &&
81 check_detached
84 test_expect_success 'checkout --detach detaches' '
85 reset &&
86 git checkout --detach branch &&
87 check_detached
90 test_expect_success 'checkout --detach without branch name' '
91 reset &&
92 git checkout --detach &&
93 check_detached
96 test_expect_success 'checkout --detach errors out for non-commit' '
97 reset &&
98 test_must_fail git checkout --detach one^{tree} &&
99 check_not_detached
102 test_expect_success 'checkout --detach errors out for extra argument' '
103 reset &&
104 git checkout main &&
105 test_must_fail git checkout --detach tag one.t &&
106 check_not_detached
109 test_expect_success 'checkout --detached and -b are incompatible' '
110 reset &&
111 test_must_fail git checkout --detach -b newbranch tag &&
112 check_not_detached
115 test_expect_success 'checkout --detach moves HEAD' '
116 reset &&
117 git checkout one &&
118 git checkout --detach two &&
119 git diff --exit-code HEAD &&
120 git diff --exit-code two
123 test_expect_success 'checkout warns on orphan commits' '
124 reset &&
125 git checkout --detach two &&
126 echo content >orphan &&
127 git add orphan &&
128 git commit -a -m orphan1 &&
129 echo new content >orphan &&
130 git commit -a -m orphan2 &&
131 orphan2=$(git rev-parse HEAD) &&
132 git checkout main 2>stderr
135 test_expect_success 'checkout warns on orphan commits: output' '
136 check_orphan_warning stderr "2 commits"
139 test_expect_success 'checkout warns orphaning 1 of 2 commits' '
140 git checkout "$orphan2" &&
141 git checkout HEAD^ 2>stderr
144 test_expect_success 'checkout warns orphaning 1 of 2 commits: output' '
145 check_orphan_warning stderr "1 commit"
148 test_expect_success 'checkout does not warn leaving ref tip' '
149 reset &&
150 git checkout --detach two &&
151 git checkout main 2>stderr
154 test_expect_success 'checkout does not warn leaving ref tip' '
155 check_no_orphan_warning stderr
158 test_expect_success 'checkout does not warn leaving reachable commit' '
159 reset &&
160 git checkout --detach HEAD^ &&
161 git checkout main 2>stderr
164 test_expect_success 'checkout does not warn leaving reachable commit' '
165 check_no_orphan_warning stderr
168 cat >expect <<'EOF'
169 Your branch is behind 'main' by 1 commit, and can be fast-forwarded.
170 (use "git pull" to update your local branch)
172 test_expect_success 'tracking count is accurate after orphan check' '
173 reset &&
174 git branch child main^ &&
175 git config branch.child.remote . &&
176 git config branch.child.merge refs/heads/main &&
177 git checkout child^ &&
178 git checkout child >stdout &&
179 test_cmp expect stdout &&
181 git checkout --detach child >stdout &&
182 test_grep ! "can be fast-forwarded\." stdout
185 test_expect_success 'no advice given for explicit detached head state' '
186 # baseline
187 test_config advice.detachedHead true &&
188 git checkout child && git checkout HEAD^0 >expect.advice 2>&1 &&
189 test_config advice.detachedHead false &&
190 git checkout child && git checkout HEAD^0 >expect.no-advice 2>&1 &&
191 test_unconfig advice.detachedHead &&
192 # without configuration, the advice.* variables default to true
193 git checkout child && git checkout HEAD^0 >actual 2>&1 &&
194 test_cmp expect.advice actual &&
196 # with explicit --detach
197 # no configuration
198 test_unconfig advice.detachedHead &&
199 git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
200 test_cmp expect.no-advice actual &&
202 # explicitly decline advice
203 test_config advice.detachedHead false &&
204 git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
205 test_cmp expect.no-advice actual
208 # Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (new format)
209 test_expect_success 'describe_detached_head prints no SHA-1 ellipsis when not asked to' "
211 commit=$(git rev-parse --short=12 main^) &&
212 commit2=$(git rev-parse --short=12 main~2) &&
213 commit3=$(git rev-parse --short=12 main~3) &&
215 # The first detach operation is more chatty than the following ones.
216 cat >1st_detach <<-EOF &&
217 Note: switching to 'HEAD^'.
219 You are in 'detached HEAD' state. You can look around, make experimental
220 changes and commit them, and you can discard any commits you make in this
221 state without impacting any branches by switching back to a branch.
223 If you want to create a new branch to retain commits you create, you may
224 do so (now or later) by using -c with the switch command. Example:
226 git switch -c <new-branch-name>
228 Or undo this operation with:
230 git switch -
232 Turn off this advice by setting config variable advice.detachedHead to false
234 HEAD is now at \$commit three
237 # The remaining ones just show info about previous and current HEADs.
238 cat >2nd_detach <<-EOF &&
239 Previous HEAD position was \$commit three
240 HEAD is now at \$commit2 two
243 cat >3rd_detach <<-EOF &&
244 Previous HEAD position was \$commit2 two
245 HEAD is now at \$commit3 one
248 reset &&
249 check_not_detached &&
251 # Various ways of *not* asking for ellipses
253 sane_unset GIT_PRINT_SHA1_ELLIPSIS &&
254 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
255 check_detached &&
256 test_cmp 1st_detach actual &&
258 GIT_PRINT_SHA1_ELLIPSIS="no" git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
259 check_detached &&
260 test_cmp 2nd_detach actual &&
262 GIT_PRINT_SHA1_ELLIPSIS= git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
263 check_detached &&
264 test_cmp 3rd_detach actual &&
266 sane_unset GIT_PRINT_SHA1_ELLIPSIS &&
268 # We only have four commits, but we can re-use them
269 reset &&
270 check_not_detached &&
272 # Make no mention of the env var at all
273 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
274 check_detached &&
275 test_cmp 1st_detach actual &&
277 GIT_PRINT_SHA1_ELLIPSIS='nope' &&
278 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
279 check_detached &&
280 test_cmp 2nd_detach actual &&
282 GIT_PRINT_SHA1_ELLIPSIS=nein &&
283 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
284 check_detached &&
285 test_cmp 3rd_detach actual &&
287 true
290 # Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (old format)
291 test_expect_success 'describe_detached_head does print SHA-1 ellipsis when asked to' "
293 commit=$(git rev-parse --short=12 main^) &&
294 commit2=$(git rev-parse --short=12 main~2) &&
295 commit3=$(git rev-parse --short=12 main~3) &&
297 # The first detach operation is more chatty than the following ones.
298 cat >1st_detach <<-EOF &&
299 Note: switching to 'HEAD^'.
301 You are in 'detached HEAD' state. You can look around, make experimental
302 changes and commit them, and you can discard any commits you make in this
303 state without impacting any branches by switching back to a branch.
305 If you want to create a new branch to retain commits you create, you may
306 do so (now or later) by using -c with the switch command. Example:
308 git switch -c <new-branch-name>
310 Or undo this operation with:
312 git switch -
314 Turn off this advice by setting config variable advice.detachedHead to false
316 HEAD is now at \$commit... three
319 # The remaining ones just show info about previous and current HEADs.
320 cat >2nd_detach <<-EOF &&
321 Previous HEAD position was \$commit... three
322 HEAD is now at \$commit2... two
325 cat >3rd_detach <<-EOF &&
326 Previous HEAD position was \$commit2... two
327 HEAD is now at \$commit3... one
330 reset &&
331 check_not_detached &&
333 # Various ways of asking for ellipses...
334 # The user can just use any kind of quoting (including none).
336 GIT_PRINT_SHA1_ELLIPSIS=yes git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
337 check_detached &&
338 test_cmp 1st_detach actual &&
340 GIT_PRINT_SHA1_ELLIPSIS=Yes git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
341 check_detached &&
342 test_cmp 2nd_detach actual &&
344 GIT_PRINT_SHA1_ELLIPSIS=YES git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
345 check_detached &&
346 test_cmp 3rd_detach actual &&
348 true
351 test_done