pull: fix handling of multiple heads

With multiple heads, we should not allow rebasing or fast-forwarding. Make sure any fast-forward request calls out specifically the fact that multiple branches are in play. Also, since we cannot fast-forward to multiple branches, fix our computation of can_ff. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Jul 22, 2021 at 05:04 UTC 6f843a3355ee590dfe09eb90679051e75fadf675
2 files changed +15 -5
builtin/pull.c
+14 -4
@@ -913,12 +913,18 @@ static int run_rebase(const struct object_id *newbase,
913 return ret;
914 }
915
916 -static int get_can_ff(struct object_id *orig_head, struct object_id *orig_merge_head)
916 +static int get_can_ff(struct object_id *orig_head,
917 + struct oid_array *merge_heads)
918 {
919 int ret;
920 struct commit_list *list = NULL;
921 struct commit *merge_head, *head;
922 + struct object_id *orig_merge_head;
923
924 + if (merge_heads->nr > 1)
925 + return 0;
926 +
927 + orig_merge_head = &merge_heads->oid[0];
928 head = lookup_commit_reference(the_repository, orig_head);
929 commit_list_insert(head, &list);
930 merge_head = lookup_commit_reference(the_repository, orig_merge_head);
@@ -1057,10 +1063,14 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
1063 die(_("Cannot merge multiple branches into empty head."));
1064 return pull_into_void(merge_heads.oid, &curr_head);
1065 }
1060 - if (opt_rebase && merge_heads.nr > 1)
1061 - die(_("Cannot rebase onto multiple branches."));
1066 + if (merge_heads.nr > 1) {
1067 + if (opt_rebase)
1068 + die(_("Cannot rebase onto multiple branches."));
1069 + if (opt_ff && !strcmp(opt_ff, "--ff-only"))
1070 + die(_("Cannot fast-forward to multiple branches."));
1071 + }
1072
1063 - can_ff = get_can_ff(&orig_head, &merge_heads.oid[0]);
1073 + can_ff = get_can_ff(&orig_head, &merge_heads);
1074
1075 /* ff-only takes precedence over rebase */
1076 if (opt_ff && !strcmp(opt_ff, "--ff-only")) {
t/t7601-merge-pull-config.sh
+1 -1
@@ -331,7 +331,7 @@ test_expect_success 'Multiple heads warns about inability to fast forward' '
331 test_i18ngrep "You have divergent branches" err
332 '
333
334 -test_expect_failure 'Multiple can never be fast forwarded' '
334 +test_expect_success 'Multiple can never be fast forwarded' '
335 git reset --hard c0 &&
336 test_must_fail git -c pull.ff=only pull . c1 c2 c3 2>err &&
337 test_i18ngrep ! "You have divergent branches" err &&