git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Elijah Newren <newren@gmail.com>
To: Thomas Gummerer <t.gummerer@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: Mon, 10 Dec 2018 10:42:44 -0800	[thread overview]
Message-ID: <CABPp-BEyRNniNFBuMMFXjvuSz9RtP6R7TeBAWDJO+Y70oe7CBA@mail.gmail.com> (raw)
In-Reply-To: <20181209200449.16342-7-t.gummerer@gmail.com>

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.

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

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

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

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

  parent reply	other threads:[~2018-12-10 18:43 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 [this message]
2018-12-11 22:18     ` Thomas Gummerer
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=CABPp-BEyRNniNFBuMMFXjvuSz9RtP6R7TeBAWDJO+Y70oe7CBA@mail.gmail.com \
    --to=newren@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=pclouds@gmail.com \
    --cc=t.gummerer@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).