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'
159test_expect_success 'successful final commit clears cherry-pick state' '
160 pristine_detach initial &&
161
162 test_must_fail git cherry-pick base picked-signed &&
163 echo resolved >foo &&
164 test_path_is_file .git/sequencer/todo &&
165 git commit -a &&
166 test_must_fail test_path_exists .git/sequencer
167'
168
169test_expect_success 'reset after final pick clears cherry-pick state' '
170 pristine_detach initial &&
171
172 test_must_fail git cherry-pick base picked-signed &&
173 echo resolved >foo &&
174 test_path_is_file .git/sequencer/todo &&
175 git reset &&
176 test_must_fail test_path_exists .git/sequencer
177'
178
179test_expect_success 'failed cherry-pick produces dirty index' '
180 pristine_detach initial &&
181
182 test_must_fail git cherry-pick picked &&
183
184 test_must_fail git update-index --refresh -q &&
185 test_must_fail git diff-index --exit-code HEAD
186'
187
188test_expect_success 'failed cherry-pick registers participants in index' '
189 pristine_detach initial &&
190 {
191 git checkout base -- foo &&
192 git ls-files --stage foo &&
193 git checkout initial -- foo &&
194 git ls-files --stage foo &&
195 git checkout picked -- foo &&
196 git ls-files --stage foo
197 } > stages &&
198 sed "
199 1 s/ 0 / 1 /
200 2 s/ 0 / 2 /
201 3 s/ 0 / 3 /
202 " < stages > expected &&
203 git read-tree -u --reset HEAD &&
204
205 test_must_fail git cherry-pick picked &&
206 git ls-files --stage --unmerged > actual &&
207
208 test_cmp expected actual
209'
210
211test_expect_success 'failed cherry-pick describes conflict in work tree' '
212 pristine_detach initial &&
213 cat <<-EOF > expected &&
214 <<<<<<< HEAD
215 a
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 'diff3 -m style' '
228 pristine_detach initial &&
229 git config merge.conflictstyle diff3 &&
230 cat <<-EOF > expected &&
231 <<<<<<< HEAD
232 a
233 ||||||| parent of objid picked
234 b
235 =======
236 c
237 >>>>>>> objid picked
238 EOF
239
240 test_must_fail git cherry-pick picked &&
241
242 sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
243 test_cmp expected actual
244'
245
246test_expect_success 'revert also handles conflicts sanely' '
247 git config --unset merge.conflictstyle &&
248 pristine_detach initial &&
249 cat <<-EOF > expected &&
250 <<<<<<< HEAD
251 a
252 =======
253 b
254 >>>>>>> parent of objid picked
255 EOF
256 {
257 git checkout picked -- foo &&
258 git ls-files --stage foo &&
259 git checkout initial -- foo &&
260 git ls-files --stage foo &&
261 git checkout base -- foo &&
262 git ls-files --stage foo
263 } > stages &&
264 sed "
265 1 s/ 0 / 1 /
266 2 s/ 0 / 2 /
267 3 s/ 0 / 3 /
268 " < stages > expected-stages &&
269 git read-tree -u --reset HEAD &&
270
271 head=$(git rev-parse HEAD) &&
272 test_must_fail git revert picked &&
273 newhead=$(git rev-parse HEAD) &&
274 git ls-files --stage --unmerged > actual-stages &&
275
276 test "$head" = "$newhead" &&
277 test_must_fail git update-index --refresh -q &&
278 test_must_fail git diff-index --exit-code HEAD &&
279 test_cmp expected-stages actual-stages &&
280 sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
281 test_cmp expected actual
282'
283
284test_expect_success 'failed revert sets REVERT_HEAD' '
285 pristine_detach initial &&
286 test_must_fail git revert picked &&
287 test_cmp_rev picked REVERT_HEAD
288'
289
290test_expect_success 'successful revert does not set REVERT_HEAD' '
291 pristine_detach base &&
292 git revert base &&
293 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
294 test_must_fail git rev-parse --verify REVERT_HEAD
295'
296
297test_expect_success 'revert --no-commit sets REVERT_HEAD' '
298 pristine_detach base &&
299 git revert --no-commit base &&
300 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
301 test_cmp_rev base REVERT_HEAD
302'
303
304test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
305 pristine_detach base &&
306 echo foo > foo &&
307 test_must_fail git revert base &&
308 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
309 test_must_fail git rev-parse --verify REVERT_HEAD
310'
311
312test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
313 pristine_detach initial &&
314 (
315 GIT_CHERRY_PICK_HELP="and then do something else" &&
316 GIT_REVERT_HELP="and then do something else, again" &&
317 export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
318 test_must_fail git revert picked
319 ) &&
320 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
321 test_cmp_rev picked REVERT_HEAD
322'
323
324test_expect_success 'git reset clears REVERT_HEAD' '
325 pristine_detach initial &&
326 test_must_fail git revert picked &&
327 git reset &&
328 test_must_fail git rev-parse --verify REVERT_HEAD
329'
330
331test_expect_success 'failed commit does not clear REVERT_HEAD' '
332 pristine_detach initial &&
333 test_must_fail git revert picked &&
334 test_must_fail git commit &&
335 test_cmp_rev picked REVERT_HEAD
336'
337
338test_expect_success 'successful final commit clears revert state' '
339 pristine_detach picked-signed &&
340
341 test_must_fail git revert picked-signed base &&
342 echo resolved >foo &&
343 test_path_is_file .git/sequencer/todo &&
344 git commit -a &&
345 test_must_fail test_path_exists .git/sequencer
346'
347
348test_expect_success 'reset after final pick clears revert state' '
349 pristine_detach picked-signed &&
350
351 test_must_fail git revert picked-signed base &&
352 echo resolved >foo &&
353 test_path_is_file .git/sequencer/todo &&
354 git reset &&
355 test_must_fail test_path_exists .git/sequencer
356'
357
358test_expect_success 'revert conflict, diff3 -m style' '
359 pristine_detach initial &&
360 git config merge.conflictstyle diff3 &&
361 cat <<-EOF > expected &&
362 <<<<<<< HEAD
363 a
364 ||||||| objid picked
365 c
366 =======
367 b
368 >>>>>>> parent of objid picked
369 EOF
370
371 test_must_fail git revert picked &&
372
373 sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
374 test_cmp expected actual
375'
376
377test_expect_success 'failed cherry-pick does not forget -s' '
378 pristine_detach initial &&
379 test_must_fail git cherry-pick -s picked &&
380 test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
381'
382
383test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
384 pristine_detach initial &&
385 test_must_fail git cherry-pick -s picked-signed &&
386 git commit -a -s &&
387 test $(git show -s |grep -c "Signed-off-by") = 1
388'
389
390test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
391 pristine_detach initial &&
392 test_must_fail git cherry-pick picked &&
393
394 git commit -a -s &&
395
396 # Do S-o-b and Conflicts appear in the right order?
397 cat <<-\EOF >expect &&
398 Signed-off-by: C O Mitter <committer@example.com>
399 # Conflicts:
400 EOF
401 grep -e "^# Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual &&
402 test_cmp expect actual &&
403
404 cat <<-\EOF >expected &&
405 picked
406
407 Signed-off-by: C O Mitter <committer@example.com>
408 EOF
409
410 git show -s --pretty=format:%B >actual &&
411 test_cmp expected actual
412'
413
414test_expect_success 'commit --amend -s places the sign-off at the right place' '
415 pristine_detach initial &&
416 test_must_fail git cherry-pick picked &&
417
418 # emulate old-style conflicts block
419 mv .git/MERGE_MSG .git/MERGE_MSG+ &&
420 sed -e "/^# Conflicts:/,\$s/^# *//" <.git/MERGE_MSG+ >.git/MERGE_MSG &&
421
422 git commit -a &&
423 git commit --amend -s &&
424
425 # Do S-o-b and Conflicts appear in the right order?
426 cat <<-\EOF >expect &&
427 Signed-off-by: C O Mitter <committer@example.com>
428 Conflicts:
429 EOF
430 grep -e "^Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual &&
431 test_cmp expect actual
432'
433
434test_expect_success 'cherry-pick preserves sparse-checkout' '
435 pristine_detach initial &&
436 test_config core.sparseCheckout true &&
437 test_when_finished "
438 echo \"/*\" >.git/info/sparse-checkout
439 git read-tree --reset -u HEAD
440 rm .git/info/sparse-checkout" &&
441 echo /unrelated >.git/info/sparse-checkout &&
442 git read-tree --reset -u HEAD &&
443 test_must_fail git cherry-pick -Xours picked>actual &&
444 test_i18ngrep ! "Changes not staged for commit:" actual
445'
446
447test_done