3 test_description='Test cherry-pick continuation features
5 + yetanotherpick: rewrites foo to e
6 + anotherpick: rewrites foo to d
7 + picked: rewrites foo to c
8 + unrelatedpick: rewrites unrelated to reallyunrelated
9 + base: rewrites foo to b
10 + initial: writes foo as a, unrelated as unrelated
17 git cherry-pick --quit &&
18 git checkout -f "$1^0" &&
19 git read-tree -u --reset HEAD &&
20 git clean -d -f -f -q -x
24 git rev-parse --verify "$1" >expect.rev &&
25 git rev-parse --verify "$2" >actual.rev &&
26 test_cmp expect.rev actual.rev
29 test_expect_success setup '
30 echo unrelated >unrelated &&
32 test_commit initial foo a &&
33 test_commit base foo b &&
34 test_commit unrelatedpick unrelated reallyunrelated &&
35 test_commit picked foo c &&
36 test_commit anotherpick foo d &&
37 test_commit yetanotherpick foo e &&
38 git config advice.detachedhead false
42 test_expect_success 'cherry-pick persists data on failure' '
43 pristine_detach initial &&
44 test_must_fail git cherry-pick -s base..anotherpick &&
45 test_path_is_dir .git/sequencer &&
46 test_path_is_file .git/sequencer/head &&
47 test_path_is_file .git/sequencer/todo &&
48 test_path_is_file .git/sequencer/opts
51 test_expect_success 'cherry-pick persists opts correctly' '
52 pristine_detach initial &&
53 test_must_fail git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours base..anotherpick &&
54 test_path_is_dir .git/sequencer &&
55 test_path_is_file .git/sequencer/head &&
56 test_path_is_file .git/sequencer/todo &&
57 test_path_is_file .git/sequencer/opts &&
58 echo "true" >expect &&
59 git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
60 test_cmp expect actual &&
62 git config --file=.git/sequencer/opts --get-all options.mainline >actual &&
63 test_cmp expect actual &&
64 echo "recursive" >expect &&
65 git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
66 test_cmp expect actual &&
67 cat >expect <<-\EOF &&
71 git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
72 test_cmp expect actual
75 test_expect_success 'cherry-pick cleans up sequencer state upon success' '
76 pristine_detach initial &&
77 git cherry-pick initial..picked &&
78 test_path_is_missing .git/sequencer
81 test_expect_success '--quit does not complain when no cherry-pick is in progress' '
82 pristine_detach initial &&
83 git cherry-pick --quit
86 test_expect_success '--abort requires cherry-pick in progress' '
87 pristine_detach initial &&
88 test_must_fail git cherry-pick --abort
91 test_expect_success '--quit cleans up sequencer state' '
92 pristine_detach initial &&
93 test_must_fail git cherry-pick base..picked &&
94 git cherry-pick --quit &&
95 test_path_is_missing .git/sequencer
98 test_expect_success '--quit keeps HEAD and conflicted index intact' '
99 pristine_detach initial &&
100 cat >expect <<-\EOF &&
102 :100644 100644 OBJID OBJID M unrelated
104 :000000 100644 OBJID OBJID A foo
105 :000000 100644 OBJID OBJID A unrelated
107 test_must_fail git cherry-pick base..picked &&
108 git cherry-pick --quit &&
109 test_path_is_missing .git/sequencer &&
110 test_must_fail git update-index --refresh &&
113 git diff-tree --root --stdin |
114 sed "s/$_x40/OBJID/g"
116 test_cmp expect actual
119 test_expect_success '--abort to cancel multiple cherry-pick' '
120 pristine_detach initial &&
121 test_must_fail git cherry-pick base..anotherpick &&
122 git cherry-pick --abort &&
123 test_path_is_missing .git/sequencer &&
124 test_cmp_rev initial HEAD &&
125 git update-index --refresh &&
126 git diff-index --exit-code HEAD
129 test_expect_success '--abort to cancel single cherry-pick' '
130 pristine_detach initial &&
131 test_must_fail git cherry-pick picked &&
132 git cherry-pick --abort &&
133 test_path_is_missing .git/sequencer &&
134 test_cmp_rev initial HEAD &&
135 git update-index --refresh &&
136 git diff-index --exit-code HEAD
139 test_expect_success 'cherry-pick --abort to cancel multiple revert' '
140 pristine_detach anotherpick &&
141 test_must_fail git revert base..picked &&
142 git cherry-pick --abort &&
143 test_path_is_missing .git/sequencer &&
144 test_cmp_rev anotherpick HEAD &&
145 git update-index --refresh &&
146 git diff-index --exit-code HEAD
149 test_expect_success 'revert --abort works, too' '
150 pristine_detach anotherpick &&
151 test_must_fail git revert base..picked &&
152 git revert --abort &&
153 test_path_is_missing .git/sequencer &&
154 test_cmp_rev anotherpick HEAD
157 test_expect_success '--abort to cancel single revert' '
158 pristine_detach anotherpick &&
159 test_must_fail git revert picked &&
160 git revert --abort &&
161 test_path_is_missing .git/sequencer &&
162 test_cmp_rev anotherpick HEAD &&
163 git update-index --refresh &&
164 git diff-index --exit-code HEAD
167 test_expect_success '--abort keeps unrelated change, easy case' '
168 pristine_detach unrelatedpick &&
169 echo changed >expect &&
170 test_must_fail git cherry-pick picked..yetanotherpick &&
171 echo changed >unrelated &&
172 git cherry-pick --abort &&
173 test_cmp expect unrelated
176 test_expect_success '--abort refuses to clobber unrelated change, harder case' '
177 pristine_detach initial &&
178 echo changed >expect &&
179 test_must_fail git cherry-pick base..anotherpick &&
180 echo changed >unrelated &&
181 test_must_fail git cherry-pick --abort &&
182 test_cmp expect unrelated &&
183 git rev-list HEAD >log &&
184 test_line_count = 2 log &&
185 test_must_fail git update-index --refresh &&
187 git checkout unrelated &&
188 git cherry-pick --abort &&
189 test_cmp_rev initial HEAD
192 test_expect_success 'cherry-pick cleans up sequencer state when one commit is left' '
193 pristine_detach initial &&
194 test_must_fail git cherry-pick base..picked &&
195 test_path_is_missing .git/sequencer &&
196 echo "resolved" >foo &&
201 git diff-tree --root --stdin |
202 sed "s/$_x40/OBJID/g"
204 cat >expect <<-\EOF &&
206 :100644 100644 OBJID OBJID M foo
208 :100644 100644 OBJID OBJID M unrelated
210 :000000 100644 OBJID OBJID A foo
211 :000000 100644 OBJID OBJID A unrelated
213 test_cmp expect actual
216 test_expect_failure '--abort after last commit in sequence' '
217 pristine_detach initial &&
218 test_must_fail git cherry-pick base..picked &&
219 git cherry-pick --abort &&
220 test_path_is_missing .git/sequencer &&
221 test_cmp_rev initial HEAD &&
222 git update-index --refresh &&
223 git diff-index --exit-code HEAD
226 test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
227 pristine_detach initial &&
228 test_must_fail git cherry-pick base..anotherpick &&
229 test-chmtime -v +0 .git/sequencer >expect &&
230 test_must_fail git cherry-pick unrelatedpick &&
231 test-chmtime -v +0 .git/sequencer >actual &&
232 test_cmp expect actual
235 test_expect_success '--continue complains when no cherry-pick is in progress' '
236 pristine_detach initial &&
237 test_must_fail git cherry-pick --continue
240 test_expect_success '--continue complains when there are unresolved conflicts' '
241 pristine_detach initial &&
242 test_must_fail git cherry-pick base..anotherpick &&
243 test_must_fail git cherry-pick --continue
246 test_expect_success '--continue continues after conflicts are resolved' '
247 pristine_detach initial &&
248 test_must_fail git cherry-pick base..anotherpick &&
252 git cherry-pick --continue &&
253 test_path_is_missing .git/sequencer &&
256 git diff-tree --root --stdin |
257 sed "s/$_x40/OBJID/g"
259 cat >expect <<-\EOF &&
261 :100644 100644 OBJID OBJID M foo
263 :100644 100644 OBJID OBJID M foo
265 :100644 100644 OBJID OBJID M unrelated
267 :000000 100644 OBJID OBJID A foo
268 :000000 100644 OBJID OBJID A unrelated
270 test_cmp expect actual
273 test_expect_success '--continue respects opts' '
274 pristine_detach initial &&
275 test_must_fail git cherry-pick -x base..anotherpick &&
279 git cherry-pick --continue &&
280 test_path_is_missing .git/sequencer &&
281 git cat-file commit HEAD >anotherpick_msg &&
282 git cat-file commit HEAD~1 >picked_msg &&
283 git cat-file commit HEAD~2 >unrelatedpick_msg &&
284 git cat-file commit HEAD~3 >initial_msg &&
285 test_must_fail grep "cherry picked from" initial_msg &&
286 grep "cherry picked from" unrelatedpick_msg &&
287 grep "cherry picked from" picked_msg &&
288 grep "cherry picked from" anotherpick_msg
291 test_expect_success '--signoff is not automatically propagated to resolved conflict' '
292 pristine_detach initial &&
293 test_must_fail git cherry-pick --signoff base..anotherpick &&
297 git cherry-pick --continue &&
298 test_path_is_missing .git/sequencer &&
299 git cat-file commit HEAD >anotherpick_msg &&
300 git cat-file commit HEAD~1 >picked_msg &&
301 git cat-file commit HEAD~2 >unrelatedpick_msg &&
302 git cat-file commit HEAD~3 >initial_msg &&
303 test_must_fail grep "Signed-off-by:" initial_msg &&
304 grep "Signed-off-by:" unrelatedpick_msg &&
305 test_must_fail grep "Signed-off-by:" picked_msg &&
306 grep "Signed-off-by:" anotherpick_msg
309 test_expect_success 'malformed instruction sheet 1' '
310 pristine_detach initial &&
311 test_must_fail git cherry-pick base..anotherpick &&
312 echo "resolved" >foo &&
315 sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
316 cp new_sheet .git/sequencer/todo &&
317 test_must_fail git cherry-pick --continue
320 test_expect_success 'malformed instruction sheet 2' '
321 pristine_detach initial &&
322 test_must_fail git cherry-pick base..anotherpick &&
323 echo "resolved" >foo &&
326 sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
327 cp new_sheet .git/sequencer/todo &&
328 test_must_fail git cherry-pick --continue