git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/4] reset: accept "git reset -- <path>" from unborn branch

From
Jonathan Nieder <jrnieder@gmail.com>
Date
Oct 19, 2010, 22:13 UTC
Message-ID
<20101019221331.GF32029@burratino>
In-Reply-To
<20101019221005.GC32029@burratino>
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@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 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
Previous: Jonathan NiederNext: Jonathan Nieder
Message 21 of 59 in “Git terminology: remote, add, track, stage, etc.”
  1. Thore HusfeldtOct 18, 2010
  2. Jonathan NiederOct 18, 2010
  3. reset: accept "git reset <removed file>"Jonathan Nieder, Oct 18, 2010
  4. Junio C HamanoOct 18, 2010
  5. Jonathan NiederOct 19, 2010
  6. Junio C HamanoOct 19, 2010
  7. Jonathan NiederOct 19, 2010
  8. Sverre RabbelierOct 18, 2010
  9. Junio C HamanoOct 19, 2010
  10. Ramkumar RamachandraOct 19, 2010
  11. Jonathan NiederOct 19, 2010
  12. Sverre RabbelierOct 19, 2010
  13. Thore HusfeldtOct 19, 2010
  14. User manual: "You cannot check out these remote-tracking branches"Jonathan Nieder, Oct 19, 2010
  15. Matthieu MoyOct 19, 2010
  16. Nicolas PitreOct 19, 2010
  17. Junio C HamanoOct 19, 2010
  18. 0/4 reset: be more flexible about <rev>Jonathan Nieder, Oct 19, 2010
  19. 1/4 reset -p: accept "git reset -p <tree>"Jonathan Nieder, Oct 19, 2010
  20. 2/4 reset: accept "git reset <tree> <path>"Jonathan Nieder, Oct 19, 2010
  21. 3/4 reset: accept "git reset -- <path>" from unborn branchJonathan Nieder, Oct 19, 2010
  22. 4/4 reset: accept "git reset HEAD <path>" from unborn branchJonathan Nieder, Oct 19, 2010
  23. Junio C HamanoOct 19, 2010
  24. Jonathan NiederOct 19, 2010
  25. Ramkumar RamachandraOct 27, 2010
  26. Drew NorthupOct 27, 2010
  27. Matthieu MoyOct 27, 2010
  28. Ramkumar RamachandraOct 28, 2010
  29. Matthieu MoyOct 28, 2010
  30. Matthieu MoyOct 18, 2010
  31. Miles BaderOct 19, 2010
  32. Wincent ColaiutaOct 19, 2010
  33. Miles BaderOct 19, 2010
  34. Wincent ColaiutaOct 19, 2010
  35. Eugene SajineOct 19, 2010
  36. Paul BolleOct 22, 2010
  37. Eugene SajineOct 22, 2010
  38. Drew NorthupOct 22, 2010
  39. Thore HusfeldtOct 20, 2010
  40. Matthieu MoyOct 20, 2010
  41. Drew NorthupOct 20, 2010
  42. Jakub NarebskiOct 18, 2010
  43. Matthijs KooijmanOct 19, 2010
  44. Jakub NarebskiOct 19, 2010
  45. Thore HusfeldtOct 19, 2010
  46. Jakub NarebskiOct 19, 2010
  47. Michael HaggertyOct 21, 2010
  48. Drew NorthupOct 21, 2010
  49. Thore HusfeldtOct 21, 2010
  50. Drew NorthupOct 21, 2010
  51. Thore HusfeldtOct 21, 2010
  52. Drew NorthupOct 21, 2010
  53. Miles BaderOct 22, 2010
  54. Drew NorthupOct 22, 2010
  55. Porcelain scripts: Rewrite cryptic "needs update" error messageRamkumar Ramachandra, Oct 19, 2010
  56. Ramkumar RamachandraOct 27, 2010
  57. Junio C HamanoNov 5, 2010
  58. Ævar Arnfjörð BjarmasonFeb 12, 2011
  59. Drew NorthupOct 19, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.