1#!/bin/sh
2
3test_description='test cherry-pick and revert with conflicts
4
5 -
6 + picked: rewrites foo to c
7 + base: rewrites foo to b
8 + initial: writes foo as a, unrelated as unrelated
9
10'
11
12. ./test-lib.sh
13
14pristine_detach () {
15 git checkout -f "$1^0" &&
16 git read-tree -u --reset HEAD &&
17 git clean -d -f -f -q -x
18}
19
20test_expect_success setup '
21
22 echo unrelated >unrelated &&
23 git add unrelated &&
24 test_commit initial foo a &&
25 test_commit base foo b &&
26 test_commit picked foo c &&
27 test_commit --signoff picked-signed foo d &&
28 git config advice.detachedhead false
29
30'
31
32test_expect_success 'failed cherry-pick does not advance HEAD' '
33 pristine_detach initial &&
34
35 head=$(git rev-parse HEAD) &&
36 test_must_fail git cherry-pick picked &&
37 newhead=$(git rev-parse HEAD) &&
38
39 test "$head" = "$newhead"
40'
41
42test_expect_success 'advice from failed cherry-pick' "
43 pristine_detach initial &&
44
45 picked=\$(git rev-parse --short picked) &&
46 cat <<-EOF >expected &&
47 error: could not apply \$picked... picked
48 hint: after resolving the conflicts, mark the corrected paths
49 hint: with 'git add <paths>' or 'git rm <paths>'
50 hint: and commit the result with 'git commit'
51 EOF
52 test_must_fail git cherry-pick picked 2>actual &&
53
54 test_i18ncmp expected actual
55"
56
57test_expect_success 'advice from failed cherry-pick --no-commit' "
58 pristine_detach initial &&
59
60 picked=\$(git rev-parse --short picked) &&
61 cat <<-EOF >expected &&
62 error: could not apply \$picked... picked
63 hint: after resolving the conflicts, mark the corrected paths
64 hint: with 'git add <paths>' or 'git rm <paths>'
65 EOF
66 test_must_fail git cherry-pick --no-commit picked 2>actual &&
67
68 test_i18ncmp expected actual
69"
70
71test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
72 pristine_detach initial &&
73 test_must_fail git cherry-pick picked &&
74 test_cmp_rev picked CHERRY_PICK_HEAD
75'
76
77test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' '
78 pristine_detach initial &&
79 git cherry-pick base &&
80 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
81'
82
83test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' '
84 pristine_detach initial &&
85 git cherry-pick --no-commit base &&
86 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
87'
88
89test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' '
90 pristine_detach initial &&
91 echo foo > foo &&
92 test_must_fail git cherry-pick base &&
93 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
94'
95
96test_expect_success \
97 'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' '
98 pristine_detach initial &&
99 echo foo > foo &&
100 test_must_fail git cherry-pick --strategy=resolve base &&
101 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
102'
103
104test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '
105 pristine_detach initial &&
106 (
107 GIT_CHERRY_PICK_HELP="and then do something else" &&
108 export GIT_CHERRY_PICK_HELP &&
109 test_must_fail git cherry-pick picked
110 ) &&
111 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
112'
113
114test_expect_success 'git reset clears CHERRY_PICK_HEAD' '
115 pristine_detach initial &&
116
117 test_must_fail git cherry-pick picked &&
118 git reset &&
119
120 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
121'
122
123test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' '
124 pristine_detach initial &&
125
126 test_must_fail git cherry-pick picked &&
127 test_must_fail git commit &&
128
129 test_cmp_rev picked CHERRY_PICK_HEAD
130'
131
132test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' '
133 pristine_detach initial &&
134
135 test_must_fail git cherry-pick picked &&
136 echo resolved >foo &&
137 git add foo &&
138 git update-index --refresh -q &&
139 test_must_fail git diff-index --exit-code HEAD &&
140 (
141 GIT_EDITOR=false &&
142 export GIT_EDITOR &&
143 test_must_fail git commit
144 ) &&
145
146 test_cmp_rev picked CHERRY_PICK_HEAD
147'
148
149test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '
150 pristine_detach initial &&
151
152 test_must_fail git cherry-pick picked &&
153 echo resolved >foo &&
154 git add foo &&
155 git commit &&
156
157 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
158'
159
160test_expect_success 'failed cherry-pick produces dirty index' '
161 pristine_detach initial &&
162
163 test_must_fail git cherry-pick picked &&
164
165 test_must_fail git update-index --refresh -q &&
166 test_must_fail git diff-index --exit-code HEAD
167'
168
169test_expect_success 'failed cherry-pick registers participants in index' '
170 pristine_detach initial &&
171 {
172 git checkout base -- foo &&
173 git ls-files --stage foo &&
174 git checkout initial -- foo &&
175 git ls-files --stage foo &&
176 git checkout picked -- foo &&
177 git ls-files --stage foo
178 } > stages &&
179 sed "
180 1 s/ 0 / 1 /
181 2 s/ 0 / 2 /
182 3 s/ 0 / 3 /
183 " < stages > expected &&
184 git read-tree -u --reset HEAD &&
185
186 test_must_fail git cherry-pick picked &&
187 git ls-files --stage --unmerged > actual &&
188
189 test_cmp expected actual
190'
191
192test_expect_success 'failed cherry-pick describes conflict in work tree' '
193 pristine_detach initial &&
194 cat <<-EOF > expected &&
195 <<<<<<< HEAD
196 a
197 =======
198 c
199 >>>>>>> objid picked
200 EOF
201
202 test_must_fail git cherry-pick picked &&
203
204 sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
205 test_cmp expected actual
206'
207
208test_expect_success 'diff3 -m style' '
209 pristine_detach initial &&
210 git config merge.conflictstyle diff3 &&
211 cat <<-EOF > expected &&
212 <<<<<<< HEAD
213 a
214 ||||||| parent of objid picked
215 b
216 =======
217 c
218 >>>>>>> objid picked
219 EOF
220
221 test_must_fail git cherry-pick picked &&
222
223 sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
224 test_cmp expected actual
225'
226
227test_expect_success 'revert also handles conflicts sanely' '
228 git config --unset merge.conflictstyle &&
229 pristine_detach initial &&
230 cat <<-EOF > expected &&
231 <<<<<<< HEAD
232 a
233 =======
234 b
235 >>>>>>> parent of objid picked
236 EOF
237 {
238 git checkout picked -- foo &&
239 git ls-files --stage foo &&
240 git checkout initial -- foo &&
241 git ls-files --stage foo &&
242 git checkout base -- foo &&
243 git ls-files --stage foo
244 } > stages &&
245 sed "
246 1 s/ 0 / 1 /
247 2 s/ 0 / 2 /
248 3 s/ 0 / 3 /
249 " < stages > expected-stages &&
250 git read-tree -u --reset HEAD &&
251
252 head=$(git rev-parse HEAD) &&
253 test_must_fail git revert picked &&
254 newhead=$(git rev-parse HEAD) &&
255 git ls-files --stage --unmerged > actual-stages &&
256
257 test "$head" = "$newhead" &&
258 test_must_fail git update-index --refresh -q &&
259 test_must_fail git diff-index --exit-code HEAD &&
260 test_cmp expected-stages actual-stages &&
261 sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
262 test_cmp expected actual
263'
264
265test_expect_success 'failed revert sets REVERT_HEAD' '
266 pristine_detach initial &&
267 test_must_fail git revert picked &&
268 test_cmp_rev picked REVERT_HEAD
269'
270
271test_expect_success 'successful revert does not set REVERT_HEAD' '
272 pristine_detach base &&
273 git revert base &&
274 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
275 test_must_fail git rev-parse --verify REVERT_HEAD
276'
277
278test_expect_success 'revert --no-commit sets REVERT_HEAD' '
279 pristine_detach base &&
280 git revert --no-commit base &&
281 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
282 test_cmp_rev base REVERT_HEAD
283'
284
285test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
286 pristine_detach base &&
287 echo foo > foo &&
288 test_must_fail git revert base &&
289 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
290 test_must_fail git rev-parse --verify REVERT_HEAD
291'
292
293test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
294 pristine_detach initial &&
295 (
296 GIT_CHERRY_PICK_HELP="and then do something else" &&
297 GIT_REVERT_HELP="and then do something else, again" &&
298 export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
299 test_must_fail git revert picked
300 ) &&
301 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
302 test_cmp_rev picked REVERT_HEAD
303'
304
305test_expect_success 'git reset clears REVERT_HEAD' '
306 pristine_detach initial &&
307 test_must_fail git revert picked &&
308 git reset &&
309 test_must_fail git rev-parse --verify REVERT_HEAD
310'
311
312test_expect_success 'failed commit does not clear REVERT_HEAD' '
313 pristine_detach initial &&
314 test_must_fail git revert picked &&
315 test_must_fail git commit &&
316 test_cmp_rev picked REVERT_HEAD
317'
318
319test_expect_success 'revert conflict, diff3 -m style' '
320 pristine_detach initial &&
321 git config merge.conflictstyle diff3 &&
322 cat <<-EOF > expected &&
323 <<<<<<< HEAD
324 a
325 ||||||| objid picked
326 c
327 =======
328 b
329 >>>>>>> parent of objid picked
330 EOF
331
332 test_must_fail git revert picked &&
333
334 sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
335 test_cmp expected actual
336'
337
338test_expect_success 'failed cherry-pick does not forget -s' '
339 pristine_detach initial &&
340 test_must_fail git cherry-pick -s picked &&
341 test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
342'
343
344test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
345 pristine_detach initial &&
346 test_must_fail git cherry-pick -s picked-signed &&
347 git commit -a -s &&
348 test $(git show -s |grep -c "Signed-off-by") = 1
349'
350
351test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
352 pristine_detach initial &&
353 test_must_fail git cherry-pick picked &&
354
355 git commit -a -s &&
356
357 # Do S-o-b and Conflicts appear in the right order?
358 cat <<-\EOF >expect &&
359 Signed-off-by: C O Mitter <committer@example.com>
360 # Conflicts:
361 EOF
362 grep -e "^# Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual &&
363 test_cmp expect actual &&
364
365 cat <<-\EOF >expected &&
366 picked
367
368 Signed-off-by: C O Mitter <committer@example.com>
369 EOF
370
371 git show -s --pretty=format:%B >actual &&
372 test_cmp expected actual
373'
374
375test_expect_success 'commit --amend -s places the sign-off at the right place' '
376 pristine_detach initial &&
377 test_must_fail git cherry-pick picked &&
378
379 # emulate old-style conflicts block
380 mv .git/MERGE_MSG .git/MERGE_MSG+ &&
381 sed -e "/^# Conflicts:/,\$s/^# *//" <.git/MERGE_MSG+ >.git/MERGE_MSG &&
382
383 git commit -a &&
384 git commit --amend -s &&
385
386 # Do S-o-b and Conflicts appear in the right order?
387 cat <<-\EOF >expect &&
388 Signed-off-by: C O Mitter <committer@example.com>
389 Conflicts:
390 EOF
391 grep -e "^Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual &&
392 test_cmp expect actual
393'
394
395test_expect_success 'cherry-pick preserves sparse-checkout' '
396 pristine_detach initial &&
397 test_config core.sparseCheckout true &&
398 test_when_finished "
399 echo \"/*\" >.git/info/sparse-checkout
400 git read-tree --reset -u HEAD
401 rm .git/info/sparse-checkout" &&
402 echo /unrelated >.git/info/sparse-checkout &&
403 git read-tree --reset -u HEAD &&
404 test_must_fail git cherry-pick -Xours picked>actual &&
405 test_i18ngrep ! "Changes not staged for commit:" actual
406'
407
408test_done