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
'cherry-pick --abort to cancel multiple revert' '
151 pristine_detach anotherpick &&
152 test_expect_code 1 git revert base..picked &&
153 git cherry-pick --abort &&
154 test_path_is_missing .git/sequencer &&
155 test_cmp_rev anotherpick HEAD &&
156 git update-index --refresh &&
157 git diff-index --exit-code HEAD
160 test_expect_success
'revert --abort works, too' '
161 pristine_detach anotherpick &&
162 test_expect_code 1 git revert base..picked &&
163 git revert --abort &&
164 test_path_is_missing .git/sequencer &&
165 test_cmp_rev anotherpick HEAD
168 test_expect_success
'--abort to cancel single revert' '
169 pristine_detach anotherpick &&
170 test_expect_code 1 git revert picked &&
171 git revert --abort &&
172 test_path_is_missing .git/sequencer &&
173 test_cmp_rev anotherpick HEAD &&
174 git update-index --refresh &&
175 git diff-index --exit-code HEAD
178 test_expect_success
'--abort keeps unrelated change, easy case' '
179 pristine_detach unrelatedpick &&
180 echo changed >expect &&
181 test_expect_code 1 git cherry-pick picked..yetanotherpick &&
182 echo changed >unrelated &&
183 git cherry-pick --abort &&
184 test_cmp expect unrelated
187 test_expect_success
'--abort refuses to clobber unrelated change, harder case' '
188 pristine_detach initial &&
189 echo changed >expect &&
190 test_expect_code 1 git cherry-pick base..anotherpick &&
191 echo changed >unrelated &&
192 test_must_fail git cherry-pick --abort &&
193 test_cmp expect unrelated &&
194 git rev-list HEAD >log &&
195 test_line_count = 2 log &&
196 test_must_fail git update-index --refresh &&
198 git checkout unrelated &&
199 git cherry-pick --abort &&
200 test_cmp_rev initial HEAD
203 test_expect_success
'cherry-pick still writes sequencer state when one commit is left' '
204 pristine_detach initial &&
205 test_expect_code 1 git cherry-pick base..picked &&
206 test_path_is_dir .git/sequencer &&
207 echo "resolved" >foo &&
212 git diff-tree --root --stdin |
213 sed "s/$_x40/OBJID/g"
215 cat >expect <<-\EOF &&
217 :100644 100644 OBJID OBJID M foo
219 :100644 100644 OBJID OBJID M unrelated
221 :000000 100644 OBJID OBJID A foo
222 :000000 100644 OBJID OBJID A unrelated
224 test_cmp expect actual
227 test_expect_success
'--abort after last commit in sequence' '
228 pristine_detach initial &&
229 test_expect_code 1 git cherry-pick base..picked &&
230 git cherry-pick --abort &&
231 test_path_is_missing .git/sequencer &&
232 test_cmp_rev initial HEAD &&
233 git update-index --refresh &&
234 git diff-index --exit-code HEAD
237 test_expect_success
'cherry-pick does not implicitly stomp an existing operation' '
238 pristine_detach initial &&
239 test_expect_code 1 git cherry-pick base..anotherpick &&
240 test-chmtime -v +0 .git/sequencer >expect &&
241 test_expect_code 128 git cherry-pick unrelatedpick &&
242 test-chmtime -v +0 .git/sequencer >actual &&
243 test_cmp expect actual
246 test_expect_success
'--continue complains when no cherry-pick is in progress' '
247 pristine_detach initial &&
248 test_expect_code 128 git cherry-pick --continue
251 test_expect_success
'--continue complains when there are unresolved conflicts' '
252 pristine_detach initial &&
253 test_expect_code 1 git cherry-pick base..anotherpick &&
254 test_expect_code 128 git cherry-pick --continue
257 test_expect_success
'--continue of single cherry-pick' '
258 pristine_detach initial &&
260 test_must_fail git cherry-pick picked &&
263 git cherry-pick --continue &&
265 test_cmp expect foo &&
266 test_cmp_rev initial HEAD^ &&
267 git diff --exit-code HEAD &&
268 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
271 test_expect_success
'--continue of single revert' '
272 pristine_detach initial &&
273 echo resolved >expect &&
274 echo "Revert \"picked\"" >expect.msg &&
275 test_must_fail git revert picked &&
276 echo resolved >foo &&
278 git cherry-pick --continue &&
280 git diff --exit-code HEAD &&
281 test_cmp expect foo &&
282 test_cmp_rev initial HEAD^ &&
283 git diff-tree -s --pretty=tformat:%s HEAD >msg &&
284 test_cmp expect.msg msg &&
285 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
286 test_must_fail git rev-parse --verify REVERT_HEAD
289 test_expect_success
'--continue after resolving conflicts' '
290 pristine_detach initial &&
292 cat >expect.log <<-\EOF &&
294 :100644 100644 OBJID OBJID M foo
296 :100644 100644 OBJID OBJID M foo
298 :100644 100644 OBJID OBJID M unrelated
300 :000000 100644 OBJID OBJID A foo
301 :000000 100644 OBJID OBJID A unrelated
303 test_must_fail git cherry-pick base..anotherpick &&
306 git cherry-pick --continue &&
309 git diff-tree --root --stdin |
310 sed "s/$_x40/OBJID/g"
312 test_cmp expect foo &&
313 test_cmp expect.log actual.log
316 test_expect_success
'--continue after resolving conflicts and committing' '
317 pristine_detach initial &&
318 test_expect_code 1 git cherry-pick base..anotherpick &&
322 git cherry-pick --continue &&
323 test_path_is_missing .git/sequencer &&
326 git diff-tree --root --stdin |
327 sed "s/$_x40/OBJID/g"
329 cat >expect <<-\EOF &&
331 :100644 100644 OBJID OBJID M foo
333 :100644 100644 OBJID OBJID M foo
335 :100644 100644 OBJID OBJID M unrelated
337 :000000 100644 OBJID OBJID A foo
338 :000000 100644 OBJID OBJID A unrelated
340 test_cmp expect actual
343 test_expect_success
'--continue asks for help after resolving patch to nil' '
344 pristine_detach conflicting &&
345 test_must_fail git cherry-pick initial..picked &&
347 test_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&
348 git checkout HEAD -- unrelated &&
349 test_must_fail git cherry-pick --continue 2>msg &&
350 test_i18ngrep "The previous cherry-pick is now empty" msg
353 test_expect_success
'follow advice and skip nil patch' '
354 pristine_detach conflicting &&
355 test_must_fail git cherry-pick initial..picked &&
357 git checkout HEAD -- unrelated &&
358 test_must_fail git cherry-pick --continue &&
360 git cherry-pick --continue &&
362 git rev-list initial..HEAD >commits &&
363 test_line_count = 3 commits
366 test_expect_success
'--continue respects opts' '
367 pristine_detach initial &&
368 test_expect_code 1 git cherry-pick -x base..anotherpick &&
372 git cherry-pick --continue &&
373 test_path_is_missing .git/sequencer &&
374 git cat-file commit HEAD >anotherpick_msg &&
375 git cat-file commit HEAD~1 >picked_msg &&
376 git cat-file commit HEAD~2 >unrelatedpick_msg &&
377 git cat-file commit HEAD~3 >initial_msg &&
378 test_must_fail grep "cherry picked from" initial_msg &&
379 grep "cherry picked from" unrelatedpick_msg &&
380 grep "cherry picked from" picked_msg &&
381 grep "cherry picked from" anotherpick_msg
384 test_expect_success
'--continue of single-pick respects -x' '
385 pristine_detach initial &&
386 test_must_fail git cherry-pick -x picked &&
389 git cherry-pick --continue &&
390 test_path_is_missing .git/sequencer &&
391 git cat-file commit HEAD >msg &&
392 grep "cherry picked from" msg
395 test_expect_success
'--continue respects -x in first commit in multi-pick' '
396 pristine_detach initial &&
397 test_must_fail git cherry-pick -x picked anotherpick &&
400 git cherry-pick --continue &&
401 test_path_is_missing .git/sequencer &&
402 git cat-file commit HEAD^ >msg &&
403 picked=$(git rev-parse --verify picked) &&
404 grep "cherry picked from.*$picked" msg
407 test_expect_failure
'--signoff is automatically propagated to resolved conflict' '
408 pristine_detach initial &&
409 test_expect_code 1 git cherry-pick --signoff base..anotherpick &&
413 git cherry-pick --continue &&
414 test_path_is_missing .git/sequencer &&
415 git cat-file commit HEAD >anotherpick_msg &&
416 git cat-file commit HEAD~1 >picked_msg &&
417 git cat-file commit HEAD~2 >unrelatedpick_msg &&
418 git cat-file commit HEAD~3 >initial_msg &&
419 test_must_fail grep "Signed-off-by:" initial_msg &&
420 grep "Signed-off-by:" unrelatedpick_msg &&
421 test_must_fail grep "Signed-off-by:" picked_msg &&
422 grep "Signed-off-by:" anotherpick_msg
425 test_expect_failure
'--signoff dropped for implicit commit of resolution, multi-pick case' '
426 pristine_detach initial &&
427 test_must_fail git cherry-pick -s picked anotherpick &&
430 git cherry-pick --continue &&
432 git diff --exit-code HEAD &&
433 test_cmp_rev initial HEAD^^ &&
434 git cat-file commit HEAD^ >msg &&
435 ! grep Signed-off-by: msg
438 test_expect_failure
'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
439 pristine_detach initial &&
440 test_must_fail git cherry-pick -s picked &&
443 git cherry-pick --continue &&
445 git diff --exit-code HEAD &&
446 test_cmp_rev initial HEAD^ &&
447 git cat-file commit HEAD >msg &&
448 ! grep Signed-off-by: msg
451 test_expect_success
'malformed instruction sheet 1' '
452 pristine_detach initial &&
453 test_expect_code 1 git cherry-pick base..anotherpick &&
454 echo "resolved" >foo &&
457 sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
458 cp new_sheet .git/sequencer/todo &&
459 test_expect_code 128 git cherry-pick --continue
462 test_expect_success
'malformed instruction sheet 2' '
463 pristine_detach initial &&
464 test_expect_code 1 git cherry-pick base..anotherpick &&
465 echo "resolved" >foo &&
468 sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
469 cp new_sheet .git/sequencer/todo &&
470 test_expect_code 128 git cherry-pick --continue
473 test_expect_success
'empty commit set' '
474 pristine_detach initial &&
475 test_expect_code 128 git cherry-pick base..base
478 test_expect_success
'malformed instruction sheet 3' '
479 pristine_detach initial &&
480 test_expect_code 1 git cherry-pick base..anotherpick &&
481 echo "resolved" >foo &&
484 sed "s/pick \([0-9a-f]*\)/pick $_r10/" .git/sequencer/todo >new_sheet &&
485 cp new_sheet .git/sequencer/todo &&
486 test_expect_code 128 git cherry-pick --continue
489 test_expect_success
'instruction sheet, fat-fingers version' '
490 pristine_detach initial &&
491 test_expect_code 1 git cherry-pick base..anotherpick &&
495 sed "s/pick \([0-9a-f]*\)/pick \1 /" .git/sequencer/todo >new_sheet &&
496 cp new_sheet .git/sequencer/todo &&
497 git cherry-pick --continue
500 test_expect_success
'commit descriptions in insn sheet are optional' '
501 pristine_detach initial &&
502 test_expect_code 1 git cherry-pick base..anotherpick &&
506 cut -d" " -f1,2 .git/sequencer/todo >new_sheet &&
507 cp new_sheet .git/sequencer/todo &&
508 git cherry-pick --continue &&
509 test_path_is_missing .git/sequencer &&
510 git rev-list HEAD >commits &&
511 test_line_count = 4 commits