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