Merge branch 'mz/rebase-i-verify' into next
[git] / t / t7609-merge-abort.sh
1 #!/bin/sh
2
3 test_description='test aborting in-progress merges
4
5 Set up repo with conflicting and non-conflicting branches:
6
7 There are three files foo/bar/baz, and the following graph illustrates the
8 content of these files in each commit:
9
10 # foo/bar/baz --- foo/bar/bazz     <-- master
11 #             \
12 #              --- foo/barf/bazf   <-- conflict_branch
13 #               \
14 #                --- foo/bart/baz  <-- clean_branch
15
16 Next, test git merge --abort with the following variables:
17 - before/after successful merge (should fail when not in merge context)
18 - with/without conflicts
19 - clean/dirty index before merge
20 - clean/dirty worktree before merge
21 - dirty index before merge matches contents on remote branch
22 - changed/unchanged worktree after merge
23 - changed/unchanged index after merge
24 '
25 . ./test-lib.sh
26
27 test_expect_success 'setup' '
28         # Create the above repo
29         echo foo > foo &&
30         echo bar > bar &&
31         echo baz > baz &&
32         git add foo bar baz &&
33         git commit -m initial &&
34         echo bazz > baz &&
35         git commit -a -m "second" &&
36         git checkout -b conflict_branch HEAD^ &&
37         echo barf > bar &&
38         echo bazf > baz &&
39         git commit -a -m "conflict" &&
40         git checkout -b clean_branch HEAD^ &&
41         echo bart > bar &&
42         git commit -a -m "clean" &&
43         git checkout master
44 '
45
46 pre_merge_head="$(git rev-parse HEAD)"
47
48 test_expect_success 'fails without MERGE_HEAD (unstarted merge)' '
49         test_must_fail git merge --abort 2>output &&
50         grep -q MERGE_HEAD output &&
51         test ! -f .git/MERGE_HEAD &&
52         test "$pre_merge_head" = "$(git rev-parse HEAD)"
53 '
54
55 test_expect_success 'fails without MERGE_HEAD (completed merge)' '
56         git merge clean_branch &&
57         test ! -f .git/MERGE_HEAD &&
58         # Merge successfully completed
59         post_merge_head="$(git rev-parse HEAD)" &&
60         test_must_fail git merge --abort 2>output &&
61         grep -q MERGE_HEAD output &&
62         test ! -f .git/MERGE_HEAD &&
63         test "$post_merge_head" = "$(git rev-parse HEAD)"
64 '
65
66 test_expect_success 'Forget previous merge' '
67         git reset --hard "$pre_merge_head"
68 '
69
70 test_expect_success 'Abort after --no-commit' '
71         # Redo merge, but stop before creating merge commit
72         git merge --no-commit clean_branch &&
73         test -f .git/MERGE_HEAD &&
74         # Abort non-conflicting merge
75         git merge --abort &&
76         test ! -f .git/MERGE_HEAD &&
77         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
78         test -z "$(git diff)" &&
79         test -z "$(git diff --staged)"
80 '
81
82 test_expect_success 'Abort after conflicts' '
83         # Create conflicting merge
84         test_must_fail git merge conflict_branch &&
85         test -f .git/MERGE_HEAD &&
86         # Abort conflicting merge
87         git merge --abort &&
88         test ! -f .git/MERGE_HEAD &&
89         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
90         test -z "$(git diff)" &&
91         test -z "$(git diff --staged)"
92 '
93
94 test_expect_success 'Clean merge with dirty index fails' '
95         echo xyzzy >> foo &&
96         git add foo &&
97         git diff --staged > expect &&
98         test_must_fail git merge clean_branch &&
99         test ! -f .git/MERGE_HEAD &&
100         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
101         test -z "$(git diff)" &&
102         git diff --staged > actual &&
103         test_cmp expect actual
104 '
105
106 test_expect_success 'Conflicting merge with dirty index fails' '
107         test_must_fail git merge conflict_branch &&
108         test ! -f .git/MERGE_HEAD &&
109         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
110         test -z "$(git diff)" &&
111         git diff --staged > actual &&
112         test_cmp expect actual
113 '
114
115 test_expect_success 'Reset index (but preserve worktree changes)' '
116         git reset "$pre_merge_head" &&
117         git diff > actual &&
118         test_cmp expect actual
119 '
120
121 test_expect_success 'Abort clean merge with non-conflicting dirty worktree' '
122         git merge --no-commit clean_branch &&
123         test -f .git/MERGE_HEAD &&
124         # Abort merge
125         git merge --abort &&
126         test ! -f .git/MERGE_HEAD &&
127         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
128         test -z "$(git diff --staged)" &&
129         git diff > actual &&
130         test_cmp expect actual
131 '
132
133 test_expect_success 'Abort conflicting merge with non-conflicting dirty worktree' '
134         test_must_fail git merge conflict_branch &&
135         test -f .git/MERGE_HEAD &&
136         # Abort merge
137         git merge --abort &&
138         test ! -f .git/MERGE_HEAD &&
139         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
140         test -z "$(git diff --staged)" &&
141         git diff > actual &&
142         test_cmp expect actual
143 '
144
145 test_expect_success 'Reset worktree changes' '
146         git reset --hard "$pre_merge_head"
147 '
148
149 test_expect_success 'Fail clean merge with conflicting dirty worktree' '
150         echo xyzzy >> bar &&
151         git diff > expect &&
152         test_must_fail git merge --no-commit clean_branch &&
153         test ! -f .git/MERGE_HEAD &&
154         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
155         test -z "$(git diff --staged)" &&
156         git diff > actual &&
157         test_cmp expect actual
158 '
159
160 test_expect_success 'Fail conflicting merge with conflicting dirty worktree' '
161         test_must_fail git merge conflict_branch &&
162         test ! -f .git/MERGE_HEAD &&
163         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
164         test -z "$(git diff --staged)" &&
165         git diff > actual &&
166         test_cmp expect actual
167 '
168
169 test_expect_success 'Reset worktree changes' '
170         git reset --hard "$pre_merge_head"
171 '
172
173 test_expect_success 'Fail clean merge with matching dirty worktree' '
174         echo bart > bar &&
175         git diff > expect &&
176         test_must_fail git merge --no-commit clean_branch &&
177         test ! -f .git/MERGE_HEAD &&
178         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
179         test -z "$(git diff --staged)" &&
180         git diff > actual &&
181         test_cmp expect actual
182 '
183
184 test_expect_success 'Abort clean merge with matching dirty index' '
185         git add bar &&
186         git diff --staged > expect &&
187         git merge --no-commit clean_branch &&
188         test -f .git/MERGE_HEAD &&
189         ### When aborting the merge, git will discard all staged changes,
190         ### including those that were staged pre-merge. In other words,
191         ### --abort will LOSE any staged changes (the staged changes that
192         ### are lost must match the merge result, or the merge would not
193         ### have been allowed to start). Change expectations accordingly:
194         rm expect &&
195         touch expect &&
196         # Abort merge
197         git merge --abort &&
198         test ! -f .git/MERGE_HEAD &&
199         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
200         git diff --staged > actual &&
201         test_cmp expect actual &&
202         test -z "$(git diff)"
203 '
204
205 test_expect_success 'Reset worktree changes' '
206         git reset --hard "$pre_merge_head"
207 '
208
209 test_expect_success 'Fail conflicting merge with matching dirty worktree' '
210         echo barf > bar &&
211         git diff > expect &&
212         test_must_fail git merge conflict_branch &&
213         test ! -f .git/MERGE_HEAD &&
214         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
215         test -z "$(git diff --staged)" &&
216         git diff > actual &&
217         test_cmp expect actual
218 '
219
220 test_expect_success 'Abort conflicting merge with matching dirty index' '
221         git add bar &&
222         git diff --staged > expect &&
223         test_must_fail git merge conflict_branch &&
224         test -f .git/MERGE_HEAD &&
225         ### When aborting the merge, git will discard all staged changes,
226         ### including those that were staged pre-merge. In other words,
227         ### --abort will LOSE any staged changes (the staged changes that
228         ### are lost must match the merge result, or the merge would not
229         ### have been allowed to start). Change expectations accordingly:
230         rm expect &&
231         touch expect &&
232         # Abort merge
233         git merge --abort &&
234         test ! -f .git/MERGE_HEAD &&
235         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
236         git diff --staged > actual &&
237         test_cmp expect actual &&
238         test -z "$(git diff)"
239 '
240
241 test_expect_success 'Reset worktree changes' '
242         git reset --hard "$pre_merge_head"
243 '
244
245 test_expect_success 'Abort merge with pre- and post-merge worktree changes' '
246         # Pre-merge worktree changes
247         echo xyzzy > foo &&
248         echo barf > bar &&
249         git add bar &&
250         git diff > expect &&
251         git diff --staged > expect-staged &&
252         # Perform merge
253         test_must_fail git merge conflict_branch &&
254         test -f .git/MERGE_HEAD &&
255         # Post-merge worktree changes
256         echo yzxxz > foo &&
257         echo blech > baz &&
258         ### When aborting the merge, git will discard staged changes (bar)
259         ### and unmerged changes (baz). Other changes that are neither
260         ### staged nor marked as unmerged (foo), will be preserved. For
261         ### these changed, git cannot tell pre-merge changes apart from
262         ### post-merge changes, so the post-merge changes will be
263         ### preserved. Change expectations accordingly:
264         git diff -- foo > expect &&
265         rm expect-staged &&
266         touch expect-staged &&
267         # Abort merge
268         git merge --abort &&
269         test ! -f .git/MERGE_HEAD &&
270         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
271         git diff > actual &&
272         test_cmp expect actual &&
273         git diff --staged > actual-staged &&
274         test_cmp expect-staged actual-staged
275 '
276
277 test_expect_success 'Reset worktree changes' '
278         git reset --hard "$pre_merge_head"
279 '
280
281 test_expect_success 'Abort merge with pre- and post-merge index changes' '
282         # Pre-merge worktree changes
283         echo xyzzy > foo &&
284         echo barf > bar &&
285         git add bar &&
286         git diff > expect &&
287         git diff --staged > expect-staged &&
288         # Perform merge
289         test_must_fail git merge conflict_branch &&
290         test -f .git/MERGE_HEAD &&
291         # Post-merge worktree changes
292         echo yzxxz > foo &&
293         echo blech > baz &&
294         git add foo bar &&
295         ### When aborting the merge, git will discard all staged changes
296         ### (foo, bar and baz), and no changes will be preserved. Whether
297         ### the changes were staged pre- or post-merge does not matter
298         ### (except for not preventing starting the merge).
299         ### Change expectations accordingly:
300         rm expect expect-staged &&
301         touch expect &&
302         touch expect-staged &&
303         # Abort merge
304         git merge --abort &&
305         test ! -f .git/MERGE_HEAD &&
306         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
307         git diff > actual &&
308         test_cmp expect actual &&
309         git diff --staged > actual-staged &&
310         test_cmp expect-staged actual-staged
311 '
312
313 test_done