Code

4d1883b7342670a997b460c398277344021adeb7
[git.git] / t / t3510-cherry-pick-sequence.sh
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
13 '
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
22 }
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
28 }
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
42 '
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
51 '
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
75 '
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
81 '
83 test_expect_success '--quit does not complain when no cherry-pick is in progress' '
84         pristine_detach initial &&
85         git cherry-pick --quit
86 '
88 test_expect_success '--abort requires cherry-pick in progress' '
89         pristine_detach initial &&
90         test_must_fail git cherry-pick --abort
91 '
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
98 '
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
108         EOF
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 &&
113         {
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 &&
201         {
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
214         EOF
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
293         EOF
294         test_must_fail git cherry-pick base..anotherpick &&
295         echo c >foo &&
296         git add foo &&
297         git cherry-pick --continue &&
298         {
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 &&
315         {
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
330         EOF
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_done