Merge branch 'jk/http-backend-deadlock' into maint
[git] / t / t7611-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         test_i18ngrep MERGE_HEAD output
51 '
52
53 test_expect_success 'fails without MERGE_HEAD (unstarted merge): .git/MERGE_HEAD sanity' '
54         test ! -f .git/MERGE_HEAD &&
55         test "$pre_merge_head" = "$(git rev-parse HEAD)"
56 '
57
58 test_expect_success 'fails without MERGE_HEAD (completed merge)' '
59         git merge clean_branch &&
60         test ! -f .git/MERGE_HEAD &&
61         # Merge successfully completed
62         post_merge_head="$(git rev-parse HEAD)" &&
63         test_must_fail git merge --abort 2>output &&
64         test_i18ngrep MERGE_HEAD output
65 '
66
67 test_expect_success 'fails without MERGE_HEAD (completed merge): .git/MERGE_HEAD sanity' '
68         test ! -f .git/MERGE_HEAD &&
69         test "$post_merge_head" = "$(git rev-parse HEAD)"
70 '
71
72 test_expect_success 'Forget previous merge' '
73         git reset --hard "$pre_merge_head"
74 '
75
76 test_expect_success 'Abort after --no-commit' '
77         # Redo merge, but stop before creating merge commit
78         git merge --no-commit clean_branch &&
79         test -f .git/MERGE_HEAD &&
80         # Abort non-conflicting merge
81         git merge --abort &&
82         test ! -f .git/MERGE_HEAD &&
83         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
84         test -z "$(git diff)" &&
85         test -z "$(git diff --staged)"
86 '
87
88 test_expect_success 'Abort after conflicts' '
89         # Create conflicting merge
90         test_must_fail git merge conflict_branch &&
91         test -f .git/MERGE_HEAD &&
92         # Abort conflicting merge
93         git merge --abort &&
94         test ! -f .git/MERGE_HEAD &&
95         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
96         test -z "$(git diff)" &&
97         test -z "$(git diff --staged)"
98 '
99
100 test_expect_success 'Clean merge with dirty index fails' '
101         echo xyzzy >> foo &&
102         git add foo &&
103         git diff --staged > expect &&
104         test_must_fail git merge clean_branch &&
105         test ! -f .git/MERGE_HEAD &&
106         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
107         test -z "$(git diff)" &&
108         git diff --staged > actual &&
109         test_cmp expect actual
110 '
111
112 test_expect_success 'Conflicting merge with dirty index fails' '
113         test_must_fail git merge conflict_branch &&
114         test ! -f .git/MERGE_HEAD &&
115         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
116         test -z "$(git diff)" &&
117         git diff --staged > actual &&
118         test_cmp expect actual
119 '
120
121 test_expect_success 'Reset index (but preserve worktree changes)' '
122         git reset "$pre_merge_head" &&
123         git diff > actual &&
124         test_cmp expect actual
125 '
126
127 test_expect_success 'Abort clean merge with non-conflicting dirty worktree' '
128         git merge --no-commit clean_branch &&
129         test -f .git/MERGE_HEAD &&
130         # Abort merge
131         git merge --abort &&
132         test ! -f .git/MERGE_HEAD &&
133         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
134         test -z "$(git diff --staged)" &&
135         git diff > actual &&
136         test_cmp expect actual
137 '
138
139 test_expect_success 'Abort conflicting merge with non-conflicting dirty worktree' '
140         test_must_fail git merge conflict_branch &&
141         test -f .git/MERGE_HEAD &&
142         # Abort merge
143         git merge --abort &&
144         test ! -f .git/MERGE_HEAD &&
145         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
146         test -z "$(git diff --staged)" &&
147         git diff > actual &&
148         test_cmp expect actual
149 '
150
151 test_expect_success 'Reset worktree changes' '
152         git reset --hard "$pre_merge_head"
153 '
154
155 test_expect_success 'Fail clean merge with conflicting dirty worktree' '
156         echo xyzzy >> bar &&
157         git diff > expect &&
158         test_must_fail git merge --no-commit clean_branch &&
159         test ! -f .git/MERGE_HEAD &&
160         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
161         test -z "$(git diff --staged)" &&
162         git diff > actual &&
163         test_cmp expect actual
164 '
165
166 test_expect_success 'Fail conflicting merge with conflicting dirty worktree' '
167         test_must_fail git merge conflict_branch &&
168         test ! -f .git/MERGE_HEAD &&
169         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
170         test -z "$(git diff --staged)" &&
171         git diff > actual &&
172         test_cmp expect actual
173 '
174
175 test_expect_success 'Reset worktree changes' '
176         git reset --hard "$pre_merge_head"
177 '
178
179 test_expect_success 'Fail clean merge with matching dirty worktree' '
180         echo bart > bar &&
181         git diff > expect &&
182         test_must_fail git merge --no-commit clean_branch &&
183         test ! -f .git/MERGE_HEAD &&
184         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
185         test -z "$(git diff --staged)" &&
186         git diff > actual &&
187         test_cmp expect actual
188 '
189
190 test_expect_success 'Abort clean merge with matching dirty index' '
191         git add bar &&
192         git diff --staged > expect &&
193         git merge --no-commit clean_branch &&
194         test -f .git/MERGE_HEAD &&
195         ### When aborting the merge, git will discard all staged changes,
196         ### including those that were staged pre-merge. In other words,
197         ### --abort will LOSE any staged changes (the staged changes that
198         ### are lost must match the merge result, or the merge would not
199         ### have been allowed to start). Change expectations accordingly:
200         rm expect &&
201         touch expect &&
202         # Abort merge
203         git merge --abort &&
204         test ! -f .git/MERGE_HEAD &&
205         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
206         git diff --staged > actual &&
207         test_cmp expect actual &&
208         test -z "$(git diff)"
209 '
210
211 test_expect_success 'Reset worktree changes' '
212         git reset --hard "$pre_merge_head"
213 '
214
215 test_expect_success 'Fail conflicting merge with matching dirty worktree' '
216         echo barf > bar &&
217         git diff > expect &&
218         test_must_fail git merge conflict_branch &&
219         test ! -f .git/MERGE_HEAD &&
220         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
221         test -z "$(git diff --staged)" &&
222         git diff > actual &&
223         test_cmp expect actual
224 '
225
226 test_expect_success 'Abort conflicting merge with matching dirty index' '
227         git add bar &&
228         git diff --staged > expect &&
229         test_must_fail git merge conflict_branch &&
230         test -f .git/MERGE_HEAD &&
231         ### When aborting the merge, git will discard all staged changes,
232         ### including those that were staged pre-merge. In other words,
233         ### --abort will LOSE any staged changes (the staged changes that
234         ### are lost must match the merge result, or the merge would not
235         ### have been allowed to start). Change expectations accordingly:
236         rm expect &&
237         touch expect &&
238         # Abort merge
239         git merge --abort &&
240         test ! -f .git/MERGE_HEAD &&
241         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
242         git diff --staged > actual &&
243         test_cmp expect actual &&
244         test -z "$(git diff)"
245 '
246
247 test_expect_success 'Reset worktree changes' '
248         git reset --hard "$pre_merge_head"
249 '
250
251 test_expect_success 'Abort merge with pre- and post-merge worktree changes' '
252         # Pre-merge worktree changes
253         echo xyzzy > foo &&
254         echo barf > bar &&
255         git add bar &&
256         git diff > expect &&
257         git diff --staged > expect-staged &&
258         # Perform merge
259         test_must_fail git merge conflict_branch &&
260         test -f .git/MERGE_HEAD &&
261         # Post-merge worktree changes
262         echo yzxxz > foo &&
263         echo blech > baz &&
264         ### When aborting the merge, git will discard staged changes (bar)
265         ### and unmerged changes (baz). Other changes that are neither
266         ### staged nor marked as unmerged (foo), will be preserved. For
267         ### these changed, git cannot tell pre-merge changes apart from
268         ### post-merge changes, so the post-merge changes will be
269         ### preserved. Change expectations accordingly:
270         git diff -- foo > expect &&
271         rm expect-staged &&
272         touch expect-staged &&
273         # Abort merge
274         git merge --abort &&
275         test ! -f .git/MERGE_HEAD &&
276         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
277         git diff > actual &&
278         test_cmp expect actual &&
279         git diff --staged > actual-staged &&
280         test_cmp expect-staged actual-staged
281 '
282
283 test_expect_success 'Reset worktree changes' '
284         git reset --hard "$pre_merge_head"
285 '
286
287 test_expect_success 'Abort merge with pre- and post-merge index changes' '
288         # Pre-merge worktree changes
289         echo xyzzy > foo &&
290         echo barf > bar &&
291         git add bar &&
292         git diff > expect &&
293         git diff --staged > expect-staged &&
294         # Perform merge
295         test_must_fail git merge conflict_branch &&
296         test -f .git/MERGE_HEAD &&
297         # Post-merge worktree changes
298         echo yzxxz > foo &&
299         echo blech > baz &&
300         git add foo bar &&
301         ### When aborting the merge, git will discard all staged changes
302         ### (foo, bar and baz), and no changes will be preserved. Whether
303         ### the changes were staged pre- or post-merge does not matter
304         ### (except for not preventing starting the merge).
305         ### Change expectations accordingly:
306         rm expect expect-staged &&
307         touch expect &&
308         touch expect-staged &&
309         # Abort merge
310         git merge --abort &&
311         test ! -f .git/MERGE_HEAD &&
312         test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
313         git diff > actual &&
314         test_cmp expect actual &&
315         git diff --staged > actual-staged &&
316         test_cmp expect-staged actual-staged
317 '
318
319 test_done