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
18 git cherry-pick --quit &&
19 git checkout -f "$1^0" &&
20 git read-tree -u --reset HEAD &&
21 git clean -d -f -f -q -x
25 git rev-parse --verify "$1" >expect.rev &&
26 git rev-parse --verify "$2" >actual.rev &&
27 test_cmp expect.rev actual.rev
30 test_expect_success setup '
31 git config advice.detachedhead false
32 echo unrelated >unrelated &&
34 test_commit initial foo a &&
35 test_commit base foo b &&
36 test_commit unrelatedpick unrelated reallyunrelated &&
37 test_commit picked foo c &&
38 test_commit anotherpick foo d &&
39 test_commit yetanotherpick foo e &&
40 pristine_detach initial &&
41 test_commit conflicting unrelated
44 test_expect_success 'cherry-pick persists data on failure' '
45 pristine_detach initial &&
46 test_must_fail git cherry-pick -s base..anotherpick &&
47 test_path_is_dir .git/sequencer &&
48 test_path_is_file .git/sequencer/head &&
49 test_path_is_file .git/sequencer/todo &&
50 test_path_is_file .git/sequencer/opts
53 test_expect_success 'cherry-pick mid-cherry-pick-sequence' '
54 pristine_detach initial &&
55 test_must_fail git cherry-pick base..anotherpick &&
56 test_cmp_rev picked CHERRY_PICK_HEAD &&
57 # "oops, I forgot that these patches rely on the change from base"
58 git checkout HEAD foo &&
59 git cherry-pick base &&
60 git cherry-pick picked &&
61 git cherry-pick --continue &&
62 git diff --exit-code anotherpick
65 test_expect_success 'cherry-pick persists opts correctly' '
66 pristine_detach initial &&
67 test_must_fail git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours base..anotherpick &&
68 test_path_is_dir .git/sequencer &&
69 test_path_is_file .git/sequencer/head &&
70 test_path_is_file .git/sequencer/todo &&
71 test_path_is_file .git/sequencer/opts &&
72 echo "true" >expect &&
73 git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
74 test_cmp expect actual &&
76 git config --file=.git/sequencer/opts --get-all options.mainline >actual &&
77 test_cmp expect actual &&
78 echo "recursive" >expect &&
79 git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
80 test_cmp expect actual &&
81 cat >expect <<-\EOF &&
85 git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
86 test_cmp expect actual
89 test_expect_success 'cherry-pick cleans up sequencer state upon success' '
90 pristine_detach initial &&
91 git cherry-pick initial..picked &&
92 test_path_is_missing .git/sequencer
95 test_expect_success '--quit does not complain when no cherry-pick is in progress' '
96 pristine_detach initial &&
97 git cherry-pick --quit
100 test_expect_success '--abort requires cherry-pick in progress' '
101 pristine_detach initial &&
102 test_must_fail git cherry-pick --abort
105 test_expect_success '--quit cleans up sequencer state' '
106 pristine_detach initial &&
107 test_must_fail git cherry-pick base..picked &&
108 git cherry-pick --quit &&
109 test_path_is_missing .git/sequencer
112 test_expect_success '--quit keeps HEAD and conflicted index intact' '
113 pristine_detach initial &&
114 cat >expect <<-\EOF &&
116 :100644 100644 OBJID OBJID M unrelated
118 :000000 100644 OBJID OBJID A foo
119 :000000 100644 OBJID OBJID A unrelated
121 test_must_fail git cherry-pick base..picked &&
122 git cherry-pick --quit &&
123 test_path_is_missing .git/sequencer &&
124 test_must_fail git update-index --refresh &&
127 git diff-tree --root --stdin |
128 sed "s/$_x40/OBJID/g"
130 test_cmp expect actual
133 test_expect_success '--abort to cancel multiple cherry-pick' '
134 pristine_detach initial &&
135 test_must_fail git cherry-pick base..anotherpick &&
136 git cherry-pick --abort &&
137 test_path_is_missing .git/sequencer &&
138 test_cmp_rev initial HEAD &&
139 git update-index --refresh &&
140 git diff-index --exit-code HEAD
143 test_expect_success '--abort to cancel single cherry-pick' '
144 pristine_detach initial &&
145 test_must_fail git cherry-pick picked &&
146 git cherry-pick --abort &&
147 test_path_is_missing .git/sequencer &&
148 test_cmp_rev initial HEAD &&
149 git update-index --refresh &&
150 git diff-index --exit-code HEAD
153 test_expect_success 'cherry-pick --abort to cancel multiple revert' '
154 pristine_detach anotherpick &&
155 test_must_fail git revert base..picked &&
156 git cherry-pick --abort &&
157 test_path_is_missing .git/sequencer &&
158 test_cmp_rev anotherpick HEAD &&
159 git update-index --refresh &&
160 git diff-index --exit-code HEAD
163 test_expect_success 'revert --abort works, too' '
164 pristine_detach anotherpick &&
165 test_must_fail git revert base..picked &&
166 git revert --abort &&
167 test_path_is_missing .git/sequencer &&
168 test_cmp_rev anotherpick HEAD
171 test_expect_success '--abort to cancel single revert' '
172 pristine_detach anotherpick &&
173 test_must_fail git revert picked &&
174 git revert --abort &&
175 test_path_is_missing .git/sequencer &&
176 test_cmp_rev anotherpick HEAD &&
177 git update-index --refresh &&
178 git diff-index --exit-code HEAD
181 test_expect_success '--abort keeps unrelated change, easy case' '
182 pristine_detach unrelatedpick &&
183 echo changed >expect &&
184 test_must_fail git cherry-pick picked..yetanotherpick &&
185 echo changed >unrelated &&
186 git cherry-pick --abort &&
187 test_cmp expect unrelated
190 test_expect_success '--abort refuses to clobber unrelated change, harder case' '
191 pristine_detach initial &&
192 echo changed >expect &&
193 test_must_fail git cherry-pick base..anotherpick &&
194 echo changed >unrelated &&
195 test_must_fail git cherry-pick --abort &&
196 test_cmp expect unrelated &&
197 git rev-list HEAD >log &&
198 test_line_count = 2 log &&
199 test_must_fail git update-index --refresh &&
201 git checkout unrelated &&
202 git cherry-pick --abort &&
203 test_cmp_rev initial HEAD
206 test_expect_success 'cherry-pick still writes sequencer state when one commit is left' '
207 pristine_detach initial &&
208 test_must_fail git cherry-pick base..picked &&
209 test_path_is_dir .git/sequencer &&
210 echo "resolved" >foo &&
215 git diff-tree --root --stdin |
216 sed "s/$_x40/OBJID/g"
218 cat >expect <<-\EOF &&
220 :100644 100644 OBJID OBJID M foo
222 :100644 100644 OBJID OBJID M unrelated
224 :000000 100644 OBJID OBJID A foo
225 :000000 100644 OBJID OBJID A unrelated
227 test_cmp expect actual
230 test_expect_success '--abort after last commit in sequence' '
231 pristine_detach initial &&
232 test_must_fail git cherry-pick base..picked &&
233 git cherry-pick --abort &&
234 test_path_is_missing .git/sequencer &&
235 test_cmp_rev initial HEAD &&
236 git update-index --refresh &&
237 git diff-index --exit-code HEAD
240 test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
241 pristine_detach initial &&
242 test_must_fail git cherry-pick base..anotherpick &&
243 test-chmtime -v +0 .git/sequencer >expect &&
244 test_must_fail git cherry-pick unrelatedpick &&
245 test-chmtime -v +0 .git/sequencer >actual &&
246 test_cmp expect actual
249 test_expect_success '--continue complains when no cherry-pick is in progress' '
250 pristine_detach initial &&
251 test_must_fail git cherry-pick --continue
254 test_expect_success '--continue complains when there are unresolved conflicts' '
255 pristine_detach initial &&
256 test_must_fail git cherry-pick base..anotherpick &&
257 test_must_fail git cherry-pick --continue
260 test_expect_success '--continue of single cherry-pick' '
261 pristine_detach initial &&
263 test_must_fail git cherry-pick picked &&
266 git cherry-pick --continue &&
268 test_cmp expect foo &&
269 test_cmp_rev initial HEAD^ &&
270 git diff --exit-code HEAD &&
271 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
274 test_expect_success '--continue of single revert' '
275 pristine_detach initial &&
276 echo resolved >expect &&
277 echo "Revert \"picked\"" >expect.msg &&
278 test_must_fail git revert picked &&
279 echo resolved >foo &&
281 git cherry-pick --continue &&
283 git diff --exit-code HEAD &&
284 test_cmp expect foo &&
285 test_cmp_rev initial HEAD^ &&
286 git diff-tree -s --pretty=tformat:%s HEAD >msg &&
287 test_cmp expect.msg msg &&
288 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
289 test_must_fail git rev-parse --verify REVERT_HEAD
292 test_expect_success '--continue after resolving conflicts' '
293 pristine_detach initial &&
295 cat >expect.log <<-\EOF &&
297 :100644 100644 OBJID OBJID M foo
299 :100644 100644 OBJID OBJID M foo
301 :100644 100644 OBJID OBJID M unrelated
303 :000000 100644 OBJID OBJID A foo
304 :000000 100644 OBJID OBJID A unrelated
306 test_must_fail git cherry-pick base..anotherpick &&
309 git cherry-pick --continue &&
312 git diff-tree --root --stdin |
313 sed "s/$_x40/OBJID/g"
315 test_cmp expect foo &&
316 test_cmp expect.log actual.log
319 test_expect_success '--continue after resolving conflicts and committing' '
320 pristine_detach initial &&
321 test_must_fail git cherry-pick base..anotherpick &&
325 git cherry-pick --continue &&
326 test_path_is_missing .git/sequencer &&
329 git diff-tree --root --stdin |
330 sed "s/$_x40/OBJID/g"
332 cat >expect <<-\EOF &&
334 :100644 100644 OBJID OBJID M foo
336 :100644 100644 OBJID OBJID M foo
338 :100644 100644 OBJID OBJID M unrelated
340 :000000 100644 OBJID OBJID A foo
341 :000000 100644 OBJID OBJID A unrelated
343 test_cmp expect actual
346 test_expect_success '--continue asks for help after resolving patch to nil' '
347 pristine_detach conflicting &&
348 test_must_fail git cherry-pick initial..picked &&
350 test_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&
351 git checkout HEAD -- unrelated &&
352 test_must_fail git cherry-pick --continue 2>msg &&
353 test_i18ngrep "The previous cherry-pick is now empty" msg
356 test_expect_success 'follow advice and skip nil patch' '
357 pristine_detach conflicting &&
358 test_must_fail git cherry-pick initial..picked &&
360 git checkout HEAD -- unrelated &&
361 test_must_fail git cherry-pick --continue &&
363 git cherry-pick --continue &&
365 git rev-list initial..HEAD >commits &&
366 test_line_count = 3 commits
369 test_expect_success '--continue respects opts' '
370 pristine_detach initial &&
371 test_must_fail git cherry-pick -x base..anotherpick &&
375 git cherry-pick --continue &&
376 test_path_is_missing .git/sequencer &&
377 git cat-file commit HEAD >anotherpick_msg &&
378 git cat-file commit HEAD~1 >picked_msg &&
379 git cat-file commit HEAD~2 >unrelatedpick_msg &&
380 git cat-file commit HEAD~3 >initial_msg &&
381 test_must_fail grep "cherry picked from" initial_msg &&
382 grep "cherry picked from" unrelatedpick_msg &&
383 grep "cherry picked from" picked_msg &&
384 grep "cherry picked from" anotherpick_msg
387 test_expect_success '--continue of single-pick respects -x' '
388 pristine_detach initial &&
389 test_must_fail git cherry-pick -x picked &&
392 git cherry-pick --continue &&
393 test_path_is_missing .git/sequencer &&
394 git cat-file commit HEAD >msg &&
395 grep "cherry picked from" msg
398 test_expect_success '--continue respects -x in first commit in multi-pick' '
399 pristine_detach initial &&
400 test_must_fail git cherry-pick -x picked anotherpick &&
403 git cherry-pick --continue &&
404 test_path_is_missing .git/sequencer &&
405 git cat-file commit HEAD^ >msg &&
406 picked=$(git rev-parse --verify picked) &&
407 grep "cherry picked from.*$picked" msg
410 test_expect_success '--signoff is not automatically propagated to resolved conflict' '
411 pristine_detach initial &&
412 test_must_fail git cherry-pick --signoff base..anotherpick &&
416 git cherry-pick --continue &&
417 test_path_is_missing .git/sequencer &&
418 git cat-file commit HEAD >anotherpick_msg &&
419 git cat-file commit HEAD~1 >picked_msg &&
420 git cat-file commit HEAD~2 >unrelatedpick_msg &&
421 git cat-file commit HEAD~3 >initial_msg &&
422 test_must_fail grep "Signed-off-by:" initial_msg &&
423 grep "Signed-off-by:" unrelatedpick_msg &&
424 test_must_fail grep "Signed-off-by:" picked_msg &&
425 grep "Signed-off-by:" anotherpick_msg
428 test_expect_success '--signoff dropped for implicit commit of resolution, multi-pick case' '
429 pristine_detach initial &&
430 test_must_fail git cherry-pick -s picked anotherpick &&
433 git cherry-pick --continue &&
435 git diff --exit-code HEAD &&
436 test_cmp_rev initial HEAD^^ &&
437 git cat-file commit HEAD^ >msg &&
438 ! grep Signed-off-by: msg
441 test_expect_success 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
442 pristine_detach initial &&
443 test_must_fail git cherry-pick -s picked &&
446 git cherry-pick --continue &&
448 git diff --exit-code HEAD &&
449 test_cmp_rev initial HEAD^ &&
450 git cat-file commit HEAD >msg &&
451 ! grep Signed-off-by: msg
454 test_expect_success 'malformed instruction sheet 1' '
455 pristine_detach initial &&
456 test_must_fail git cherry-pick base..anotherpick &&
457 echo "resolved" >foo &&
460 sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
461 cp new_sheet .git/sequencer/todo &&
462 test_must_fail git cherry-pick --continue
465 test_expect_success 'malformed instruction sheet 2' '
466 pristine_detach initial &&
467 test_must_fail git cherry-pick base..anotherpick &&
468 echo "resolved" >foo &&
471 sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
472 cp new_sheet .git/sequencer/todo &&
473 test_must_fail git cherry-pick --continue
476 test_expect_success 'empty commit set' '
477 pristine_detach initial &&
478 test_expect_code 128 git cherry-pick base..base