#include #include "cache.h" #include "commit.h" static struct commit *common_ancestor(struct commit *rev1, struct commit *rev2) { struct commit_list *list = NULL; struct commit_list *result = NULL; if (rev1 == rev2) return rev1; parse_commit(rev1); parse_commit(rev2); rev1->object.flags |= 1; rev2->object.flags |= 2; insert_by_date(rev1, &list); insert_by_date(rev2, &list); while (list) { struct commit *commit = list->item; struct commit_list *tmp = list, *parents; int flags = commit->object.flags & 3; list = list->next; free(tmp); switch (flags) { case 3: insert_by_date(commit, &result); continue; case 0: die("git-merge-base: commit without either parent?"); } parents = commit->parents; while (parents) { struct commit *p = parents->item; parents = parents->next; if ((p->object.flags & flags) == flags) continue; parse_commit(p); p->object.flags |= flags; insert_by_date(p, &list); } } if (!result) return NULL; return result->item; } int main(int argc, char **argv) { struct commit *rev1, *rev2, *ret; unsigned char rev1key[20], rev2key[20]; if (argc != 3 || get_sha1(argv[1], rev1key) || get_sha1(argv[2], rev2key)) { usage("git-merge-base "); } rev1 = lookup_commit_reference(rev1key); rev2 = lookup_commit_reference(rev2key); if (!rev1 || !rev2) return 1; ret = common_ancestor(rev1, rev2); if (!ret) return 1; printf("%s\n", sha1_to_hex(ret->object.sha1)); return 0; }