summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Schreiber <arthurschreiber@github.com>2016-10-18 08:20:41 +0200
committerArthur Schreiber <arthurschreiber@github.com>2016-10-18 08:20:41 +0200
commit6d354747acf9f76200355b79907c1f370d29e8d6 (patch)
tree99fc0b38baedf94bc255025122696660e0bd7a94
parenta7df4a9151f09ca1f66f6267f2beb9ddf9739b73 (diff)
downloadlibgit2-6d354747acf9f76200355b79907c1f370d29e8d6.tar.gz
Perf: Don't perform merge operations for trivial merges.
When one side of a merge is treesame to the ancestor, we can take the other side and skip all the expensive merge operations. This optimization can only be performed when the generation of REUC extension data is skipped.
-rw-r--r--src/merge.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/merge.c b/src/merge.c
index 6934aa731..2a8fc7fa6 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -2018,6 +2018,26 @@ int git_merge_trees(
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
int error;
+ assert(out && repo);
+
+ /* if one side is treesame to the ancestor, take the other side */
+ if (ancestor_tree && merge_opts && (merge_opts->flags & GIT_MERGE_SKIP_REUC)) {
+ const git_tree *result = NULL;
+ const git_oid *ancestor_tree_id = git_tree_id(ancestor_tree);
+
+ if (our_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(our_tree)))
+ result = their_tree;
+ else if (their_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(their_tree)))
+ result = our_tree;
+
+ if (result) {
+ if ((error = git_index_new(out)) == 0)
+ error = git_index_read_tree(*out, result);
+
+ return error;
+ }
+ }
+
iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
if ((error = git_iterator_for_tree(