From: Thomas Gummerer <t.gummerer@gmail.com>
To: Elijah Newren <newren@gmail.com>
Cc: "Git Mailing List" <git@vger.kernel.org>,
"Junio C Hamano" <gitster@pobox.com>,
"Nguyễn Thái Ngọc" <pclouds@gmail.com>
Subject: Re: [PATCH 6/8] checkout: add --cached option
Date: Tue, 11 Dec 2018 22:18:25 +0000 [thread overview]
Message-ID: <20181211221825.GS4883@hank.intra.tgummerer.com> (raw)
In-Reply-To: <CABPp-BEyRNniNFBuMMFXjvuSz9RtP6R7TeBAWDJO+Y70oe7CBA@mail.gmail.com>
On 12/10, Elijah Newren wrote:
> On Sun, Dec 9, 2018 at 12:05 PM Thomas Gummerer <t.gummerer@gmail.com> wrote:
> >
> > Add a new --cached option to git checkout, which works only on the
> > index, but not the working tree, similar to what 'git reset <tree-ish>
> > -- <pathspec>... does. Indeed the tests are adapted from the 'git
> > reset' tests.
> >
> > In the longer term the idea is to potentially deprecate 'git reset
> > <tree-ish> -- <pathspec>...', so the 'git reset' command becomes only
> > about re-pointing the HEAD, and not also about copying entries from
> > <tree-ish> to the index.
> >
> > Note that 'git checkout' by default works in overlay mode, meaning
> > files that match the pathspec that don't exist in <tree-ish>, but
> > exist in the index would not be removed. 'git checkout --no-overlay
> > --cached' can be used to get the same behaviour as 'git reset
> > <tree-ish> -- <pathspec>'.
>
> I think this argues _even more_ that --no-overlay should be the
> default. Your series is valuable even if we don't push on that, I'm
> just being noisy about what I think would be an even better world.
I think just having that mode in 'git restore-files' Duy is working on
may have to be enough for now.
> Also, I don't think I've mentioned it yet, but I'm really excited
> about this series and what you're doing. It's super cool. (Which I
> expected when I saw the description of the desired behavior, but I'm
> also liking and contemplating re-using some code...)
Thanks :)
> > One thing this patch doesn't currently deal with is conflicts.
> > Currently 'git checkout --{ours,theirs} -- <file-with-conflicts>'
> > doesn't do anything with the index, so the --cached option just
> > mirrors that behaviour. But given it doesn't even deal with
> > conflicts, the '--cached' option doesn't make much sense when no
> > <tree-ish> is given. As it operates only on the index, it's always a
> > no-op if no tree-ish is given.
> >
> > Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
> > ---
> >
> > Maybe we can just disallow --cached without <tree-ish> given for now,
> > and possibly later allow it with some different behaviour for
> > conflicts, not sure what the best way forward here is. We can also
> > just make it update the index as appropriate, and have it behave
> > different than 'git checkout' curerntly does when handling conflicts?
>
> Huh?
> "git checkout -- <path>"
> means update <path> from the index, meaning the index is left alone
> (it's the source) and only the working tree is touched.
>
> When you add a flag named --cached to only update the index and not
> the working tree, then the index becomes the sole destination.
>
> Now we combine: no tree is specified means the index is the source of
> the writing, and --cached being specified means the index is the sole
> destination of the writing. Thus, you have a no-op. If the user
> specifies --cached and no tree, you should immediately exit with a
> message along the lines of "Nothing to do; no tree given and --cached
> specified." The presence of conflicts seems completely irrelevant to
> me here.
Ah yeah you're right, thanks for a sanity check. The command I was
most worried about was 'git checkout --cached --{ours,theirs} -- <pathspec>',
which I thought should update the index. But as we don't give any
tree-ish, I'm not sure anymore it should. Maybe just always exiting
with the message you mention above is the right thing to do.
> > builtin/checkout.c | 26 ++++++++--
> > t/t2016-checkout-patch.sh | 8 +++
> > t/t2026-checkout-cached.sh | 103 +++++++++++++++++++++++++++++++++++++
> > t/t9902-completion.sh | 1 +
> > 4 files changed, 135 insertions(+), 3 deletions(-)
> > create mode 100755 t/t2026-checkout-cached.sh
> >
> > diff --git a/builtin/checkout.c b/builtin/checkout.c
> > index 0aef35bbc4..6ba85e9de5 100644
> > --- a/builtin/checkout.c
> > +++ b/builtin/checkout.c
> > @@ -45,6 +45,7 @@ struct checkout_opts {
> > int ignore_other_worktrees;
> > int show_progress;
> > int overlay_mode;
> > + int cached;
> > /*
> > * If new checkout options are added, skip_merge_working_tree
> > * should be updated accordingly.
> > @@ -288,6 +289,10 @@ static int checkout_paths(const struct checkout_opts *opts,
> > die(_("Cannot update paths and switch to branch '%s' at the same time."),
> > opts->new_branch);
> >
> > + if (opts->patch_mode && opts->cached)
> > + return run_add_interactive(revision, "--patch=reset",
> > + &opts->pathspec);
> > +
> > if (opts->patch_mode)
> > return run_add_interactive(revision, "--patch=checkout",
> > &opts->pathspec);
> > @@ -319,7 +324,9 @@ static int checkout_paths(const struct checkout_opts *opts,
> > * the current index, which means that it should
> > * be removed.
> > */
> > - ce->ce_flags |= CE_MATCHED | CE_REMOVE | CE_WT_REMOVE;
> > + ce->ce_flags |= CE_MATCHED | CE_REMOVE;
> > + if (!opts->cached)
> > + ce->ce_flags |= CE_WT_REMOVE;
> > continue;
> > } else {
> > /*
> > @@ -392,6 +399,9 @@ static int checkout_paths(const struct checkout_opts *opts,
> > for (pos = 0; pos < active_nr; pos++) {
> > struct cache_entry *ce = active_cache[pos];
> > if (ce->ce_flags & CE_MATCHED) {
> > + if (opts->cached) {
> > + continue;
> > + }
> > if (!ce_stage(ce)) {
> > errs |= checkout_entry(ce, &state, NULL);
> > continue;
> > @@ -571,6 +581,11 @@ static int skip_merge_working_tree(const struct checkout_opts *opts,
> > * not tested here
> > */
> >
> > + /*
> > + * opts->cached cannot be used with switching branches so is
> > + * not tested here
> > + */
> > +
> > /*
> > * If we aren't creating a new branch any changes or updates will
> > * happen in the existing branch. Since that could only be updating
> > @@ -1207,9 +1222,13 @@ static int checkout_branch(struct checkout_opts *opts,
> > die(_("'%s' cannot be used with switching branches"),
> > "--patch");
> >
> > - if (!opts->overlay_mode)
> > + if (opts->overlay_mode != -1)
> > + die(_("'%s' cannot be used with switching branches"),
> > + "--overlay/--no-overlay");
> > +
> > + if (opts->cached)
> > die(_("'%s' cannot be used with switching branches"),
> > - "--no-overlay");
> > + "--cached");
> >
> > if (opts->writeout_stage)
> > die(_("'%s' cannot be used with switching branches"),
> > @@ -1300,6 +1319,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
> > PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
> > OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
> > OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode")),
> > + OPT_BOOL(0, "cached", &opts.cached, N_("work on the index only")),
> > OPT_END(),
> > };
> >
> > diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh
> > index 47aeb0b167..e8774046e0 100755
> > --- a/t/t2016-checkout-patch.sh
> > +++ b/t/t2016-checkout-patch.sh
> > @@ -108,6 +108,14 @@ test_expect_success PERL 'path limiting works: foo inside dir' '
> > verify_state dir/foo head head
> > '
> >
> > +test_expect_success PERL 'git checkout --cached -p' '
> > + set_and_save_state dir/foo work work &&
> > + test_write_lines n y | git checkout --cached -p >output &&
> > + verify_state dir/foo work head &&
> > + verify_saved_state bar &&
> > + test_i18ngrep "Unstage" output
> > +'
> > +
> > test_expect_success PERL 'none of this moved HEAD' '
> > verify_saved_head
> > '
> > diff --git a/t/t2026-checkout-cached.sh b/t/t2026-checkout-cached.sh
> > new file mode 100755
> > index 0000000000..1b66192727
> > --- /dev/null
> > +++ b/t/t2026-checkout-cached.sh
> > @@ -0,0 +1,103 @@
> > +#!/bin/sh
> > +
> > +test_description='checkout --cached <pathspec>'
> > +
> > +. ./test-lib.sh
> > +
> > +test_expect_success 'checkout --cached <pathspec>' '
> > + echo 1 >file1 &&
> > + echo 2 >file2 &&
> > + git add file1 file2 &&
> > + test_tick &&
> > + git commit -m files &&
> > + git rm file2 &&
> > + echo 3 >file3 &&
> > + echo 4 >file1 &&
> > + git add file1 file3 &&
> > + git checkout --cached HEAD -- file1 file2 &&
> > + test_must_fail git diff --quiet &&
> > +
> > + cat >expect <<-\EOF &&
> > + diff --git a/file1 b/file1
> > + index d00491f..b8626c4 100644
> > + --- a/file1
> > + +++ b/file1
> > + @@ -1 +1 @@
> > + -1
> > + +4
> > + diff --git a/file2 b/file2
> > + deleted file mode 100644
> > + index 0cfbf08..0000000
> > + --- a/file2
> > + +++ /dev/null
> > + @@ -1 +0,0 @@
> > + -2
> > + EOF
> > + git diff >actual &&
> > + test_cmp expect actual &&
> > +
> > + cat >expect <<-\EOF &&
> > + diff --git a/file3 b/file3
> > + new file mode 100644
> > + index 0000000..00750ed
> > + --- /dev/null
> > + +++ b/file3
> > + @@ -0,0 +1 @@
> > + +3
> > + EOF
> > + git diff --cached >actual &&
> > + test_cmp expect actual
> > +'
> > +
> > +test_expect_success 'checking out an unmodified path is a no-op' '
> > + git reset --hard &&
> > + git checkout --cached HEAD -- file1 &&
> > + git diff-files --exit-code &&
> > + git diff-index --cached --exit-code HEAD
> > +'
> > +
> > +test_expect_success 'checking out specific path that is unmerged' '
> > + test_commit file3 file3 &&
> > + git rm --cached file2 &&
> > + echo 1234 >file2 &&
> > + F1=$(git rev-parse HEAD:file1) &&
> > + F2=$(git rev-parse HEAD:file2) &&
> > + F3=$(git rev-parse HEAD:file3) &&
> > + {
> > + echo "100644 $F1 1 file2" &&
> > + echo "100644 $F2 2 file2" &&
> > + echo "100644 $F3 3 file2"
> > + } | git update-index --index-info &&
> > + git ls-files -u &&
> > + git checkout --cached HEAD file2 &&
> > + test_must_fail git diff --quiet &&
> > + git diff-index --exit-code --cached HEAD
> > +'
> > +
> > +test_expect_success '--cached without --no-overlay does not remove entry from index' '
> > + test_must_fail git checkout --cached HEAD^ file3 &&
> > + git ls-files --error-unmatch -- file3
> > +'
> > +
> > +test_expect_success 'file is removed from the index with --no-overlay' '
> > + git checkout --cached --no-overlay HEAD^ file3 &&
> > + test_path_is_file file3 &&
> > + test_must_fail git ls-files --error-unmatch -- file3
> > +'
> > +
> > +test_expect_success 'test checkout --cached --no-overlay at given paths' '
> > + mkdir sub &&
> > + >sub/file1 &&
> > + >sub/file2 &&
> > + git update-index --add sub/file1 sub/file2 &&
> > + T=$(git write-tree) &&
> > + git checkout --cached --no-overlay HEAD sub/file2 &&
> > + test_must_fail git diff --quiet &&
> > + U=$(git write-tree) &&
>
> Do we need to worry at all about losing the exit status of write-tree
> in either invocation? In particular, if the second one for U fails
> somehow, we'd end up with $U being a blank string and we'd still
> probably get "$T" != "$U" below.
Hmm this seems to be a fairly common pattern in our test suite:
$ git grep -F '$(git write-tree)' t/* | wc -l
112
But maybe it's just something we used to do, but should move away
from. Just writing the output to a file shouldn't be much harder
either, I'll do that in the next iteration.
> You also had some rev-parse invocations hidden in a sub-shell in both
> this patch and patch 5, but subsequent commands relied on non-empty
> output out of those, so I figured those were fine. This one might be
> too, but I thought I'd at least mention it.
>
> > + echo "$T" &&
> > + echo "$U" &&
> > + test_must_fail git diff-index --cached --exit-code "$T" &&
> > + test "$T" != "$U"
> > +'
> > +
> > +test_done
> > diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> > index a3fd9a9630..cbc304ace8 100755
> > --- a/t/t9902-completion.sh
> > +++ b/t/t9902-completion.sh
> > @@ -1437,6 +1437,7 @@ test_expect_success 'double dash "git checkout"' '
> > --no-quiet Z
> > --no-... Z
> > --overlay Z
> > + --cached Z
> > EOF
> > '
> >
> > --
> > 2.20.0.405.gbc1bbc6f85
next prev parent reply other threads:[~2018-12-11 22:18 UTC|newest]
Thread overview: 115+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-09 20:04 [PATCH 0/8] introduce no-overlay and cached mode in git checkout Thomas Gummerer
2018-12-09 20:04 ` [PATCH 1/8] move worktree tests to t24* Thomas Gummerer
2018-12-10 3:48 ` Junio C Hamano
2018-12-10 15:32 ` Duy Nguyen
2018-12-11 21:50 ` Thomas Gummerer
2018-12-12 13:26 ` Eric Sunshine
2018-12-12 17:07 ` Duy Nguyen
2018-12-09 20:04 ` [PATCH 2/8] entry: factor out unlink_entry function Thomas Gummerer
2018-12-10 15:49 ` Duy Nguyen
2018-12-10 17:23 ` Elijah Newren
2018-12-10 17:27 ` Duy Nguyen
2018-12-11 2:23 ` Junio C Hamano
2018-12-20 13:36 ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 3/8] entry: support CE_WT_REMOVE flag in checkout_entry Thomas Gummerer
2018-12-10 15:58 ` Duy Nguyen
2018-12-11 2:28 ` Junio C Hamano
2018-12-12 6:16 ` Duy Nguyen
2018-12-12 7:36 ` Junio C Hamano
2018-12-10 17:49 ` Elijah Newren
2018-12-11 22:00 ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 4/8] read-cache: add invalidate parameter to remove_marked_cache_entries Thomas Gummerer
2018-12-10 16:08 ` Duy Nguyen
2018-12-10 18:09 ` Elijah Newren
2018-12-10 18:19 ` Duy Nguyen
2018-12-10 18:25 ` Elijah Newren
2018-12-10 18:33 ` Duy Nguyen
2018-12-10 18:47 ` Elijah Newren
2018-12-11 21:59 ` Thomas Gummerer
2018-12-11 2:42 ` Junio C Hamano
2018-12-09 20:04 ` [PATCH 5/8] checkout: introduce --{,no-}overlay option Thomas Gummerer
2018-12-10 16:42 ` Duy Nguyen
2018-12-11 22:42 ` Thomas Gummerer
2018-12-10 18:19 ` Elijah Newren
2018-12-11 3:07 ` Junio C Hamano
2018-12-11 6:04 ` Elijah Newren
2018-12-11 22:07 ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 6/8] checkout: add --cached option Thomas Gummerer
2018-12-10 16:49 ` Duy Nguyen
2018-12-11 3:13 ` Junio C Hamano
2018-12-11 6:12 ` Elijah Newren
2018-12-11 19:23 ` Duy Nguyen
2019-01-31 5:54 ` Duy Nguyen
2019-01-31 19:05 ` Junio C Hamano
2019-02-01 6:48 ` Duy Nguyen
2019-02-01 17:57 ` Junio C Hamano
2019-02-02 10:57 ` Duy Nguyen
2019-02-19 4:20 ` Duy Nguyen
2019-02-19 14:42 ` Elijah Newren
2019-02-19 14:57 ` Duy Nguyen
2019-02-19 19:07 ` Junio C Hamano
2019-02-19 22:24 ` Elijah Newren
2019-02-19 22:36 ` Junio C Hamano
2019-02-19 23:00 ` Elijah Newren
2019-02-20 1:53 ` Duy Nguyen
2019-02-19 19:02 ` Junio C Hamano
2019-02-19 19:10 ` Junio C Hamano
2019-02-19 22:04 ` Elijah Newren
2019-02-19 22:29 ` Junio C Hamano
2019-02-20 2:32 ` Duy Nguyen
2019-02-20 3:52 ` Duy Nguyen
2019-02-20 2:19 ` Duy Nguyen
2019-02-19 22:13 ` Elijah Newren
2019-02-19 22:33 ` Junio C Hamano
2018-12-10 18:42 ` Elijah Newren
2018-12-11 22:18 ` Thomas Gummerer [this message]
2018-12-09 20:04 ` [PATCH 7/8] checkout: allow ignoring unmatched pathspec Thomas Gummerer
2018-12-10 16:51 ` Duy Nguyen
2018-12-11 22:23 ` Thomas Gummerer
2018-12-10 20:25 ` Elijah Newren
2018-12-11 22:36 ` Thomas Gummerer
2018-12-09 20:04 ` [PATCH 8/8] stash: use git checkout --no-overlay Thomas Gummerer
2018-12-10 20:26 ` Elijah Newren
2018-12-10 3:47 ` [PATCH 0/8] introduce no-overlay and cached mode in git checkout Junio C Hamano
2018-12-20 8:43 ` Thomas Gummerer
2018-12-10 17:06 ` Duy Nguyen
2018-12-10 17:18 ` Elijah Newren
2018-12-10 18:37 ` Duy Nguyen
2018-12-11 22:52 ` Thomas Gummerer
2018-12-12 7:28 ` Junio C Hamano
2018-12-20 13:48 ` [PATCH v2 0/8] introduce no-overlay " Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 1/8] move worktree tests to t24* Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 2/8] entry: factor out unlink_entry function Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 3/8] entry: support CE_WT_REMOVE flag in checkout_entry Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 4/8] read-cache: add invalidate parameter to remove_marked_cache_entries Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 5/8] checkout: clarify comment Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 6/8] checkout: factor out mark_cache_entry_for_checkout function Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 7/8] checkout: introduce --{,no-}overlay option Thomas Gummerer
2018-12-23 8:05 ` Duy Nguyen
2018-12-23 9:44 ` Eric Sunshine
2019-01-06 18:18 ` Thomas Gummerer
2018-12-20 13:48 ` [PATCH v2 8/8] checkout: introduce checkout.overlayMode config Thomas Gummerer
2019-01-02 23:39 ` Junio C Hamano
2019-01-06 18:32 ` Thomas Gummerer
2019-01-07 17:00 ` Junio C Hamano
2019-01-08 21:52 ` [PATCH v3 0/8] introduce no-overlay mode in git checkout Thomas Gummerer
2019-01-08 21:52 ` [PATCH v3 1/8] move worktree tests to t24* Thomas Gummerer
2019-01-08 21:52 ` [PATCH v3 2/8] entry: factor out unlink_entry function Thomas Gummerer
2019-01-08 21:52 ` [PATCH v3 3/8] entry: support CE_WT_REMOVE flag in checkout_entry Thomas Gummerer
2019-01-08 21:52 ` [PATCH v3 4/8] read-cache: add invalidate parameter to remove_marked_cache_entries Thomas Gummerer
2019-01-08 21:52 ` [PATCH v3 5/8] checkout: clarify comment Thomas Gummerer
2019-01-08 21:52 ` [PATCH v3 6/8] checkout: factor out mark_cache_entry_for_checkout function Thomas Gummerer
2019-01-08 21:52 ` [PATCH v3 7/8] checkout: introduce --{,no-}overlay option Thomas Gummerer
2019-01-22 23:53 ` Jonathan Nieder
2019-01-23 19:05 ` Junio C Hamano
2019-01-23 20:21 ` Thomas Gummerer
2019-01-23 20:47 ` Jonathan Nieder
2019-01-24 22:08 ` Thomas Gummerer
2019-01-23 21:08 ` Junio C Hamano
2019-01-24 1:12 ` Jonathan Nieder
2019-01-24 22:02 ` Thomas Gummerer
2019-01-24 23:02 ` Junio C Hamano
2019-01-25 2:26 ` Jonathan Nieder
2019-01-25 9:24 ` Duy Nguyen
2019-02-09 18:54 ` Philip Oakley
2019-01-08 21:52 ` [PATCH v3 8/8] checkout: introduce checkout.overlayMode config Thomas Gummerer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181211221825.GS4883@hank.intra.tgummerer.com \
--to=t.gummerer@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=newren@gmail.com \
--cc=pclouds@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).