Skip to content

Commit 2f328c3

Browse files
martinvonzgitster
authored andcommitted
reset $sha1 $pathspec: require $sha1 only to be treeish
Resetting with paths does not update HEAD and there is nothing else that a commit should be needed for. Relax the argument parsing so only a tree is required. The sha1 is only passed to read_from_tree(), which already only requires a tree. The "rev" variable we pass to run_add_interactive() will resolve to a tree. This is fine since interactive_reset only needs the parameter to be a treeish and doesn't use it for display purposes. Signed-off-by: Martin von Zweigbergk <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7637df1 commit 2f328c3

File tree

2 files changed

+35
-21
lines changed

2 files changed

+35
-21
lines changed

builtin/reset.c

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,10 @@ static const char **parse_args(const char **argv, const char *prefix, const char
178178
/*
179179
* Possible arguments are:
180180
*
181-
* git reset [-opts] <rev> <paths>...
182-
* git reset [-opts] <rev> -- <paths>...
183-
* git reset [-opts] -- <paths>...
181+
* git reset [-opts] [<rev>]
182+
* git reset [-opts] <tree> [<paths>...]
183+
* git reset [-opts] <tree> -- [<paths>...]
184+
* git reset [-opts] -- [<paths>...]
184185
* git reset [-opts] <paths>...
185186
*
186187
* At this point, argv points immediately after [-opts].
@@ -195,11 +196,13 @@ static const char **parse_args(const char **argv, const char *prefix, const char
195196
}
196197
/*
197198
* Otherwise, argv[0] could be either <rev> or <paths> and
198-
* has to be unambiguous.
199+
* has to be unambiguous. If there is a single argument, it
200+
* can not be a tree
199201
*/
200-
else if (!get_sha1_committish(argv[0], unused)) {
202+
else if ((!argv[1] && !get_sha1_committish(argv[0], unused)) ||
203+
(argv[1] && !get_sha1_treeish(argv[0], unused))) {
201204
/*
202-
* Ok, argv[0] looks like a rev; it should not
205+
* Ok, argv[0] looks like a commit/tree; it should not
203206
* be a filename.
204207
*/
205208
verify_non_filename(prefix, argv[0]);
@@ -241,7 +244,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
241244
const char *rev;
242245
unsigned char sha1[20];
243246
const char **pathspec = NULL;
244-
struct commit *commit;
245247
const struct option options[] = {
246248
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
247249
OPT_SET_INT(0, "mixed", &reset_type,
@@ -263,19 +265,23 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
263265
PARSE_OPT_KEEP_DASHDASH);
264266
pathspec = parse_args(argv, prefix, &rev);
265267

266-
if (get_sha1_committish(rev, sha1))
267-
die(_("Failed to resolve '%s' as a valid ref."), rev);
268-
269-
/*
270-
* NOTE: As "git reset $treeish -- $path" should be usable on
271-
* any tree-ish, this is not strictly correct. We are not
272-
* moving the HEAD to any commit; we are merely resetting the
273-
* entries in the index to that of a treeish.
274-
*/
275-
commit = lookup_commit_reference(sha1);
276-
if (!commit)
277-
die(_("Could not parse object '%s'."), rev);
278-
hashcpy(sha1, commit->object.sha1);
268+
if (!pathspec) {
269+
struct commit *commit;
270+
if (get_sha1_committish(rev, sha1))
271+
die(_("Failed to resolve '%s' as a valid revision."), rev);
272+
commit = lookup_commit_reference(sha1);
273+
if (!commit)
274+
die(_("Could not parse object '%s'."), rev);
275+
hashcpy(sha1, commit->object.sha1);
276+
} else {
277+
struct tree *tree;
278+
if (get_sha1_treeish(rev, sha1))
279+
die(_("Failed to resolve '%s' as a valid tree."), rev);
280+
tree = parse_tree_indirect(sha1);
281+
if (!tree)
282+
die(_("Could not parse object '%s'."), rev);
283+
hashcpy(sha1, tree->object.sha1);
284+
}
279285

280286
if (patch_mode) {
281287
if (reset_type != NONE)
@@ -340,7 +346,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
340346
update_ref_status = update_refs(rev, sha1);
341347

342348
if (reset_type == HARD && !update_ref_status && !quiet)
343-
print_new_head_line(commit);
349+
print_new_head_line(lookup_commit_reference(sha1));
344350

345351
remove_branch_state();
346352
}

t/t7102-reset.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,4 +497,12 @@ test_expect_success 'disambiguation (4)' '
497497
test ! -f secondfile
498498
'
499499

500+
test_expect_success 'reset with paths accepts tree' '
501+
# for simpler tests, drop last commit containing added files
502+
git reset --hard HEAD^ &&
503+
git reset HEAD^^{tree} -- . &&
504+
git diff --cached HEAD^ --exit-code &&
505+
git diff HEAD --exit-code
506+
'
507+
500508
test_done

0 commit comments

Comments
 (0)