提交 0b9442d6 编写于 作者: L Linus Torvalds 提交者: Junio C Hamano

[PATCH] Speed up git-merge-base a lot

In commit 4f7eb2e5 I fixed git-merge-base
getting confused by datestamps that caused it to traverse things in a
non-obvious order.

However, my fix was a very brute-force one, and it had some really
horrible implications for more complex trees with lots of parallell
development. It might end up traversing all the way to the root commit.

Now, normally that isn't that horrible: it's used mainly for merging, and
the bad cases really tend to happen fairly rarely, so if it takes a few
seconds, we're not in too bad shape.

However, gitk will also do the git-merge-base for every merge it shows,
because it basically re-does the trivial merge in order to show the
"interesting" parts. And there we'd really like the result to be
instantaneous.

This patch does that by walking the tree more completely, and using the
same heuristic as git-rev-list to decide "ok, the rest is uninteresting".

In one - hopefully fairly extreme - case, it made a git-merge-base go from
just under five seconds(!) to a tenth of a second on my machine.
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
Signed-off-by: NJunio C Hamano <junkio@cox.net>
上级 2b64f88f
......@@ -2,6 +2,22 @@
#include "cache.h"
#include "commit.h"
#define PARENT1 1
#define PARENT2 2
#define UNINTERESTING 4
static int interesting(struct commit_list *list)
{
while (list) {
struct commit *commit = list->item;
list = list->next;
if (commit->object.flags & UNINTERESTING)
continue;
return 1;
}
return 0;
}
static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
{
struct commit_list *list = NULL;
......@@ -18,19 +34,18 @@ static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2)
insert_by_date(rev1, &list);
insert_by_date(rev2, &list);
while (list) {
while (interesting(list)) {
struct commit *commit = list->item;
struct commit_list *tmp = list, *parents;
int flags = commit->object.flags & 3;
int flags = commit->object.flags & 7;
list = list->next;
free(tmp);
switch (flags) {
case 3:
if (flags == 3) {
insert_by_date(commit, &result);
continue;
case 0:
die("git-merge-base: commit without either parent?");
/* Mark children of a found merge uninteresting */
flags |= UNINTERESTING;
}
parents = commit->parents;
while (parents) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册