diff options
-rw-r--r-- | Documentation/git-checkout.txt | 4 | ||||
-rw-r--r-- | Documentation/git-restore.txt | 4 | ||||
-rw-r--r-- | add-patch.c | 8 | ||||
-rw-r--r-- | builtin/checkout.c | 15 | ||||
-rwxr-xr-x | git-add--interactive.perl | 7 | ||||
-rwxr-xr-x | t/t2016-checkout-patch.sh | 11 | ||||
-rwxr-xr-x | t/t2071-restore-patch.sh | 8 |
7 files changed, 56 insertions, 1 deletions
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index afa5c11fd3..6ae8bf8dee 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -351,6 +351,10 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. <tree-ish>:: Tree to checkout from (when paths are given). If not specified, the index will be used. ++ +As a special case, you may use `"A...B"` as a shortcut for the +merge base of `A` and `B` if there is exactly one merge base. You can +leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. \--:: Do not interpret any more arguments as options. diff --git a/Documentation/git-restore.txt b/Documentation/git-restore.txt index 84c6c40010..55bde91ef9 100644 --- a/Documentation/git-restore.txt +++ b/Documentation/git-restore.txt @@ -40,6 +40,10 @@ OPTIONS + If not specified, the contents are restored from `HEAD` if `--staged` is given, otherwise from the index. ++ +As a special case, you may use `"A...B"` as a shortcut for the +merge base of `A` and `B` if there is exactly one merge base. You can +leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. -p:: --patch:: diff --git a/add-patch.c b/add-patch.c index bd94bd3a7c..be4cf6e9e5 100644 --- a/add-patch.c +++ b/add-patch.c @@ -1695,6 +1695,14 @@ int run_add_p(struct repository *r, enum add_p_mode mode, if (mode == ADD_P_STASH) s.mode = &patch_mode_stash; else if (mode == ADD_P_RESET) { + /* + * NEEDSWORK: Instead of comparing to the literal "HEAD", + * compare the commit objects instead so that other ways of + * saying the same thing (such as "@") are also handled + * appropriately. + * + * This applies to the cases below too. + */ if (!revision || !strcmp(revision, "HEAD")) s.mode = &patch_mode_reset_head; else diff --git a/builtin/checkout.c b/builtin/checkout.c index 0951f8fee5..2e69ed24f2 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -471,6 +471,19 @@ static int checkout_paths(const struct checkout_opts *opts, if (opts->patch_mode) { const char *patch_mode; + const char *rev = new_branch_info->name; + char rev_oid[GIT_MAX_HEXSZ + 1]; + + /* + * Since rev can be in the form of `<a>...<b>` (which is not + * recognized by diff-index), we will always replace the name + * with the hex of the commit (whether it's in `...` form or + * not) for the run_add_interactive() machinery to work + * properly. However, there is special logic for the HEAD case + * so we mustn't replace that. + */ + if (rev && strcmp(rev, "HEAD")) + rev = oid_to_hex_r(rev_oid, &new_branch_info->commit->object.oid); if (opts->checkout_index && opts->checkout_worktree) patch_mode = "--patch=checkout"; @@ -481,7 +494,7 @@ static int checkout_paths(const struct checkout_opts *opts, else BUG("either flag must have been set, worktree=%d, index=%d", opts->checkout_worktree, opts->checkout_index); - return run_add_interactive(new_branch_info->name, patch_mode, &opts->pathspec); + return run_add_interactive(rev, patch_mode, &opts->pathspec); } repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR); diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 8a72018712..e713fe3d02 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -1830,6 +1830,13 @@ sub process_args { $arg = shift @ARGV or die __("missing --"); if ($arg ne '--') { $patch_mode_revision = $arg; + + # NEEDSWORK: Instead of comparing to the literal "HEAD", + # compare the commit objects instead so that other ways of + # saying the same thing (such as "@") are also handled + # appropriately. + # + # This applies to the cases below too. $patch_mode = ($arg eq 'HEAD' ? 'reset_head' : 'reset_nothead'); $arg = shift @ARGV or die __("missing --"); diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh index 47aeb0b167..d91a329eb3 100755 --- a/t/t2016-checkout-patch.sh +++ b/t/t2016-checkout-patch.sh @@ -18,6 +18,10 @@ test_expect_success PERL 'setup' ' # note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar' +# NEEDSWORK: Since the builtin add-p is used when $GIT_TEST_ADD_I_USE_BUILTIN +# is given, we should replace the PERL prerequisite with an ADD_I prerequisite +# which first checks if $GIT_TEST_ADD_I_USE_BUILTIN is defined before checking +# PERL. test_expect_success PERL 'saying "n" does nothing' ' set_and_save_state dir/foo work head && test_write_lines n n | git checkout -p && @@ -59,6 +63,13 @@ test_expect_success PERL 'git checkout -p HEAD with change already staged' ' verify_state dir/foo head head ' +test_expect_success PERL 'git checkout -p HEAD^...' ' + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git checkout -p HEAD^... && + verify_saved_state bar && + verify_state dir/foo parent parent +' + test_expect_success PERL 'git checkout -p HEAD^' ' # the third n is to get out in case it mistakenly does not apply test_write_lines n y n | git checkout -p HEAD^ && diff --git a/t/t2071-restore-patch.sh b/t/t2071-restore-patch.sh index 98b2476e7c..b5c5c0ff7e 100755 --- a/t/t2071-restore-patch.sh +++ b/t/t2071-restore-patch.sh @@ -60,6 +60,14 @@ test_expect_success PERL 'git restore -p --source=HEAD^' ' verify_state dir/foo parent index ' +test_expect_success PERL 'git restore -p --source=HEAD^...' ' + set_state dir/foo work index && + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git restore -p --source=HEAD^... && + verify_saved_state bar && + verify_state dir/foo parent index +' + test_expect_success PERL 'git restore -p handles deletion' ' set_state dir/foo work index && rm dir/foo && |