Skip to content

Commit 6683463

Browse files
author
Linus Torvalds
committed
Do a very simple "merge-base" that finds the most recent common
parent of two commits. The question of "best" commit can probably be tweaked almost arbitrarily. In particular, trying to take things like how big the tree differences are into account migt be a good idea. This one is just very simple.
1 parent 15000d7 commit 6683463

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ CC=gcc
1414

1515
PROG= update-cache show-diff init-db write-tree read-tree commit-tree \
1616
cat-file fsck-cache checkout-cache diff-tree rev-tree show-files \
17-
check-files ls-tree
17+
check-files ls-tree merge-base
1818

1919
all: $(PROG)
2020

@@ -64,6 +64,9 @@ check-files: check-files.o read-cache.o
6464
ls-tree: ls-tree.o read-cache.o
6565
$(CC) $(CFLAGS) -o ls-tree ls-tree.o read-cache.o $(LIBS)
6666

67+
merge-base: merge-base.o read-cache.o
68+
$(CC) $(CFLAGS) -o merge-base merge-base.o read-cache.o $(LIBS)
69+
6770
read-cache.o: cache.h
6871
show-diff.o: cache.h
6972

merge-base.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include "cache.h"
2+
#include "revision.h"
3+
4+
/*
5+
* This is stupid. We could have much better heurstics, I bet.
6+
*/
7+
static int better(struct revision *new, struct revision *old)
8+
{
9+
return new->date > old->date;
10+
}
11+
12+
static struct revision *common_parent(struct revision *rev1, struct revision *rev2)
13+
{
14+
int i;
15+
struct revision *best = NULL;
16+
17+
mark_reachable(rev1, 1);
18+
mark_reachable(rev2, 2);
19+
for (i = 0; i < nr_revs ;i++) {
20+
struct revision *rev = revs[i];
21+
if ((rev->flags & 3) != 3)
22+
continue;
23+
if (!best) {
24+
best = rev;
25+
continue;
26+
}
27+
if (better(rev, best))
28+
best = rev;
29+
}
30+
return best;
31+
}
32+
33+
int main(int argc, char **argv)
34+
{
35+
unsigned char rev1[20], rev2[20];
36+
struct revision *common;
37+
38+
if (argc != 3 || get_sha1_hex(argv[1], rev1) || get_sha1_hex(argv[2], rev2))
39+
usage("merge-base <commit1> <commit2>");
40+
41+
/*
42+
* We will eventually want to include a revision cache file
43+
* that "rev-tree.c" has generated, since this is going to
44+
* otherwise be quite expensive for big trees..
45+
*
46+
* That's some time off, though, and in the meantime we know
47+
* that we have a solution to the eventual expense.
48+
*/
49+
parse_commit(rev1);
50+
parse_commit(rev2);
51+
52+
common = common_parent(lookup_rev(rev1), lookup_rev(rev2));
53+
if (!common)
54+
die("no common parent found");
55+
printf("%s\n", sha1_to_hex(common->sha1));
56+
return 0;
57+
}

0 commit comments

Comments
 (0)