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:
@ -351,6 +351,10 @@ leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
|
|||||||
<tree-ish>::
|
<tree-ish>::
|
||||||
Tree to checkout from (when paths are given). If not specified,
|
Tree to checkout from (when paths are given). If not specified,
|
||||||
the index will be used.
|
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.
|
Do not interpret any more arguments as options.
|
||||||
|
@ -40,6 +40,10 @@ OPTIONS
|
|||||||
+
|
+
|
||||||
If not specified, the contents are restored from `HEAD` if `--staged` is
|
If not specified, the contents are restored from `HEAD` if `--staged` is
|
||||||
given, otherwise from the index.
|
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::
|
-p::
|
||||||
--patch::
|
--patch::
|
||||||
|
@ -1695,6 +1695,14 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
|
|||||||
if (mode == ADD_P_STASH)
|
if (mode == ADD_P_STASH)
|
||||||
s.mode = &patch_mode_stash;
|
s.mode = &patch_mode_stash;
|
||||||
else if (mode == ADD_P_RESET) {
|
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"))
|
if (!revision || !strcmp(revision, "HEAD"))
|
||||||
s.mode = &patch_mode_reset_head;
|
s.mode = &patch_mode_reset_head;
|
||||||
else
|
else
|
||||||
|
@ -471,6 +471,19 @@ static int checkout_paths(const struct checkout_opts *opts,
|
|||||||
|
|
||||||
if (opts->patch_mode) {
|
if (opts->patch_mode) {
|
||||||
const char *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)
|
if (opts->checkout_index && opts->checkout_worktree)
|
||||||
patch_mode = "--patch=checkout";
|
patch_mode = "--patch=checkout";
|
||||||
@ -481,7 +494,7 @@ static int checkout_paths(const struct checkout_opts *opts,
|
|||||||
else
|
else
|
||||||
BUG("either flag must have been set, worktree=%d, index=%d",
|
BUG("either flag must have been set, worktree=%d, index=%d",
|
||||||
opts->checkout_worktree, opts->checkout_index);
|
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);
|
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
|
||||||
|
@ -1830,6 +1830,13 @@ sub process_args {
|
|||||||
$arg = shift @ARGV or die __("missing --");
|
$arg = shift @ARGV or die __("missing --");
|
||||||
if ($arg ne '--') {
|
if ($arg ne '--') {
|
||||||
$patch_mode_revision = $arg;
|
$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' ?
|
$patch_mode = ($arg eq 'HEAD' ?
|
||||||
'reset_head' : 'reset_nothead');
|
'reset_head' : 'reset_nothead');
|
||||||
$arg = shift @ARGV or die __("missing --");
|
$arg = shift @ARGV or die __("missing --");
|
||||||
|
@ -18,6 +18,10 @@ test_expect_success PERL 'setup' '
|
|||||||
|
|
||||||
# note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar'
|
# 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' '
|
test_expect_success PERL 'saying "n" does nothing' '
|
||||||
set_and_save_state dir/foo work head &&
|
set_and_save_state dir/foo work head &&
|
||||||
test_write_lines n n | git checkout -p &&
|
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
|
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^' '
|
test_expect_success PERL 'git checkout -p HEAD^' '
|
||||||
# the third n is to get out in case it mistakenly does not apply
|
# the third n is to get out in case it mistakenly does not apply
|
||||||
test_write_lines n y n | git checkout -p HEAD^ &&
|
test_write_lines n y n | git checkout -p HEAD^ &&
|
||||||
|
@ -60,6 +60,14 @@ test_expect_success PERL 'git restore -p --source=HEAD^' '
|
|||||||
verify_state dir/foo parent index
|
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' '
|
test_expect_success PERL 'git restore -p handles deletion' '
|
||||||
set_state dir/foo work index &&
|
set_state dir/foo work index &&
|
||||||
rm dir/foo &&
|
rm dir/foo &&
|
||||||
|
Reference in New Issue
Block a user