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

[PATCH 2/2] restore: default to HEAD when combining --worktree and --staged

From
Eric Sunshine <sunshine@sunshineco.com>
Date
May 1, 2020, 08:27 UTC
Message-ID
<20200501082746.23943-3-sunshine@sunshineco.com>
In-Reply-To
<20200501082746.23943-1-sunshine@sunshineco.com>

The default restore source for --worktree is the index, and the default source for --staged is HEAD. However, when combining --worktree and --staged in the same invocation, git-restore requires the source to be specified explicitly via --source since it would otherwise be ambiguous ("should it restore from the index or from HEAD?"). This requirement makes it cumbersome to restore a file in both the worktree and the index.

However, HEAD is also a reasonably intuitive default restore source when --worktree and --staged are combined. After all, if a user is asking to throw away all local changes to a file (on disk and in the index) without specifying a restore source explicitly -- and the user expects the file to be restored from _somewhere_ -- then it is likely that the user expects them to be restored from HEAD, which is an intuitive and logical place to find a recent unadulterated copy of the file.

Therefore, make HEAD the default restore source when --worktree and --staged are combined.

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
---
 Documentation/git-restore.txt | 14 +++++++-------
 builtin/checkout.c            |  9 +++------
 t/t2070-restore.sh            | 12 +++++++++---
 3 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/Documentation/git-restore.txt b/Documentation/git-restore.txt
index 8906499637..5b61812e17 100644
--- a/Documentation/git-restore.txt
+++ b/Documentation/git-restore.txt
@@ -22,10 +22,10 @@ The command can also be used to restore the content in the index with
 `--staged`, or restore both the working tree and the index with
 `--staged --worktree`.
 
-By default, the restore sources for working tree and the index are the
-index and `HEAD` respectively. `--source` could be used to specify a
-commit as the restore source; it is required when combining `--staged`
-and `--worktree`.
+By default, the restore source for `--worktree` is the index, and the
+restore source for `--staged` is `HEAD`. When combining `--worktree` and
+`--staged`, the restore source is `HEAD`. `--source` can be used to specify
+a different commit as the restore source.
 
 See "Reset, restore and revert" in linkgit:git[1] for the differences
 between the three commands.
@@ -40,10 +40,10 @@ OPTIONS
 	tree. It is common to specify the source tree by naming a
 	commit, branch or tag associated with it.
 +
-If not specified, the default restore source for the working tree is
-the index, and the default restore source for the index is
+If not specified, the default restore source for `--worktree` is
+the index, and the default restore source for `--staged` is
 `HEAD`. When both `--staged` and `--worktree` are specified,
-`--source` must also be specified.
+the default restore source is `HEAD`.
 
 -p::
 --patch::
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 7a01d00f53..500c3e23ff 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1604,14 +1604,11 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	}
 	if (opts->checkout_index < 0 || opts->checkout_worktree < 0)
 		BUG("these flags should be non-negative by now");
-	if (opts->checkout_index > 0 && opts->checkout_worktree > 0 &&
-	    !opts->from_treeish)
-		die(_("--source required when using --worktree and --staged"));
 	/*
-	 * convenient shortcut: "git restore --staged" equals
-	 * "git restore --staged --source HEAD"
+	 * convenient shortcut: "git restore --staged [--worktree]" equals
+	 * "git restore --staged [--worktree] --source HEAD"
 	 */
-	if (!opts->from_treeish && opts->checkout_index && !opts->checkout_worktree)
+	if (!opts->from_treeish && opts->checkout_index)
 		opts->from_treeish = "HEAD";
 
 	/*
diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh
index 19efa21fdb..89e5a142c9 100755
--- a/t/t2070-restore.sh
+++ b/t/t2070-restore.sh
@@ -69,9 +69,15 @@ test_expect_success 'restore --staged uses HEAD as source' '
 	test_cmp expected actual
 '
 
-test_expect_success 'restore --worktree --staged requires --source' '
-	test_must_fail git restore --worktree --staged first.t 2>err &&
-	test_i18ngrep "source required when using --worktree and --staged" err
+test_expect_success 'restore --worktree --staged uses HEAD as source' '
+	test_when_finished git reset --hard &&
+	git show HEAD:./first.t >expected &&
+	echo dirty >>first.t &&
+	git add first.t &&
+	git restore --worktree --staged first.t &&
+	git show :./first.t >actual &&
+	test_cmp expected actual &&
+	test_cmp expected first.t
 '
 
 test_expect_success 'restore --ignore-unmerged ignores unmerged entries' '
-- 
2.26.2.526.g744177e7f7
Previous: Taylor BlauNext: Junio C Hamano
Message 5 of 10 in “enhance "git restore --worktree --staged" behavior”
  1. 0/2 enhance "git restore --worktree --staged" behaviorEric Sunshine, May 1, 2020
  2. 1/2 restore: require --source when combining --worktree and --stagedEric Sunshine, May 1, 2020
  3. Eric SunshineMay 1, 2020
  4. Taylor BlauMay 1, 2020
  5. 2/2 restore: default to HEAD when combining --worktree and --stagedEric Sunshine, May 1, 2020
  6. Junio C HamanoMay 1, 2020
  7. Eric SunshineMay 5, 2020
  8. Taylor BlauMay 1, 2020
  9. Eric SunshineMay 5, 2020
  10. Taylor BlauMay 5, 2020

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.