diff options
author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2018-04-25 14:28:56 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-04-26 12:28:42 +0900 |
commit | d1e8b0114bef98e8efe3f8d35430300ff9e00443 (patch) | |
tree | 9d0b6aff06162167b92a938c8a270d3ae7dd0db8 | |
parent | sequencer: introduce the `merge` command (diff) | |
download | tgif-d1e8b0114bef98e8efe3f8d35430300ff9e00443.tar.xz |
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 <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | sequencer.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/sequencer.c b/sequencer.c index 94f4831a0c..6722095655 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2687,7 +2687,7 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len, struct commit *head_commit, *merge_commit, *i; struct commit_list *bases, *j, *reversed = NULL; struct merge_options o; - int merge_arg_len, oneline_offset, ret; + int merge_arg_len, oneline_offset, can_fast_forward, ret; static struct lock_file lock; const char *p; @@ -2772,6 +2772,37 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len, } } + /* + * If HEAD is not identical to the first parent of the original merge + * commit, we cannot fast-forward. + */ + can_fast_forward = opts->allow_ff && commit && commit->parents && + !oidcmp(&commit->parents->item->object.oid, + &head_commit->object.oid); + + /* + * If the merge head is different from the original one, we cannot + * fast-forward. + */ + if (can_fast_forward) { + struct commit_list *second_parent = commit->parents->next; + + if (second_parent && !second_parent->next && + oidcmp(&merge_commit->object.oid, + &second_parent->item->object.oid)) + can_fast_forward = 0; + } + + if (can_fast_forward && commit->parents->next && + !commit->parents->next->next && + !oidcmp(&commit->parents->next->item->object.oid, + &merge_commit->object.oid)) { + rollback_lock_file(&lock); + ret = fast_forward_to(&commit->object.oid, + &head_commit->object.oid, 0, opts); + goto leave_merge; + } + write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ, git_path_merge_head(), 0); write_message("no-ff", 5, git_path_merge_mode(), 0); |