@@ -1691,6 +1691,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
struct branch_info *new_branch_info)
{
int parseopt_flags = 0;
+ int unborn_and_unspecified = 0;
opts->overwrite_ignore = 1;
opts->prefix = prefix;
@@ -1754,12 +1755,6 @@ 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");
- /*
- * convenient shortcut: "git restore --staged [--worktree]" equals
- * "git restore --staged [--worktree] --source HEAD"
- */
- if (!opts->from_treeish && opts->checkout_index)
- opts->from_treeish = "HEAD";
/*
* From here on, new_branch will contain the branch to be checked out,
@@ -1785,6 +1780,18 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
opts->new_branch = argv0 + 1;
}
+ /*
+ * convenient shortcut: "git restore --staged [--worktree]" equals
+ * "git restore --staged [--worktree] --source HEAD"
+ */
+ if (!opts->from_treeish && opts->checkout_index) {
+ struct object_id oid;
+ opts->from_treeish = "HEAD";
+
+ if(repo_get_oid(the_repository, opts->from_treeish, &oid))
+ unborn_and_unspecified = 1;
+ }
+
/*
* Extract branch name from command line arguments, so
* all that is left is pathspecs.
@@ -1812,7 +1819,13 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
} else if (!opts->accept_ref && opts->from_treeish) {
struct object_id rev;
- if (repo_get_oid_mb(the_repository, opts->from_treeish, &rev))
+ /*
+ * when the branch is unborn and no revision is given, use
+ * empty tree as source
+ */
+ if(unborn_and_unspecified)
+ oidcpy(&rev, the_hash_algo->empty_tree);
+ else if (repo_get_oid_mb(the_repository, opts->from_treeish, &rev))
die(_("could not resolve %s"), opts->from_treeish);
setup_new_branch_info_and_source_tree(new_branch_info,
new file mode 100755
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='restore --staged should work on unborn branch'
+. ./test-lib.sh
+
+test_expect_success 'explicitly naming HEAD on unborn should fail' '
+ echo a >foo &&
+ echo b >bar &&
+ git add foo bar &&
+ test_must_fail git restore --staged --source=HEAD .
+'
+
+test_expect_success 'restore --staged .' '
+ rm .git/index &&
+ git add foo bar &&
+ git restore --staged . &&
+ git diff --cached --name-only >actual &&
+ test_must_be_empty actual
+'
+
+test_expect_success 'restore --staged $file' '
+ rm .git/index &&
+ git add foo bar &&
+ git restore --staged foo &&
+ git diff --cached --name-only >actual &&
+ echo bar >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'restore -p --staged' '
+ rm .git/index &&
+ git add foo bar &&
+ test_write_lines y n | git restore -p --staged >output &&
+ git diff --cached --name-only >actual &&
+ echo foo >expected &&
+ test_cmp expected actual &&
+ test_grep "Unstage" output
+'
+
+test_done
Some users expect that being on an unborn branch is similar to having an empty tree checked out. However, when running "git restore --staged ." on unborn branch having staged changes, the follwing error gets printed, fatal: could not resolve HEAD Therefore, teach "git restore --staged ." without a source option, to take empty tree as source on unborn branch. Note that, this assumption is already taken by "git reset" (166ec2e9). However, still disallow explicitly referring to HEAD on unborn branch. Signed-off-by: Ghanshyam Thakkar <shyamthakkar001@gmail.com> --- builtin/checkout.c | 27 +++++++++++++++++++------- t/t2073-restore-unborn.sh | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) create mode 100755 t/t2073-restore-unborn.sh