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 persists opts correctly' '
54 pristine_detach initial &&
55 test_must_fail git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours base..anotherpick &&
56 test_path_is_dir .git/sequencer &&
57 test_path_is_file .git/sequencer/head &&
58 test_path_is_file .git/sequencer/todo &&
59 test_path_is_file .git/sequencer/opts &&
60 echo "true" >expect &&
61 git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
62 test_cmp expect actual &&
64 git config --file=.git/sequencer/opts --get-all options.mainline >actual &&
65 test_cmp expect actual &&
66 echo "recursive" >expect &&
67 git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
68 test_cmp expect actual &&
69 cat >expect <<-\EOF &&
73 git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
74 test_cmp expect actual
77 test_expect_success
'cherry-pick cleans up sequencer state upon success' '
78 pristine_detach initial &&
79 git cherry-pick initial..picked &&
80 test_path_is_missing .git/sequencer
83 test_expect_success
'--quit does not complain when no cherry-pick is in progress' '
84 pristine_detach initial &&
85 git cherry-pick --quit
88 test_expect_success
'--abort requires cherry-pick in progress' '
89 pristine_detach initial &&
90 test_must_fail git cherry-pick --abort
93 test_expect_success
'--quit cleans up sequencer state' '
94 pristine_detach initial &&
95 test_must_fail git cherry-pick base..picked &&
96 git cherry-pick --quit &&
97 test_path_is_missing .git/sequencer
100 test_expect_success
'--quit keeps HEAD and conflicted index intact' '
101 pristine_detach initial &&
102 cat >expect <<-\EOF &&
104 :100644 100644 OBJID OBJID M unrelated
106 :000000 100644 OBJID OBJID A foo
107 :000000 100644 OBJID OBJID A unrelated
109 test_must_fail git cherry-pick base..picked &&
110 git cherry-pick --quit &&
111 test_path_is_missing .git/sequencer &&
112 test_must_fail git update-index --refresh &&
115 git diff-tree --root --stdin |
116 sed "s/$_x40/OBJID/g"
118 test_cmp expect actual
121 test_expect_success
'--abort to cancel multiple cherry-pick' '
122 pristine_detach initial &&
123 test_must_fail git cherry-pick base..anotherpick &&
124 git cherry-pick --abort &&
125 test_path_is_missing .git/sequencer &&
126 test_cmp_rev initial HEAD &&
127 git update-index --refresh &&
128 git diff-index --exit-code HEAD
131 test_expect_success
'--abort to cancel single cherry-pick' '
132 pristine_detach initial &&
133 test_must_fail git cherry-pick picked &&
134 git cherry-pick --abort &&
135 test_path_is_missing .git/sequencer &&
136 test_cmp_rev initial HEAD &&
137 git update-index --refresh &&
138 git diff-index --exit-code HEAD
141 test_expect_success
'cherry-pick --abort to cancel multiple revert' '
142 pristine_detach anotherpick &&
143 test_must_fail git revert base..picked &&
144 git cherry-pick --abort &&
145 test_path_is_missing .git/sequencer &&
146 test_cmp_rev anotherpick HEAD &&
147 git update-index --refresh &&
148 git diff-index --exit-code HEAD
151 test_expect_success
'revert --abort works, too' '
152 pristine_detach anotherpick &&
153 test_must_fail git revert base..picked &&
154 git revert --abort &&
155 test_path_is_missing .git/sequencer &&
156 test_cmp_rev anotherpick HEAD
159 test_expect_success
'--abort to cancel single revert' '
160 pristine_detach anotherpick &&
161 test_must_fail git revert picked &&
162 git revert --abort &&
163 test_path_is_missing .git/sequencer &&
164 test_cmp_rev anotherpick HEAD &&
165 git update-index --refresh &&
166 git diff-index --exit-code HEAD
169 test_expect_success
'--abort keeps unrelated change, easy case' '
170 pristine_detach unrelatedpick &&
171 echo changed >expect &&
172 test_must_fail git cherry-pick picked..yetanotherpick &&
173 echo changed >unrelated &&
174 git cherry-pick --abort &&
175 test_cmp expect unrelated
178 test_expect_success
'--abort refuses to clobber unrelated change, harder case' '
179 pristine_detach initial &&
180 echo changed >expect &&
181 test_must_fail git cherry-pick base..anotherpick &&
182 echo changed >unrelated &&
183 test_must_fail git cherry-pick --abort &&
184 test_cmp expect unrelated &&
185 git rev-list HEAD >log &&
186 test_line_count = 2 log &&
187 test_must_fail git update-index --refresh &&
189 git checkout unrelated &&
190 git cherry-pick --abort &&
191 test_cmp_rev initial HEAD
194 test_expect_success
'cherry-pick cleans up sequencer state when one commit is left' '
195 pristine_detach initial &&
196 test_must_fail git cherry-pick base..picked &&
197 test_path_is_missing .git/sequencer &&
198 echo "resolved" >foo &&
203 git diff-tree --root --stdin |
204 sed "s/$_x40/OBJID/g"
206 cat >expect <<-\EOF &&
208 :100644 100644 OBJID OBJID M foo
210 :100644 100644 OBJID OBJID M unrelated
212 :000000 100644 OBJID OBJID A foo
213 :000000 100644 OBJID OBJID A unrelated
215 test_cmp expect actual
218 test_expect_failure
'--abort after last commit in sequence' '
219 pristine_detach initial &&
220 test_must_fail git cherry-pick base..picked &&
221 git cherry-pick --abort &&
222 test_path_is_missing .git/sequencer &&
223 test_cmp_rev initial HEAD &&
224 git update-index --refresh &&
225 git diff-index --exit-code HEAD
228 test_expect_success
'cherry-pick does not implicitly stomp an existing operation' '
229 pristine_detach initial &&
230 test_must_fail git cherry-pick base..anotherpick &&
231 test-chmtime -v +0 .git/sequencer >expect &&
232 test_must_fail git cherry-pick unrelatedpick &&
233 test-chmtime -v +0 .git/sequencer >actual &&
234 test_cmp expect actual
237 test_expect_success
'--continue complains when no cherry-pick is in progress' '
238 pristine_detach initial &&
239 test_must_fail git cherry-pick --continue
242 test_expect_success
'--continue complains when there are unresolved conflicts' '
243 pristine_detach initial &&
244 test_must_fail git cherry-pick base..anotherpick &&
245 test_must_fail git cherry-pick --continue
248 test_expect_success
'--continue of single cherry-pick' '
249 pristine_detach initial &&
251 test_must_fail git cherry-pick picked &&
254 git cherry-pick --continue &&
256 test_cmp expect foo &&
257 test_cmp_rev initial HEAD^ &&
258 git diff --exit-code HEAD &&
259 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
262 test_expect_success
'--continue of single revert' '
263 pristine_detach initial &&
264 echo resolved >expect &&
265 echo "Revert \"picked\"" >expect.msg &&
266 test_must_fail git revert picked &&
267 echo resolved >foo &&
269 git cherry-pick --continue &&
271 git diff --exit-code HEAD &&
272 test_cmp expect foo &&
273 test_cmp_rev initial HEAD^ &&
274 git diff-tree -s --pretty=tformat:%s HEAD >msg &&
275 test_cmp expect.msg msg &&
276 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
277 test_must_fail git rev-parse --verify REVERT_HEAD
280 test_expect_success
'--continue after resolving conflicts' '
281 pristine_detach initial &&
283 cat >expect.log <<-\EOF &&
285 :100644 100644 OBJID OBJID M foo
287 :100644 100644 OBJID OBJID M foo
289 :100644 100644 OBJID OBJID M unrelated
291 :000000 100644 OBJID OBJID A foo
292 :000000 100644 OBJID OBJID A unrelated
294 test_must_fail git cherry-pick base..anotherpick &&
297 git cherry-pick --continue &&
300 git diff-tree --root --stdin |
301 sed "s/$_x40/OBJID/g"
303 test_cmp expect foo &&
304 test_cmp expect.log actual.log
307 test_expect_success
'--continue after resolving conflicts and committing' '
308 pristine_detach initial &&
309 test_must_fail git cherry-pick base..anotherpick &&
313 git cherry-pick --continue &&
314 test_path_is_missing .git/sequencer &&
317 git diff-tree --root --stdin |
318 sed "s/$_x40/OBJID/g"
320 cat >expect <<-\EOF &&
322 :100644 100644 OBJID OBJID M foo
324 :100644 100644 OBJID OBJID M foo
326 :100644 100644 OBJID OBJID M unrelated
328 :000000 100644 OBJID OBJID A foo
329 :000000 100644 OBJID OBJID A unrelated
331 test_cmp expect actual
334 test_expect_success
'--continue asks for help after resolving patch to nil' '
335 pristine_detach conflicting &&
336 test_must_fail git cherry-pick initial..picked &&
338 test_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&
339 git checkout HEAD -- unrelated &&
340 test_must_fail git cherry-pick --continue 2>msg &&
341 test_i18ngrep "The previous cherry-pick is now empty" msg
344 test_expect_failure
'follow advice and skip nil patch' '
345 pristine_detach conflicting &&
346 test_must_fail git cherry-pick initial..picked &&
348 git checkout HEAD -- unrelated &&
349 test_must_fail git cherry-pick --continue &&
351 git cherry-pick --continue &&
353 git rev-list initial..HEAD >commits &&
354 test_line_count = 3 commits
357 test_expect_success
'--continue respects opts' '
358 pristine_detach initial &&
359 test_must_fail git cherry-pick -x base..anotherpick &&
363 git cherry-pick --continue &&
364 test_path_is_missing .git/sequencer &&
365 git cat-file commit HEAD >anotherpick_msg &&
366 git cat-file commit HEAD~1 >picked_msg &&
367 git cat-file commit HEAD~2 >unrelatedpick_msg &&
368 git cat-file commit HEAD~3 >initial_msg &&
369 test_must_fail grep "cherry picked from" initial_msg &&
370 grep "cherry picked from" unrelatedpick_msg &&
371 grep "cherry picked from" picked_msg &&
372 grep "cherry picked from" anotherpick_msg
375 test_expect_success
'--continue of single-pick respects -x' '
376 pristine_detach initial &&
377 test_must_fail git cherry-pick -x picked &&
380 git cherry-pick --continue &&
381 test_path_is_missing .git/sequencer &&
382 git cat-file commit HEAD >msg &&
383 grep "cherry picked from" msg
386 test_expect_success
'--continue respects -x in first commit in multi-pick' '
387 pristine_detach initial &&
388 test_must_fail git cherry-pick -x picked anotherpick &&
391 git cherry-pick --continue &&
392 test_path_is_missing .git/sequencer &&
393 git cat-file commit HEAD^ >msg &&
394 picked=$(git rev-parse --verify picked) &&
395 grep "cherry picked from.*$picked" msg
398 test_expect_success
'--signoff is not automatically propagated to resolved conflict' '
399 pristine_detach initial &&
400 test_must_fail git cherry-pick --signoff base..anotherpick &&
404 git cherry-pick --continue &&
405 test_path_is_missing .git/sequencer &&
406 git cat-file commit HEAD >anotherpick_msg &&
407 git cat-file commit HEAD~1 >picked_msg &&
408 git cat-file commit HEAD~2 >unrelatedpick_msg &&
409 git cat-file commit HEAD~3 >initial_msg &&
410 test_must_fail grep "Signed-off-by:" initial_msg &&
411 grep "Signed-off-by:" unrelatedpick_msg &&
412 test_must_fail grep "Signed-off-by:" picked_msg &&
413 grep "Signed-off-by:" anotherpick_msg
416 test_expect_success
'--signoff dropped for implicit commit of resolution, multi-pick case' '
417 pristine_detach initial &&
418 test_must_fail git cherry-pick -s picked anotherpick &&
421 git cherry-pick --continue &&
423 git diff --exit-code HEAD &&
424 test_cmp_rev initial HEAD^^ &&
425 git cat-file commit HEAD^ >msg &&
426 ! grep Signed-off-by: msg
429 test_expect_success
'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
430 pristine_detach initial &&
431 test_must_fail git cherry-pick -s picked &&
434 git cherry-pick --continue &&
436 git diff --exit-code HEAD &&
437 test_cmp_rev initial HEAD^ &&
438 git cat-file commit HEAD >msg &&
439 ! grep Signed-off-by: msg
442 test_expect_success
'malformed instruction sheet 1' '
443 pristine_detach initial &&
444 test_must_fail git cherry-pick base..anotherpick &&
445 echo "resolved" >foo &&
448 sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
449 cp new_sheet .git/sequencer/todo &&
450 test_must_fail git cherry-pick --continue
453 test_expect_success
'malformed instruction sheet 2' '
454 pristine_detach initial &&
455 test_must_fail git cherry-pick base..anotherpick &&
456 echo "resolved" >foo &&
459 sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
460 cp new_sheet .git/sequencer/todo &&
461 test_must_fail git cherry-pick --continue
464 test_expect_success
'empty commit set' '
465 pristine_detach initial &&
466 test_expect_code 128 git cherry-pick base..base