1#!/bin/sh
2
3test_description='checkout into detached HEAD state'
4. ./test-lib.sh
5
6check_detached () {
7 test_must_fail git symbolic-ref -q HEAD >/dev/null
8}
9
10check_not_detached () {
11 git symbolic-ref -q HEAD >/dev/null
12}
13
14PREV_HEAD_DESC='Previous HEAD position was'
15check_orphan_warning() {
16 test_i18ngrep "you are leaving $2 behind" "$1" &&
17 test_i18ngrep ! "$PREV_HEAD_DESC" "$1"
18}
19check_no_orphan_warning() {
20 test_i18ngrep ! "you are leaving .* commit.*behind" "$1" &&
21 test_i18ngrep "$PREV_HEAD_DESC" "$1"
22}
23
24reset () {
25 git checkout master &&
26 check_not_detached
27}
28
29test_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
38test_expect_success 'checkout branch does not detach' '
39 reset &&
40 git checkout branch &&
41 check_not_detached
42'
43
44test_expect_success 'checkout tag detaches' '
45 reset &&
46 git checkout tag &&
47 check_detached
48'
49
50test_expect_success 'checkout branch by full name detaches' '
51 reset &&
52 git checkout refs/heads/branch &&
53 check_detached
54'
55
56test_expect_success 'checkout non-ref detaches' '
57 reset &&
58 git checkout branch^ &&
59 check_detached
60'
61
62test_expect_success 'checkout ref^0 detaches' '
63 reset &&
64 git checkout branch^0 &&
65 check_detached
66'
67
68test_expect_success 'checkout --detach detaches' '
69 reset &&
70 git checkout --detach branch &&
71 check_detached
72'
73
74test_expect_success 'checkout --detach without branch name' '
75 reset &&
76 git checkout --detach &&
77 check_detached
78'
79
80test_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
86test_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
93test_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
99test_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
107test_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
119test_expect_success 'checkout warns on orphan commits: output' '
120 check_orphan_warning stderr "2 commits"
121'
122
123test_expect_success 'checkout warns orphaning 1 of 2 commits' '
124 git checkout "$orphan2" &&
125 git checkout HEAD^ 2>stderr
126'
127
128test_expect_success 'checkout warns orphaning 1 of 2 commits: output' '
129 check_orphan_warning stderr "1 commit"
130'
131
132test_expect_success 'checkout does not warn leaving ref tip' '
133 reset &&
134 git checkout --detach two &&
135 git checkout master 2>stderr
136'
137
138test_expect_success 'checkout does not warn leaving ref tip' '
139 check_no_orphan_warning stderr
140'
141
142test_expect_success 'checkout does not warn leaving reachable commit' '
143 reset &&
144 git checkout --detach HEAD^ &&
145 git checkout master 2>stderr
146'
147
148test_expect_success 'checkout does not warn leaving reachable commit' '
149 check_no_orphan_warning stderr
150'
151
152cat >expect <<'EOF'
153Your branch is behind 'master' by 1 commit, and can be fast-forwarded.
154EOF
155test_expect_success 'tracking count is accurate after orphan check' '
156 reset &&
157 git branch child master^ &&
158 git config branch.child.remote . &&
159 git config branch.child.merge refs/heads/master &&
160 git checkout child^ &&
161 git checkout child >stdout &&
162 test_cmp expect stdout
163'
164
165test_done