Skip to content

Commit d1e8b01

Browse files
dschogitster
authored andcommitted
sequencer: fast-forward merge commands, if possible
Just like with regular `pick` commands, if we are trying to rebase a merge commit, we now test whether the parents of said commit match HEAD and the commits to be merged, and fast-forward if possible. This is not only faster, but also avoids unnecessary proliferation of new objects. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4c68e7d commit d1e8b01

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

sequencer.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2687,7 +2687,7 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
26872687
struct commit *head_commit, *merge_commit, *i;
26882688
struct commit_list *bases, *j, *reversed = NULL;
26892689
struct merge_options o;
2690-
int merge_arg_len, oneline_offset, ret;
2690+
int merge_arg_len, oneline_offset, can_fast_forward, ret;
26912691
static struct lock_file lock;
26922692
const char *p;
26932693

@@ -2772,6 +2772,37 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
27722772
}
27732773
}
27742774

2775+
/*
2776+
* If HEAD is not identical to the first parent of the original merge
2777+
* commit, we cannot fast-forward.
2778+
*/
2779+
can_fast_forward = opts->allow_ff && commit && commit->parents &&
2780+
!oidcmp(&commit->parents->item->object.oid,
2781+
&head_commit->object.oid);
2782+
2783+
/*
2784+
* If the merge head is different from the original one, we cannot
2785+
* fast-forward.
2786+
*/
2787+
if (can_fast_forward) {
2788+
struct commit_list *second_parent = commit->parents->next;
2789+
2790+
if (second_parent && !second_parent->next &&
2791+
oidcmp(&merge_commit->object.oid,
2792+
&second_parent->item->object.oid))
2793+
can_fast_forward = 0;
2794+
}
2795+
2796+
if (can_fast_forward && commit->parents->next &&
2797+
!commit->parents->next->next &&
2798+
!oidcmp(&commit->parents->next->item->object.oid,
2799+
&merge_commit->object.oid)) {
2800+
rollback_lock_file(&lock);
2801+
ret = fast_forward_to(&commit->object.oid,
2802+
&head_commit->object.oid, 0, opts);
2803+
goto leave_merge;
2804+
}
2805+
27752806
write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ,
27762807
git_path_merge_head(), 0);
27772808
write_message("no-ff", 5, git_path_merge_mode(), 0);

0 commit comments

Comments
 (0)