3 test_description
='Test cherry-pick continuation features
5 + conflicting: rewrites unrelated to conflicting
6 + yetanotherpick: rewrites foo to e
7 + anotherpick: rewrites foo to d
8 + picked: rewrites foo to c
9 + unrelatedpick: rewrites unrelated to reallyunrelated
10 + base: rewrites foo to b
11 + initial: writes foo as a, unrelated as unrelated
17 # Repeat first match 10 times
18 _r10
='\1\1\1\1\1\1\1\1\1\1'
21 git cherry-pick
--quit &&
22 git checkout
-f "$1^0" &&
23 git read-tree
-u --reset HEAD
&&
24 git clean
-d -f -f -q -x
27 test_expect_success setup
'
28 git config advice.detachedhead false &&
29 echo unrelated >unrelated &&
31 test_commit initial foo a &&
32 test_commit base foo b &&
33 test_commit unrelatedpick unrelated reallyunrelated &&
34 test_commit picked foo c &&
35 test_commit anotherpick foo d &&
36 test_commit yetanotherpick foo e &&
37 pristine_detach initial &&
38 test_commit conflicting unrelated
41 test_expect_success
'cherry-pick persists data on failure' '
42 pristine_detach initial &&
43 test_expect_code 1 git cherry-pick -s base..anotherpick &&
44 test_path_is_dir .git/sequencer &&
45 test_path_is_file .git/sequencer/head &&
46 test_path_is_file .git/sequencer/todo &&
47 test_path_is_file .git/sequencer/opts
50 test_expect_success
'cherry-pick mid-cherry-pick-sequence' '
51 pristine_detach initial &&
52 test_must_fail git cherry-pick base..anotherpick &&
53 test_cmp_rev picked CHERRY_PICK_HEAD &&
54 # "oops, I forgot that these patches rely on the change from base"
55 git checkout HEAD foo &&
56 git cherry-pick base &&
57 git cherry-pick picked &&
58 git cherry-pick --continue &&
59 git diff --exit-code anotherpick
62 test_expect_success
'cherry-pick persists opts correctly' '
63 pristine_detach initial &&
64 test_expect_code 128 git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours initial..anotherpick &&
65 test_path_is_dir .git/sequencer &&
66 test_path_is_file .git/sequencer/head &&
67 test_path_is_file .git/sequencer/todo &&
68 test_path_is_file .git/sequencer/opts &&
69 echo "true" >expect &&
70 git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
71 test_cmp expect actual &&
73 git config --file=.git/sequencer/opts --get-all options.mainline >actual &&
74 test_cmp expect actual &&
75 echo "recursive" >expect &&
76 git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
77 test_cmp expect actual &&
78 cat >expect <<-\EOF &&
82 git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
83 test_cmp expect actual
86 test_expect_success
'cherry-pick cleans up sequencer state upon success' '
87 pristine_detach initial &&
88 git cherry-pick initial..picked &&
89 test_path_is_missing .git/sequencer
92 test_expect_success
'--quit does not complain when no cherry-pick is in progress' '
93 pristine_detach initial &&
94 git cherry-pick --quit
97 test_expect_success
'--abort requires cherry-pick in progress' '
98 pristine_detach initial &&
99 test_must_fail git cherry-pick --abort
102 test_expect_success
'--quit cleans up sequencer state' '
103 pristine_detach initial &&
104 test_expect_code 1 git cherry-pick base..picked &&
105 git cherry-pick --quit &&
106 test_path_is_missing .git/sequencer
109 test_expect_success
'--quit keeps HEAD and conflicted index intact' '
110 pristine_detach initial &&
111 cat >expect <<-\EOF &&
113 :100644 100644 OBJID OBJID M unrelated
115 :000000 100644 OBJID OBJID A foo
116 :000000 100644 OBJID OBJID A unrelated
118 test_expect_code 1 git cherry-pick base..picked &&
119 git cherry-pick --quit &&
120 test_path_is_missing .git/sequencer &&
121 test_must_fail git update-index --refresh &&
124 git diff-tree --root --stdin |
125 sed "s/$_x40/OBJID/g"
127 test_cmp expect actual
130 test_expect_success
'--abort to cancel multiple cherry-pick' '
131 pristine_detach initial &&
132 test_expect_code 1 git cherry-pick base..anotherpick &&
133 git cherry-pick --abort &&
134 test_path_is_missing .git/sequencer &&
135 test_cmp_rev initial HEAD &&
136 git update-index --refresh &&
137 git diff-index --exit-code HEAD
140 test_expect_success
'--abort to cancel single cherry-pick' '
141 pristine_detach initial &&
142 test_expect_code 1 git cherry-pick picked &&
143 git cherry-pick --abort &&
144 test_path_is_missing .git/sequencer &&
145 test_cmp_rev initial HEAD &&
146 git update-index --refresh &&
147 git diff-index --exit-code HEAD
150 test_expect_success
'--abort does not unsafely change HEAD' '
151 pristine_detach initial &&
152 test_must_fail git cherry-pick picked anotherpick &&
153 git reset --hard base &&
154 test_must_fail git cherry-pick picked anotherpick &&
155 git cherry-pick --abort 2>actual &&
156 test_i18ngrep "You seem to have moved HEAD" actual &&
157 test_cmp_rev base HEAD
160 test_expect_success
'cherry-pick --abort to cancel multiple revert' '
161 pristine_detach anotherpick &&
162 test_expect_code 1 git revert base..picked &&
163 git cherry-pick --abort &&
164 test_path_is_missing .git/sequencer &&
165 test_cmp_rev anotherpick HEAD &&
166 git update-index --refresh &&
167 git diff-index --exit-code HEAD
170 test_expect_success
'revert --abort works, too' '
171 pristine_detach anotherpick &&
172 test_expect_code 1 git revert base..picked &&
173 git revert --abort &&
174 test_path_is_missing .git/sequencer &&
175 test_cmp_rev anotherpick HEAD
178 test_expect_success
'--abort to cancel single revert' '
179 pristine_detach anotherpick &&
180 test_expect_code 1 git revert picked &&
181 git revert --abort &&
182 test_path_is_missing .git/sequencer &&
183 test_cmp_rev anotherpick HEAD &&
184 git update-index --refresh &&
185 git diff-index --exit-code HEAD
188 test_expect_success
'--abort keeps unrelated change, easy case' '
189 pristine_detach unrelatedpick &&
190 echo changed >expect &&
191 test_expect_code 1 git cherry-pick picked..yetanotherpick &&
192 echo changed >unrelated &&
193 git cherry-pick --abort &&
194 test_cmp expect unrelated
197 test_expect_success
'--abort refuses to clobber unrelated change, harder case' '
198 pristine_detach initial &&
199 echo changed >expect &&
200 test_expect_code 1 git cherry-pick base..anotherpick &&
201 echo changed >unrelated &&
202 test_must_fail git cherry-pick --abort &&
203 test_cmp expect unrelated &&
204 git rev-list HEAD >log &&
205 test_line_count = 2 log &&
206 test_must_fail git update-index --refresh &&
208 git checkout unrelated &&
209 git cherry-pick --abort &&
210 test_cmp_rev initial HEAD
213 test_expect_success
'cherry-pick still writes sequencer state when one commit is left' '
214 pristine_detach initial &&
215 test_expect_code 1 git cherry-pick base..picked &&
216 test_path_is_dir .git/sequencer &&
217 echo "resolved" >foo &&
222 git diff-tree --root --stdin |
223 sed "s/$_x40/OBJID/g"
225 cat >expect <<-\EOF &&
227 :100644 100644 OBJID OBJID M foo
229 :100644 100644 OBJID OBJID M unrelated
231 :000000 100644 OBJID OBJID A foo
232 :000000 100644 OBJID OBJID A unrelated
234 test_cmp expect actual
237 test_expect_success
'--abort after last commit in sequence' '
238 pristine_detach initial &&
239 test_expect_code 1 git cherry-pick base..picked &&
240 git cherry-pick --abort &&
241 test_path_is_missing .git/sequencer &&
242 test_cmp_rev initial HEAD &&
243 git update-index --refresh &&
244 git diff-index --exit-code HEAD
247 test_expect_success
'cherry-pick does not implicitly stomp an existing operation' '
248 pristine_detach initial &&
249 test_expect_code 1 git cherry-pick base..anotherpick &&
250 test-chmtime -v +0 .git/sequencer >expect &&
251 test_expect_code 128 git cherry-pick unrelatedpick &&
252 test-chmtime -v +0 .git/sequencer >actual &&
253 test_cmp expect actual
256 test_expect_success
'--continue complains when no cherry-pick is in progress' '
257 pristine_detach initial &&
258 test_expect_code 128 git cherry-pick --continue
261 test_expect_success
'--continue complains when there are unresolved conflicts' '
262 pristine_detach initial &&
263 test_expect_code 1 git cherry-pick base..anotherpick &&
264 test_expect_code 128 git cherry-pick --continue
267 test_expect_success
'--continue of single cherry-pick' '
268 pristine_detach initial &&
270 test_must_fail git cherry-pick picked &&
273 git cherry-pick --continue &&
275 test_cmp expect foo &&
276 test_cmp_rev initial HEAD^ &&
277 git diff --exit-code HEAD &&
278 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
281 test_expect_success
'--continue of single revert' '
282 pristine_detach initial &&
283 echo resolved >expect &&
284 echo "Revert \"picked\"" >expect.msg &&
285 test_must_fail git revert picked &&
286 echo resolved >foo &&
288 git cherry-pick --continue &&
290 git diff --exit-code HEAD &&
291 test_cmp expect foo &&
292 test_cmp_rev initial HEAD^ &&
293 git diff-tree -s --pretty=tformat:%s HEAD >msg &&
294 test_cmp expect.msg msg &&
295 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
296 test_must_fail git rev-parse --verify REVERT_HEAD
299 test_expect_success
'--continue after resolving conflicts' '
300 pristine_detach initial &&
302 cat >expect.log <<-\EOF &&
304 :100644 100644 OBJID OBJID M foo
306 :100644 100644 OBJID OBJID M foo
308 :100644 100644 OBJID OBJID M unrelated
310 :000000 100644 OBJID OBJID A foo
311 :000000 100644 OBJID OBJID A unrelated
313 test_must_fail git cherry-pick base..anotherpick &&
316 git cherry-pick --continue &&
319 git diff-tree --root --stdin |
320 sed "s/$_x40/OBJID/g"
322 test_cmp expect foo &&
323 test_cmp expect.log actual.log
326 test_expect_success
'--continue after resolving conflicts and committing' '
327 pristine_detach initial &&
328 test_expect_code 1 git cherry-pick base..anotherpick &&
332 git cherry-pick --continue &&
333 test_path_is_missing .git/sequencer &&
336 git diff-tree --root --stdin |
337 sed "s/$_x40/OBJID/g"
339 cat >expect <<-\EOF &&
341 :100644 100644 OBJID OBJID M foo
343 :100644 100644 OBJID OBJID M foo
345 :100644 100644 OBJID OBJID M unrelated
347 :000000 100644 OBJID OBJID A foo
348 :000000 100644 OBJID OBJID A unrelated
350 test_cmp expect actual
353 test_expect_success
'--continue asks for help after resolving patch to nil' '
354 pristine_detach conflicting &&
355 test_must_fail git cherry-pick initial..picked &&
357 test_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&
358 git checkout HEAD -- unrelated &&
359 test_must_fail git cherry-pick --continue 2>msg &&
360 test_i18ngrep "The previous cherry-pick is now empty" msg
363 test_expect_success
'follow advice and skip nil patch' '
364 pristine_detach conflicting &&
365 test_must_fail git cherry-pick initial..picked &&
367 git checkout HEAD -- unrelated &&
368 test_must_fail git cherry-pick --continue &&
370 git cherry-pick --continue &&
372 git rev-list initial..HEAD >commits &&
373 test_line_count = 3 commits
376 test_expect_success
'--continue respects opts' '
377 pristine_detach initial &&
378 test_expect_code 1 git cherry-pick -x base..anotherpick &&
382 git cherry-pick --continue &&
383 test_path_is_missing .git/sequencer &&
384 git cat-file commit HEAD >anotherpick_msg &&
385 git cat-file commit HEAD~1 >picked_msg &&
386 git cat-file commit HEAD~2 >unrelatedpick_msg &&
387 git cat-file commit HEAD~3 >initial_msg &&
388 ! grep "cherry picked from" initial_msg &&
389 grep "cherry picked from" unrelatedpick_msg &&
390 grep "cherry picked from" picked_msg &&
391 grep "cherry picked from" anotherpick_msg
394 test_expect_success
'--continue of single-pick respects -x' '
395 pristine_detach initial &&
396 test_must_fail git cherry-pick -x picked &&
399 git cherry-pick --continue &&
400 test_path_is_missing .git/sequencer &&
401 git cat-file commit HEAD >msg &&
402 grep "cherry picked from" msg
405 test_expect_success
'--continue respects -x in first commit in multi-pick' '
406 pristine_detach initial &&
407 test_must_fail git cherry-pick -x picked anotherpick &&
410 git cherry-pick --continue &&
411 test_path_is_missing .git/sequencer &&
412 git cat-file commit HEAD^ >msg &&
413 picked=$(git rev-parse --verify picked) &&
414 grep "cherry picked from.*$picked" msg
417 test_expect_failure
'--signoff is automatically propagated to resolved conflict' '
418 pristine_detach initial &&
419 test_expect_code 1 git cherry-pick --signoff base..anotherpick &&
423 git cherry-pick --continue &&
424 test_path_is_missing .git/sequencer &&
425 git cat-file commit HEAD >anotherpick_msg &&
426 git cat-file commit HEAD~1 >picked_msg &&
427 git cat-file commit HEAD~2 >unrelatedpick_msg &&
428 git cat-file commit HEAD~3 >initial_msg &&
429 ! grep "Signed-off-by:" initial_msg &&
430 grep "Signed-off-by:" unrelatedpick_msg &&
431 ! grep "Signed-off-by:" picked_msg &&
432 grep "Signed-off-by:" anotherpick_msg
435 test_expect_failure
'--signoff dropped for implicit commit of resolution, multi-pick case' '
436 pristine_detach initial &&
437 test_must_fail git cherry-pick -s picked anotherpick &&
440 git cherry-pick --continue &&
442 git diff --exit-code HEAD &&
443 test_cmp_rev initial HEAD^^ &&
444 git cat-file commit HEAD^ >msg &&
445 ! grep Signed-off-by: msg
448 test_expect_failure
'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
449 pristine_detach initial &&
450 test_must_fail git cherry-pick -s picked &&
453 git cherry-pick --continue &&
455 git diff --exit-code HEAD &&
456 test_cmp_rev initial HEAD^ &&
457 git cat-file commit HEAD >msg &&
458 ! grep Signed-off-by: msg
461 test_expect_success
'malformed instruction sheet 1' '
462 pristine_detach initial &&
463 test_expect_code 1 git cherry-pick base..anotherpick &&
464 echo "resolved" >foo &&
467 sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
468 cp new_sheet .git/sequencer/todo &&
469 test_expect_code 128 git cherry-pick --continue
472 test_expect_success
'malformed instruction sheet 2' '
473 pristine_detach initial &&
474 test_expect_code 1 git cherry-pick base..anotherpick &&
475 echo "resolved" >foo &&
478 sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
479 cp new_sheet .git/sequencer/todo &&
480 test_expect_code 128 git cherry-pick --continue
483 test_expect_success
'empty commit set' '
484 pristine_detach initial &&
485 test_expect_code 128 git cherry-pick base..base
488 test_expect_success
'malformed instruction sheet 3' '
489 pristine_detach initial &&
490 test_expect_code 1 git cherry-pick base..anotherpick &&
491 echo "resolved" >foo &&
494 sed "s/pick \([0-9a-f]*\)/pick $_r10/" .git/sequencer/todo >new_sheet &&
495 cp new_sheet .git/sequencer/todo &&
496 test_expect_code 128 git cherry-pick --continue
499 test_expect_success
'instruction sheet, fat-fingers version' '
500 pristine_detach initial &&
501 test_expect_code 1 git cherry-pick base..anotherpick &&
505 sed "s/pick \([0-9a-f]*\)/pick \1 /" .git/sequencer/todo >new_sheet &&
506 cp new_sheet .git/sequencer/todo &&
507 git cherry-pick --continue
510 test_expect_success
'commit descriptions in insn sheet are optional' '
511 pristine_detach initial &&
512 test_expect_code 1 git cherry-pick base..anotherpick &&
516 cut -d" " -f1,2 .git/sequencer/todo >new_sheet &&
517 cp new_sheet .git/sequencer/todo &&
518 git cherry-pick --continue &&
519 test_path_is_missing .git/sequencer &&
520 git rev-list HEAD >commits &&
521 test_line_count = 4 commits