A common workflow: git checkout <branch> ... hack hack hack ... git add -- <path1> <path2> git reset -- <path1>; # oops, that one isn't ready yet git commit One might try to use 'git reset' to undo the effect of 'git add' on an unborn branch, too, but it doesn't work: ... hack hack hack ... $ git add -- <path1> <path2> $ git reset -- <path1> fatal: Failed to resolve 'HEAD' as a valid ref. It is obvious that the operator meant to remove the entry for <path1>, so just do that. This patch only affects the "git reset <path>" syntax; explicit use of "git reset HEAD <path>" will still error out. Suggested-by: Sverre Rabbelier <srabbelier@xxxxxxxxx> Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- builtin/reset.c | 15 ++++++++++++- t/t7106-reset-unborn.sh | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100755 t/t7106-reset-unborn.sh diff --git a/builtin/reset.c b/builtin/reset.c index 2375472..ff57764 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -234,12 +234,14 @@ static void die_if_unmerged_cache(int reset_type) } int cmd_reset(int argc, const char **argv, const char *prefix) { int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0; + int unborn_branch = 0; int patch_mode = 0; - const char *rev = "HEAD"; + const char *implicit_HEAD = "HEAD"; + const char *rev = implicit_HEAD; unsigned char sha1[20], *orig = NULL, sha1_orig[20], *old_orig = NULL, sha1_old_orig[20]; struct commit *commit; char *reflog_action, msg[1024]; const struct option options[] = { @@ -303,11 +305,18 @@ int cmd_reset(int argc, const char **argv, const char *prefix) if (reset_type != NONE) die("--patch is incompatible with --{hard,mixed,soft}"); return interactive_reset(rev, argv + i, prefix); } - if (get_sha1(rev, sha1)) + if (rev == implicit_HEAD) { + /* We may be on a branch yet to be born. */ + resolve_ref("HEAD", sha1, 0, NULL); + if (is_null_sha1(sha1)) { + unborn_branch = 1; + hashcpy(sha1, (const unsigned char *) EMPTY_TREE_SHA1_BIN); + } + } else if (get_sha1(rev, sha1)) die("Failed to resolve '%s' as a valid ref.", rev); /* git reset tree [--] paths... can be used to * load chosen paths from the tree into the index without * affecting the working tree nor HEAD. */ @@ -319,10 +328,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix) reset_type_names[reset_type]); return read_from_tree(prefix, argv + i, sha1, quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN); } + if (unborn_branch) + die("Failed to resolve 'HEAD' as a valid ref."); commit = lookup_commit_reference(sha1); if (!commit) die("Could not parse object '%s'.", rev); hashcpy(sha1, commit->object.sha1); diff --git a/t/t7106-reset-unborn.sh b/t/t7106-reset-unborn.sh new file mode 100755 index 0000000..7baaffd --- /dev/null +++ b/t/t7106-reset-unborn.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='git reset from a branch yet to be born' +. ./test-lib.sh + +>empty + +index_is_empty () { + git ls-files >actual && + test_cmp empty actual +} + +test_expect_success 'reset to remove file' ' + echo one >file && + git add file && + git reset file && + index_is_empty +' + +test_expect_success 'reset after rm to remove file' ' + echo one >file && + git add file && + rm file && + git reset -- file && + index_is_empty +' + +test_expect_success 'reset file that does not match index' ' + echo one >file && + git add file && + echo two >file && + git reset -- file && + index_is_empty +' + +test_expect_success 'reset absent file' ' + git reset -- file && + index_is_empty +' + +test_expect_success 'reset HEAD <files> from unborn branch' ' + test_must_fail git reset HEAD -- . +' + +test_expect_success 'reset HEAD from unborn branch' ' + test_must_fail git reset HEAD && + test_must_fail git reset HEAD -- +' + +test_done -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html