revert: pass around rev-list args in already-parsed form
[alt-git.git] / t / t3510-cherry-pick-sequence.sh
blob56c95ec18c5061ef8ac760503dd6fd16f72779c3
1 #!/bin/sh
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
15 . ./test-lib.sh
17 pristine_detach () {
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
24 test_cmp_rev () {
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 &&
33 git add 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 &&
63 echo "1" >expect &&
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 &&
70 patience
71 ours
72 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 &&
103 OBJID
104 :100644 100644 OBJID OBJID M unrelated
105 OBJID
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 &&
114 git rev-list HEAD |
115 git diff-tree --root --stdin |
116 sed "s/$_x40/OBJID/g"
117 } >actual &&
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 &&
199 git add foo &&
200 git commit &&
202 git rev-list HEAD |
203 git diff-tree --root --stdin |
204 sed "s/$_x40/OBJID/g"
205 } >actual &&
206 cat >expect <<-\EOF &&
207 OBJID
208 :100644 100644 OBJID OBJID M foo
209 OBJID
210 :100644 100644 OBJID OBJID M unrelated
211 OBJID
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 &&
250 echo c >expect &&
251 test_must_fail git cherry-pick picked &&
252 echo c >foo &&
253 git add foo &&
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 &&
268 git add 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 &&
282 echo d >expect &&
283 cat >expect.log <<-\EOF &&
284 OBJID
285 :100644 100644 OBJID OBJID M foo
286 OBJID
287 :100644 100644 OBJID OBJID M foo
288 OBJID
289 :100644 100644 OBJID OBJID M unrelated
290 OBJID
291 :000000 100644 OBJID OBJID A foo
292 :000000 100644 OBJID OBJID A unrelated
294 test_must_fail git cherry-pick base..anotherpick &&
295 echo c >foo &&
296 git add foo &&
297 git cherry-pick --continue &&
299 git rev-list HEAD |
300 git diff-tree --root --stdin |
301 sed "s/$_x40/OBJID/g"
302 } >actual.log &&
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 &&
310 echo "c" >foo &&
311 git add foo &&
312 git commit &&
313 git cherry-pick --continue &&
314 test_path_is_missing .git/sequencer &&
316 git rev-list HEAD |
317 git diff-tree --root --stdin |
318 sed "s/$_x40/OBJID/g"
319 } >actual &&
320 cat >expect <<-\EOF &&
321 OBJID
322 :100644 100644 OBJID OBJID M foo
323 OBJID
324 :100644 100644 OBJID OBJID M foo
325 OBJID
326 :100644 100644 OBJID OBJID M unrelated
327 OBJID
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 &&
350 git reset &&
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 &&
360 echo "c" >foo &&
361 git add foo &&
362 git commit &&
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 &&
378 echo c >foo &&
379 git add foo &&
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 &&
389 echo c >foo &&
390 git add foo &&
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 &&
401 echo "c" >foo &&
402 git add foo &&
403 git commit &&
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 &&
419 echo c >foo &&
420 git add foo &&
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 &&
432 echo c >foo &&
433 git add foo &&
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 &&
446 git add foo &&
447 git commit &&
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 &&
457 git add foo &&
458 git commit &&
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
469 test_done