Merge branch 'cp/git-flush-is-an-env-bool'
[alt-git.git] / t / t2020-checkout-detach.sh
blob8202ef8c74f639fb53a16b943fb5923ecd4e420e
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 test_expect_success 'checkout tag detaches' '
49 reset &&
50 git checkout tag &&
51 check_detached
54 test_expect_success 'checkout branch by full name detaches' '
55 reset &&
56 git checkout refs/heads/branch &&
57 check_detached
60 test_expect_success 'checkout non-ref detaches' '
61 reset &&
62 git checkout branch^ &&
63 check_detached
66 test_expect_success 'checkout ref^0 detaches' '
67 reset &&
68 git checkout branch^0 &&
69 check_detached
72 test_expect_success 'checkout --detach detaches' '
73 reset &&
74 git checkout --detach branch &&
75 check_detached
78 test_expect_success 'checkout --detach without branch name' '
79 reset &&
80 git checkout --detach &&
81 check_detached
84 test_expect_success 'checkout --detach errors out for non-commit' '
85 reset &&
86 test_must_fail git checkout --detach one^{tree} &&
87 check_not_detached
90 test_expect_success 'checkout --detach errors out for extra argument' '
91 reset &&
92 git checkout main &&
93 test_must_fail git checkout --detach tag one.t &&
94 check_not_detached
97 test_expect_success 'checkout --detached and -b are incompatible' '
98 reset &&
99 test_must_fail git checkout --detach -b newbranch tag &&
100 check_not_detached
103 test_expect_success 'checkout --detach moves HEAD' '
104 reset &&
105 git checkout one &&
106 git checkout --detach two &&
107 git diff --exit-code HEAD &&
108 git diff --exit-code two
111 test_expect_success 'checkout warns on orphan commits' '
112 reset &&
113 git checkout --detach two &&
114 echo content >orphan &&
115 git add orphan &&
116 git commit -a -m orphan1 &&
117 echo new content >orphan &&
118 git commit -a -m orphan2 &&
119 orphan2=$(git rev-parse HEAD) &&
120 git checkout main 2>stderr
123 test_expect_success 'checkout warns on orphan commits: output' '
124 check_orphan_warning stderr "2 commits"
127 test_expect_success 'checkout warns orphaning 1 of 2 commits' '
128 git checkout "$orphan2" &&
129 git checkout HEAD^ 2>stderr
132 test_expect_success 'checkout warns orphaning 1 of 2 commits: output' '
133 check_orphan_warning stderr "1 commit"
136 test_expect_success 'checkout does not warn leaving ref tip' '
137 reset &&
138 git checkout --detach two &&
139 git checkout main 2>stderr
142 test_expect_success 'checkout does not warn leaving ref tip' '
143 check_no_orphan_warning stderr
146 test_expect_success 'checkout does not warn leaving reachable commit' '
147 reset &&
148 git checkout --detach HEAD^ &&
149 git checkout main 2>stderr
152 test_expect_success 'checkout does not warn leaving reachable commit' '
153 check_no_orphan_warning stderr
156 cat >expect <<'EOF'
157 Your branch is behind 'main' by 1 commit, and can be fast-forwarded.
158 (use "git pull" to update your local branch)
160 test_expect_success 'tracking count is accurate after orphan check' '
161 reset &&
162 git branch child main^ &&
163 git config branch.child.remote . &&
164 git config branch.child.merge refs/heads/main &&
165 git checkout child^ &&
166 git checkout child >stdout &&
167 test_cmp expect stdout
170 test_expect_success 'no advice given for explicit detached head state' '
171 # baseline
172 test_config advice.detachedHead true &&
173 git checkout child && git checkout HEAD^0 >expect.advice 2>&1 &&
174 test_config advice.detachedHead false &&
175 git checkout child && git checkout HEAD^0 >expect.no-advice 2>&1 &&
176 test_unconfig advice.detachedHead &&
177 # without configuration, the advice.* variables default to true
178 git checkout child && git checkout HEAD^0 >actual 2>&1 &&
179 test_cmp expect.advice actual &&
181 # with explicit --detach
182 # no configuration
183 test_unconfig advice.detachedHead &&
184 git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
185 test_cmp expect.no-advice actual &&
187 # explicitly decline advice
188 test_config advice.detachedHead false &&
189 git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
190 test_cmp expect.no-advice actual
193 # Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (new format)
194 test_expect_success 'describe_detached_head prints no SHA-1 ellipsis when not asked to' "
196 commit=$(git rev-parse --short=12 main^) &&
197 commit2=$(git rev-parse --short=12 main~2) &&
198 commit3=$(git rev-parse --short=12 main~3) &&
200 # The first detach operation is more chatty than the following ones.
201 cat >1st_detach <<-EOF &&
202 Note: switching to 'HEAD^'.
204 You are in 'detached HEAD' state. You can look around, make experimental
205 changes and commit them, and you can discard any commits you make in this
206 state without impacting any branches by switching back to a branch.
208 If you want to create a new branch to retain commits you create, you may
209 do so (now or later) by using -c with the switch command. Example:
211 git switch -c <new-branch-name>
213 Or undo this operation with:
215 git switch -
217 Turn off this advice by setting config variable advice.detachedHead to false
219 HEAD is now at \$commit three
222 # The remaining ones just show info about previous and current HEADs.
223 cat >2nd_detach <<-EOF &&
224 Previous HEAD position was \$commit three
225 HEAD is now at \$commit2 two
228 cat >3rd_detach <<-EOF &&
229 Previous HEAD position was \$commit2 two
230 HEAD is now at \$commit3 one
233 reset &&
234 check_not_detached &&
236 # Various ways of *not* asking for ellipses
238 sane_unset GIT_PRINT_SHA1_ELLIPSIS &&
239 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
240 check_detached &&
241 test_cmp 1st_detach actual &&
243 GIT_PRINT_SHA1_ELLIPSIS="no" git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
244 check_detached &&
245 test_cmp 2nd_detach actual &&
247 GIT_PRINT_SHA1_ELLIPSIS= git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
248 check_detached &&
249 test_cmp 3rd_detach actual &&
251 sane_unset GIT_PRINT_SHA1_ELLIPSIS &&
253 # We only have four commits, but we can re-use them
254 reset &&
255 check_not_detached &&
257 # Make no mention of the env var at all
258 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
259 check_detached &&
260 test_cmp 1st_detach actual &&
262 GIT_PRINT_SHA1_ELLIPSIS='nope' &&
263 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
264 check_detached &&
265 test_cmp 2nd_detach actual &&
267 GIT_PRINT_SHA1_ELLIPSIS=nein &&
268 git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
269 check_detached &&
270 test_cmp 3rd_detach actual &&
272 true
275 # Detached HEAD tests for GIT_PRINT_SHA1_ELLIPSIS (old format)
276 test_expect_success 'describe_detached_head does print SHA-1 ellipsis when asked to' "
278 commit=$(git rev-parse --short=12 main^) &&
279 commit2=$(git rev-parse --short=12 main~2) &&
280 commit3=$(git rev-parse --short=12 main~3) &&
282 # The first detach operation is more chatty than the following ones.
283 cat >1st_detach <<-EOF &&
284 Note: switching to 'HEAD^'.
286 You are in 'detached HEAD' state. You can look around, make experimental
287 changes and commit them, and you can discard any commits you make in this
288 state without impacting any branches by switching back to a branch.
290 If you want to create a new branch to retain commits you create, you may
291 do so (now or later) by using -c with the switch command. Example:
293 git switch -c <new-branch-name>
295 Or undo this operation with:
297 git switch -
299 Turn off this advice by setting config variable advice.detachedHead to false
301 HEAD is now at \$commit... three
304 # The remaining ones just show info about previous and current HEADs.
305 cat >2nd_detach <<-EOF &&
306 Previous HEAD position was \$commit... three
307 HEAD is now at \$commit2... two
310 cat >3rd_detach <<-EOF &&
311 Previous HEAD position was \$commit2... two
312 HEAD is now at \$commit3... one
315 reset &&
316 check_not_detached &&
318 # Various ways of asking for ellipses...
319 # The user can just use any kind of quoting (including none).
321 GIT_PRINT_SHA1_ELLIPSIS=yes git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
322 check_detached &&
323 test_cmp 1st_detach actual &&
325 GIT_PRINT_SHA1_ELLIPSIS=Yes git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
326 check_detached &&
327 test_cmp 2nd_detach actual &&
329 GIT_PRINT_SHA1_ELLIPSIS=YES git -c 'core.abbrev=12' checkout HEAD^ >actual 2>&1 &&
330 check_detached &&
331 test_cmp 3rd_detach actual &&
333 true
336 test_done