int cmd_merge_recursive(int argc, const char **argv, const char *prefix) { const unsigned char *bases[21]; unsigned bases_count = 0; int i, failed; unsigned char h1[20], h2[20]; struct merge_options o; struct commit *result; init_merge_options(&o); if (argv[0] && ends_with(argv[0], "-subtree")) o.subtree_shift = ""; if (argc < 4) usagef(builtin_merge_recursive_usage, argv[0]); for (i = 1; i < argc; ++i) { const char *arg = argv[i]; if (starts_with(arg, "--")) { if (!arg[2]) break; if (parse_merge_opt(&o, arg + 2)) die("Unknown option %s", arg); continue; } if (bases_count < ARRAY_SIZE(bases)-1) { unsigned char *sha = xmalloc(20); if (get_sha1(argv[i], sha)) die("Could not parse object '%s'", argv[i]); bases[bases_count++] = sha; } else warning("Cannot handle more than %d bases. " "Ignoring %s.", (int)ARRAY_SIZE(bases)-1, argv[i]); } if (argc - i != 3) /* "--" "<head>" "<remote>" */ die("Not handling anything other than two heads merge."); o.branch1 = argv[++i]; o.branch2 = argv[++i]; if (get_sha1(o.branch1, h1)) die("Could not resolve ref '%s'", o.branch1); if (get_sha1(o.branch2, h2)) die("Could not resolve ref '%s'", o.branch2); o.branch1 = better_branch_name(o.branch1); o.branch2 = better_branch_name(o.branch2); if (o.verbosity >= 3) printf("Merging %s with %s\n", o.branch1, o.branch2); failed = merge_recursive_generic(&o, h1, h2, bases_count, bases, &result); if (failed < 0) return 128; /* die() error code */ return failed; }
static struct commit *get_ref(const char *ref) { unsigned char sha1[20]; struct object *object; if (get_sha1(ref, sha1)) die("Could not resolve ref '%s'", ref); object = deref_tag(parse_object(sha1), ref, strlen(ref)); if (!object) return NULL; if (object->type == OBJ_TREE) return make_virtual_commit((struct tree*)object, better_branch_name(ref)); if (object->type != OBJ_COMMIT) return NULL; if (parse_commit((struct commit *)object)) die("Could not parse commit '%s'", sha1_to_hex(object->sha1)); return (struct commit *)object; }
int cmd_merge_recursive(int argc, const char **argv, const char *prefix) { static const char *bases[20]; static unsigned bases_count = 0; int i, clean; const char *branch1, *branch2; struct commit *result, *h1, *h2; struct commit_list *ca = NULL; struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); int index_fd; if (argv[0]) { int namelen = strlen(argv[0]); if (8 < namelen && !strcmp(argv[0] + namelen - 8, "-subtree")) subtree_merge = 1; } git_config(merge_config, NULL); if (getenv("GIT_MERGE_VERBOSITY")) verbosity = strtol(getenv("GIT_MERGE_VERBOSITY"), NULL, 10); if (argc < 4) die("Usage: %s <base>... -- <head> <remote> ...\n", argv[0]); for (i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--")) break; if (bases_count < sizeof(bases)/sizeof(*bases)) bases[bases_count++] = argv[i]; } if (argc - i != 3) /* "--" "<head>" "<remote>" */ die("Not handling anything other than two heads merge."); if (verbosity >= 5) buffer_output = 0; branch1 = argv[++i]; branch2 = argv[++i]; h1 = get_ref(branch1); h2 = get_ref(branch2); branch1 = better_branch_name(branch1); branch2 = better_branch_name(branch2); if (show(3)) printf("Merging %s with %s\n", branch1, branch2); index_fd = hold_locked_index(lock, 1); for (i = 0; i < bases_count; i++) { struct commit *ancestor = get_ref(bases[i]); ca = commit_list_insert(ancestor, &ca); } clean = merge_recursive(h1, h2, branch1, branch2, ca, &result); if (active_cache_changed && (write_cache(index_fd, active_cache, active_nr) || commit_locked_index(lock))) die ("unable to write %s", get_index_file()); return clean ? 0: 1; }