1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-10 13:06:07 +02:00

Merge branch 'dl/checkout-p-merge-base'

"git checkout -p A...B [-- <path>]" did not work, even though the
same command without "-p" correctly used the merge-base between
commits A and B.

* dl/checkout-p-merge-base:
  t2016: add a NEEDSWORK about the PERL prerequisite
  add-patch: add NEEDSWORK about comparing commits
  Doc: document "A...B" form for <tree-ish> in checkout and switch
  builtin/checkout: fix `git checkout -p HEAD...` bug
This commit is contained in:
Junio C Hamano 2020-10-27 15:09:50 -07:00
commit f3cfeb3078
7 changed files with 56 additions and 1 deletions

View File

@ -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.

View File

@ -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::

View File

@ -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

View File

@ -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);

View File

@ -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 --");

View File

@ -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^ &&

View File

@ -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 &&