t7601: test interaction of merge/rebase/fast-forward flags and options

The interaction of rebase and merge flags and options was not well tested. Add several tests to check for correct behavior from the following rules: * --ff-only vs. --[no-]rebase (and the related pull.ff=only vs. pull.rebase) * --rebase[=!false] vs. --no-ff and --ff (and the related pull.rebase=!false overrides pull.ff=!only) * command line flags take precedence over config, except: * --no-rebase heeds pull.ff=!only * pull.rebase=!false vs --no-ff and --ff For more details behind these rules and a larger table of individual cases, refer to https://lore.kernel.org/git/xmqqwnpqot4m.fsf@gitster.g/ and the links found therein. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Jul 21, 2021 at 01:42 UTC be19c5ca3e28cb16d55623de2e5aa1d45bd5b5ba
1 file changed +182
t/t7601-merge-pull-config.sh
+182
@@ -143,6 +143,188 @@ test_expect_success 'pull.rebase not set and --ff-only given (not-fast-forward)'
143 test_i18ngrep ! "Pulling without specifying how to reconcile" err
144 '
145
146 +test_does_rebase () {
147 + git reset --hard c2 &&
148 + git "$@" . c1 &&
149 + # Check that we actually did a rebase
150 + git rev-list --count HEAD >actual &&
151 + git rev-list --merges --count HEAD >>actual &&
152 + test_write_lines 3 0 >expect &&
153 + test_cmp expect actual &&
154 + rm actual expect
155 +}
156 +
157 +# Prefers merge over fast-forward
158 +test_does_merge_when_ff_possible () {
159 + git reset --hard c0 &&
160 + git "$@" . c1 &&
161 + # Check that we actually did a merge
162 + git rev-list --count HEAD >actual &&
163 + git rev-list --merges --count HEAD >>actual &&
164 + test_write_lines 3 1 >expect &&
165 + test_cmp expect actual &&
166 + rm actual expect
167 +}
168 +
169 +# Prefers fast-forward over merge or rebase
170 +test_does_fast_forward () {
171 + git reset --hard c0 &&
172 + git "$@" . c1 &&
173 +
174 + # Check that we did not get any merges
175 + git rev-list --count HEAD >actual &&
176 + git rev-list --merges --count HEAD >>actual &&
177 + test_write_lines 2 0 >expect &&
178 + test_cmp expect actual &&
179 +
180 + # Check that we ended up at c1
181 + git rev-parse HEAD >actual &&
182 + git rev-parse c1^{commit} >expect &&
183 + test_cmp actual expect &&
184 +
185 + # Remove temporary files
186 + rm actual expect
187 +}
188 +
189 +# Doesn't fail when fast-forward not possible; does a merge
190 +test_falls_back_to_full_merge () {
191 + git reset --hard c2 &&
192 + git "$@" . c1 &&
193 + # Check that we actually did a merge
194 + git rev-list --count HEAD >actual &&
195 + git rev-list --merges --count HEAD >>actual &&
196 + test_write_lines 4 1 >expect &&
197 + test_cmp expect actual &&
198 + rm actual expect
199 +}
200 +
201 +# Attempts fast forward, which is impossible, and bails
202 +test_attempts_fast_forward () {
203 + git reset --hard c2 &&
204 + test_must_fail git "$@" . c1 2>err &&
205 + test_i18ngrep "Not possible to fast-forward, aborting" err
206 +}
207 +
208 +#
209 +# Group 1: Interaction of --ff-only with --[no-]rebase
210 +# (And related interaction of pull.ff=only with pull.rebase)
211 +#
212 +test_expect_failure '--ff-only overrides --rebase' '
213 + test_attempts_fast_forward pull --rebase --ff-only
214 +'
215 +
216 +test_expect_failure '--ff-only overrides --rebase even if first' '
217 + test_attempts_fast_forward pull --ff-only --rebase
218 +'
219 +
220 +test_expect_success '--ff-only overrides --no-rebase' '
221 + test_attempts_fast_forward pull --ff-only --no-rebase
222 +'
223 +
224 +test_expect_failure 'pull.ff=only overrides pull.rebase=true' '
225 + test_attempts_fast_forward -c pull.ff=only -c pull.rebase=true pull
226 +'
227 +
228 +test_expect_success 'pull.ff=only overrides pull.rebase=false' '
229 + test_attempts_fast_forward -c pull.ff=only -c pull.rebase=false pull
230 +'
231 +
232 +# Group 2: --rebase=[!false] overrides --no-ff and --ff
233 +# (And related interaction of pull.rebase=!false and pull.ff=!only)
234 +test_expect_success '--rebase overrides --no-ff' '
235 + test_does_rebase pull --rebase --no-ff
236 +'
237 +
238 +test_expect_success '--rebase overrides --ff' '
239 + test_does_rebase pull --rebase --ff
240 +'
241 +
242 +test_expect_success '--rebase fast-forwards when possible' '
243 + test_does_fast_forward pull --rebase --ff
244 +'
245 +
246 +test_expect_success 'pull.rebase=true overrides pull.ff=false' '
247 + test_does_rebase -c pull.rebase=true -c pull.ff=false pull
248 +'
249 +
250 +test_expect_success 'pull.rebase=true overrides pull.ff=true' '
251 + test_does_rebase -c pull.rebase=true -c pull.ff=true pull
252 +'
253 +
254 +# Group 3: command line flags take precedence over config
255 +test_expect_failure '--ff-only takes precedence over pull.rebase=true' '
256 + test_attempts_fast_forward -c pull.rebase=true pull --ff-only
257 +'
258 +
259 +test_expect_success '--ff-only takes precedence over pull.rebase=false' '
260 + test_attempts_fast_forward -c pull.rebase=false pull --ff-only
261 +'
262 +
263 +test_expect_failure '--no-rebase takes precedence over pull.ff=only' '
264 + test_falls_back_to_full_merge -c pull.ff=only pull --no-rebase
265 +'
266 +
267 +test_expect_success '--rebase takes precedence over pull.ff=only' '
268 + test_does_rebase -c pull.ff=only pull --rebase
269 +'
270 +
271 +test_expect_success '--rebase overrides pull.ff=true' '
272 + test_does_rebase -c pull.ff=true pull --rebase
273 +'
274 +
275 +test_expect_success '--rebase overrides pull.ff=false' '
276 + test_does_rebase -c pull.ff=false pull --rebase
277 +'
278 +
279 +test_expect_success '--rebase overrides pull.ff unset' '
280 + test_does_rebase pull --rebase
281 +'
282 +
283 +# Group 4: --no-rebase heeds pull.ff=!only or explict --ff or --no-ff
284 +
285 +test_expect_success '--no-rebase works with --no-ff' '
286 + test_does_merge_when_ff_possible pull --no-rebase --no-ff
287 +'
288 +
289 +test_expect_success '--no-rebase works with --ff' '
290 + test_does_fast_forward pull --no-rebase --ff
291 +'
292 +
293 +test_expect_success '--no-rebase does ff if pull.ff unset' '
294 + test_does_fast_forward pull --no-rebase
295 +'
296 +
297 +test_expect_success '--no-rebase heeds pull.ff=true' '
298 + test_does_fast_forward -c pull.ff=true pull --no-rebase
299 +'
300 +
301 +test_expect_success '--no-rebase heeds pull.ff=false' '
302 + test_does_merge_when_ff_possible -c pull.ff=false pull --no-rebase
303 +'
304 +
305 +# Group 5: pull.rebase=!false in combination with --no-ff or --ff
306 +test_expect_success 'pull.rebase=true and --no-ff' '
307 + test_does_rebase -c pull.rebase=true pull --no-ff
308 +'
309 +
310 +test_expect_success 'pull.rebase=true and --ff' '
311 + test_does_rebase -c pull.rebase=true pull --ff
312 +'
313 +
314 +test_expect_success 'pull.rebase=false and --no-ff' '
315 + test_does_merge_when_ff_possible -c pull.rebase=false pull --no-ff
316 +'
317 +
318 +test_expect_success 'pull.rebase=false and --ff, ff possible' '
319 + test_does_fast_forward -c pull.rebase=false pull --ff
320 +'
321 +
322 +test_expect_success 'pull.rebase=false and --ff, ff not possible' '
323 + test_falls_back_to_full_merge -c pull.rebase=false pull --ff
324 +'
325 +
326 +# End of groupings for conflicting merge vs. rebase flags/options
327 +
328 test_expect_success 'merge c1 with c2' '
329 git reset --hard c1 &&
330 test -f c0.c &&