diff options
Diffstat (limited to 'builtin-revert.c')
-rw-r--r-- | builtin-revert.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/builtin-revert.c b/builtin-revert.c index a655c8ee2a..bfed69d7e2 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -19,9 +19,9 @@ * Copyright (c) 2005 Junio C Hamano */ -static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] <commit-ish>"; +static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] [-m parent-number] <commit-ish>"; -static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] <commit-ish>"; +static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-m parent-number] [-r] [-x] <commit-ish>"; static int edit; static int replay; @@ -29,6 +29,7 @@ static enum { REVERT, CHERRY_PICK } action; static int no_commit; static struct commit *commit; static int needed_deref; +static int mainline; static const char *me; @@ -58,6 +59,12 @@ static void parse_options(int argc, const char **argv) else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-" "to-expose-my-private-commit-object-name")) replay = 0; + else if (!strcmp(arg, "-m") || !strcmp(arg, "--mainline")) { + if (++i >= argc || + strtol_i(argv[i], 10, &mainline) || + mainline <= 0) + usage(usage_str); + } else if (strcmp(arg, "-r")) usage(usage_str); } @@ -234,7 +241,7 @@ static int merge_recursive(const char *base_sha1, static int revert_or_cherry_pick(int argc, const char **argv) { unsigned char head[20]; - struct commit *base, *next; + struct commit *base, *next, *parent; int i; char *oneline, *reencoded_message = NULL; const char *message, *encoding; @@ -269,8 +276,29 @@ static int revert_or_cherry_pick(int argc, const char **argv) if (!commit->parents) die ("Cannot %s a root commit", me); - if (commit->parents->next) - die ("Cannot %s a multi-parent commit.", me); + if (commit->parents->next) { + /* Reverting or cherry-picking a merge commit */ + int cnt; + struct commit_list *p; + + if (!mainline) + die("Commit %s is a merge but no -m option was given.", + sha1_to_hex(commit->object.sha1)); + + for (cnt = 1, p = commit->parents; + cnt != mainline && p; + cnt++) + p = p->next; + if (cnt != mainline || !p) + die("Commit %s does not have parent %d", + sha1_to_hex(commit->object.sha1), mainline); + parent = p->item; + } else if (0 < mainline) + die("Mainline was specified but commit %s is not a merge.", + sha1_to_hex(commit->object.sha1)); + else + parent = commit->parents->item; + if (!(message = commit->buffer)) die ("Cannot get commit message for %s", sha1_to_hex(commit->object.sha1)); @@ -299,14 +327,14 @@ static int revert_or_cherry_pick(int argc, const char **argv) char *oneline_body = strchr(oneline, ' '); base = commit; - next = commit->parents->item; + next = parent; add_to_msg("Revert \""); add_to_msg(oneline_body + 1); add_to_msg("\"\n\nThis reverts commit "); add_to_msg(sha1_to_hex(commit->object.sha1)); add_to_msg(".\n"); } else { - base = commit->parents->item; + base = parent; next = commit; set_author_ident_env(message); add_message_to_msg(message); |