summaryrefslogtreecommitdiffstats
path: root/t/t7611-merge-abort.sh
blob: c0e9425115f8041d615e454018150cd300eb47d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#!/bin/sh

test_description='test aborting in-progress merges

Set up repo with conflicting and non-conflicting branches:

There are three files foo/bar/baz, and the following graph illustrates the
content of these files in each commit:

# foo/bar/baz --- foo/bar/bazz     <-- main
#             \
#              --- foo/barf/bazf   <-- conflict_branch
#               \
#                --- foo/bart/baz  <-- clean_branch

Next, test git merge --abort with the following variables:
- before/after successful merge (should fail when not in merge context)
- with/without conflicts
- clean/dirty index before merge
- clean/dirty worktree before merge
- dirty index before merge matches contents on remote branch
- changed/unchanged worktree after merge
- changed/unchanged index after merge
'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME

. ./test-lib.sh

test_expect_success 'setup' '
	# Create the above repo
	echo foo > foo &&
	echo bar > bar &&
	echo baz > baz &&
	git add foo bar baz &&
	git commit -m initial &&
	echo bazz > baz &&
	git commit -a -m "second" &&
	git checkout -b conflict_branch HEAD^ &&
	echo barf > bar &&
	echo bazf > baz &&
	git commit -a -m "conflict" &&
	git checkout -b clean_branch HEAD^ &&
	echo bart > bar &&
	git commit -a -m "clean" &&
	git checkout main
'

pre_merge_head="$(git rev-parse HEAD)"

test_expect_success 'fails without MERGE_HEAD (unstarted merge)' '
	test_must_fail git merge --abort 2>output &&
	test_i18ngrep MERGE_HEAD output
'

test_expect_success 'fails without MERGE_HEAD (unstarted merge): .git/MERGE_HEAD sanity' '
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)"
'

test_expect_success 'fails without MERGE_HEAD (completed merge)' '
	git merge clean_branch &&
	test ! -f .git/MERGE_HEAD &&
	# Merge successfully completed
	post_merge_head="$(git rev-parse HEAD)" &&
	test_must_fail git merge --abort 2>output &&
	test_i18ngrep MERGE_HEAD output
'

test_expect_success 'fails without MERGE_HEAD (completed merge): .git/MERGE_HEAD sanity' '
	test ! -f .git/MERGE_HEAD &&
	test "$post_merge_head" = "$(git rev-parse HEAD)"
'

test_expect_success 'Forget previous merge' '
	git reset --hard "$pre_merge_head"
'

test_expect_success 'Abort after --no-commit' '
	# Redo merge, but stop before creating merge commit
	git merge --no-commit clean_branch &&
	test -f .git/MERGE_HEAD &&
	# Abort non-conflicting merge
	git merge --abort &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff)" &&
	test -z "$(git diff --staged)"
'

test_expect_success 'Abort after conflicts' '
	# Create conflicting merge
	test_must_fail git merge conflict_branch &&
	test -f .git/MERGE_HEAD &&
	# Abort conflicting merge
	git merge --abort &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff)" &&
	test -z "$(git diff --staged)"
'

test_expect_success 'Clean merge with dirty index fails' '
	echo xyzzy >> foo &&
	git add foo &&
	git diff --staged > expect &&
	test_must_fail git merge clean_branch &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff)" &&
	git diff --staged > actual &&
	test_cmp expect actual
'

test_expect_success 'Conflicting merge with dirty index fails' '
	test_must_fail git merge conflict_branch &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff)" &&
	git diff --staged > actual &&
	test_cmp expect actual
'

test_expect_success 'Reset index (but preserve worktree changes)' '
	git reset "$pre_merge_head" &&
	git diff > actual &&
	test_cmp expect actual
'

test_expect_success 'Abort clean merge with non-conflicting dirty worktree' '
	git merge --no-commit clean_branch &&
	test -f .git/MERGE_HEAD &&
	# Abort merge
	git merge --abort &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff --staged)" &&
	git diff > actual &&
	test_cmp expect actual
'

test_expect_success 'Abort conflicting merge with non-conflicting dirty worktree' '
	test_must_fail git merge conflict_branch &&
	test -f .git/MERGE_HEAD &&
	# Abort merge
	git merge --abort &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff --staged)" &&
	git diff > actual &&
	test_cmp expect actual
'

test_expect_success 'Reset worktree changes' '
	git reset --hard "$pre_merge_head"
'

test_expect_success 'Fail clean merge with conflicting dirty worktree' '
	echo xyzzy >> bar &&
	git diff > expect &&
	test_must_fail git merge --no-commit clean_branch &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff --staged)" &&
	git diff > actual &&
	test_cmp expect actual
'

test_expect_success 'Fail conflicting merge with conflicting dirty worktree' '
	test_must_fail git merge conflict_branch &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff --staged)" &&
	git diff > actual &&
	test_cmp expect actual
'

test_expect_success 'Reset worktree changes' '
	git reset --hard "$pre_merge_head"
'

test_expect_success 'Fail clean merge with matching dirty worktree' '
	echo bart > bar &&
	git diff > expect &&
	test_must_fail git merge --no-commit clean_branch &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff --staged)" &&
	git diff > actual &&
	test_cmp expect actual
'

test_expect_success 'Fail conflicting merge with matching dirty worktree' '
	echo barf > bar &&
	git diff > expect &&
	test_must_fail git merge conflict_branch &&
	test ! -f .git/MERGE_HEAD &&
	test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
	test -z "$(git diff --staged)" &&
	git diff > actual &&
	test_cmp expect actual
'

test_done