diff options
Diffstat (limited to 'builtin-reset.c')
-rw-r--r-- | builtin-reset.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/builtin-reset.c b/builtin-reset.c index 9514b77f8c..11d1c6e4d6 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -20,11 +20,14 @@ #include "parse-options.h" static const char * const git_reset_usage[] = { - "git reset [--mixed | --soft | --hard] [-q] [<commit>]", + "git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>]", "git reset [--mixed] <commit> [--] <paths>...", NULL }; +enum reset_type { MIXED, SOFT, HARD, MERGE, NONE }; +static const char *reset_type_names[] = { "mixed", "soft", "hard", "merge", NULL }; + static char *args_to_str(const char **argv) { char *buf = NULL; @@ -49,7 +52,7 @@ static inline int is_merge(void) return !access(git_path("MERGE_HEAD"), F_OK); } -static int reset_index_file(const unsigned char *sha1, int is_hard_reset, int quiet) +static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet) { int i = 0; const char *args[6]; @@ -57,9 +60,17 @@ static int reset_index_file(const unsigned char *sha1, int is_hard_reset, int qu args[i++] = "read-tree"; if (!quiet) args[i++] = "-v"; - args[i++] = "--reset"; - if (is_hard_reset) + switch (reset_type) { + case MERGE: args[i++] = "-u"; + args[i++] = "-m"; + break; + case HARD: + args[i++] = "-u"; + /* fallthrough */ + default: + args[i++] = "--reset"; + } args[i++] = sha1_to_hex(sha1); args[i] = NULL; @@ -97,7 +108,8 @@ static int update_index_refresh(int fd, struct lock_file *index_lock, int flags) if (read_cache() < 0) return error("Could not read index"); - result = refresh_cache(flags) ? 1 : 0; + result = refresh_index(&the_index, (flags), NULL, NULL, + "Unstaged changes after reset:") ? 1 : 0; if (write_cache(fd, active_cache, active_nr) || commit_locked_index(index_lock)) return error ("Could not refresh index"); @@ -131,6 +143,17 @@ static void update_index_from_diff(struct diff_queue_struct *q, } } +static int interactive_reset(const char *revision, const char **argv, + const char *prefix) +{ + const char **pathspec = NULL; + + if (*argv) + pathspec = get_pathspec(prefix, argv); + + return run_add_interactive(revision, "--patch=reset", pathspec); +} + static int read_from_tree(const char *prefix, const char **argv, unsigned char *tree_sha1, int refresh_flags) { @@ -169,12 +192,10 @@ static void prepend_reflog_action(const char *action, char *buf, size_t size) warning("Reflog action message too long: %.*s...", 50, buf); } -enum reset_type { MIXED, SOFT, HARD, NONE }; -static const char *reset_type_names[] = { "mixed", "soft", "hard", NULL }; - int cmd_reset(int argc, const char **argv, const char *prefix) { int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0; + int patch_mode = 0; const char *rev = "HEAD"; unsigned char sha1[20], *orig = NULL, sha1_orig[20], *old_orig = NULL, sha1_old_orig[20]; @@ -186,14 +207,17 @@ int cmd_reset(int argc, const char **argv, const char *prefix) OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT), OPT_SET_INT(0, "hard", &reset_type, "reset HEAD, index and working tree", HARD), + OPT_SET_INT(0, "merge", &reset_type, + "reset HEAD, index and working tree", MERGE), OPT_BOOLEAN('q', NULL, &quiet, "disable showing new HEAD in hard reset and progress message"), + OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"), OPT_END() }; git_config(git_default_config, NULL); - argc = parse_options(argc, argv, options, git_reset_usage, + argc = parse_options(argc, argv, prefix, options, git_reset_usage, PARSE_OPT_KEEP_DASHDASH); reflog_action = args_to_str(argv); setenv("GIT_REFLOG_ACTION", reflog_action, 0); @@ -218,7 +242,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) } /* * Otherwise, argv[i] could be either <rev> or <paths> and - * has to be unambigous. + * has to be unambiguous. */ else if (!get_sha1(argv[i], sha1)) { /* @@ -241,6 +265,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix) die("Could not parse object '%s'.", rev); hashcpy(sha1, commit->object.sha1); + if (patch_mode) { + if (reset_type != NONE) + die("--patch is incompatible with --{hard,mixed,soft}"); + return interactive_reset(rev, argv + i, prefix); + } + /* git reset tree [--] paths... can be used to * load chosen paths from the tree into the index without * affecting the working tree nor HEAD. */ @@ -251,13 +281,15 @@ int cmd_reset(int argc, const char **argv, const char *prefix) die("Cannot do %s reset with paths.", reset_type_names[reset_type]); return read_from_tree(prefix, argv + i, sha1, - quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED); + quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN); } if (reset_type == NONE) reset_type = MIXED; /* by default */ - if (reset_type == HARD && is_bare_repository()) - die("hard reset makes no sense in a bare repository"); + if ((reset_type == HARD || reset_type == MERGE) + && !is_inside_work_tree()) + die("%s reset requires a work tree", + reset_type_names[reset_type]); /* Soft reset does not touch the index file nor the working tree * at all, but requires them in a good order. Other resets reset @@ -266,7 +298,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) if (is_merge() || read_cache() < 0 || unmerged_cache()) die("Cannot do a soft reset in the middle of a merge."); } - else if (reset_index_file(sha1, (reset_type == HARD), quiet)) + else if (reset_index_file(sha1, reset_type, quiet)) die("Could not reset index file to revision '%s'.", rev); /* Any resets update HEAD to the head being switched to, @@ -292,7 +324,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) break; case MIXED: /* Report what has not been updated. */ update_index_refresh(0, NULL, - quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED); + quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN); break; } |