git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Phillip Wood <phillip.wood123@gmail.com>
To: brianmlyles@gmail.com, git@vger.kernel.org
Cc: me@ttaylorr.com, newren@gmail.com
Subject: Re: [PATCH 4/4] cherry-pick: Add `--empty` for more robust redundant commit handling
Date: Tue, 23 Jan 2024 14:25:43 +0000	[thread overview]
Message-ID: <b897771e-c60e-4e41-bfae-3bcfdd832be1@gmail.com> (raw)
In-Reply-To: <20240119060721.3734775-5-brianmlyles@gmail.com>

Hi Brian


On 19/01/2024 05:59, brianmlyles@gmail.com wrote:
> From: Brian Lyles <brianmlyles@gmail.com>
> 
> As with `git-rebase` and `git-am`, `git-cherry-pick` can result in a
> commit being made redundant if the content from the picked commit is
> already present in the target history. However, `git-cherry-pick` does
> not have the same options available that `git-rebase` and `git-am` have.
> 
> There are three things that can be done with these redundant commits:
> drop them, keep them, or have the cherry-pick stop and wait for the user
> to take an action. `git-rebase` has the `--empty` option added in commit
> e98c4269c8 (rebase (interactive-backend): fix handling of commits that
> become empty, 2020-02-15), which handles all three of these scenarios.
> Similarly, `git-am` got its own `--empty` in 7c096b8d61 (am: support
> --empty=<option> to handle empty patches, 2021-12-09).
> 
> `git-cherry-pick`, on the other hand, only supports two of the three
> possiblities: Keep the redundant commits via `--keep-redundant-commits`,
> or have the cherry-pick fail by not specifying that option. There is no
> way to automatically drop redundant commits.
> 
> In order to bring `git-cherry-pick` more in-line with `git-rebase` and
> `git-am`, this commit adds an `--empty` option to `git-cherry-pick`. It
> has the same three options (keep, drop, and stop), and largely behaves
> the same. The notable difference is that for `git-cherry-pick`, the
> default will be `stop`, which maintains the current behavior when the
> option is not specified.

Thanks for the well explained commit message

> The `--keep-redundant-commits` option will be documented as a deprecated
> synonym of `--empty=keep`, and will be supported for backwards
> compatibility for the time being.

I'm not sure if we need to deprecate it as in "it will be removed in the 
future" or just reduce it prominence in favor of --empty

> Signed-off-by: Brian Lyles <brianmlyles@gmail.com>
> ---
>   Documentation/git-cherry-pick.txt | 28 ++++++++++++++++++-------
>   builtin/revert.c                  | 35 ++++++++++++++++++++++++++++++-
>   sequencer.c                       |  6 ++++++
>   t/t3505-cherry-pick-empty.sh      | 26 ++++++++++++++++++++++-
>   4 files changed, 86 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
> index 806295a730..8c20a10d4b 100644
> --- a/Documentation/git-cherry-pick.txt
> +++ b/Documentation/git-cherry-pick.txt
> @@ -132,23 +132,37 @@ effect to your index in a row.
>   	keeps commits that were initially empty (i.e. the commit recorded the
>   	same tree as its parent).  Commits which are made empty due to a
>   	previous commit will cause the cherry-pick to fail.  To force the
> -	inclusion of those commits use `--keep-redundant-commits`.
> +	inclusion of those commits use `--empty=keep`.
>   
>   --allow-empty-message::
>   	By default, cherry-picking a commit with an empty message will fail.
>   	This option overrides that behavior, allowing commits with empty
>   	messages to be cherry picked.
>   
> ---keep-redundant-commits::
> -	If a commit being cherry picked duplicates a commit already in the
> -	current history, it will become empty.  By default these
> -	redundant commits cause `cherry-pick` to stop so the user can
> -	examine the commit. This option overrides that behavior and
> -	creates an empty commit object. Note that use of this option only
> +--empty=(stop|drop|keep)::
> +	How to handle commits being cherry-picked that are redundant with
> +	changes already in the current history.
> ++
> +--
> +`stop`;;

I'm still on the fence about "stop" vs "ask". I see in your tests you've 
accidentally used "ask" which makes me wonder if that is the more 
familiar term for users who probably use "git rebase" more often than 
"git am".

> +	The cherry-pick will stop when the empty commit is applied, allowing
> +	you to examine the commit. This is the default behavior.
> +`drop`;;
> +	The empty commit will be dropped.
> +`keep`;;
> +	The empty commit will be kept. Note that use of this option only
>   	results in an empty commit when the commit was not initially empty,
>   	but rather became empty due to a previous commit. Commits that were
>   	initially empty will cause the cherry-pick to fail. To force the
>   	inclusion of those commits use `--allow-empty`.
> +--
> ++
> +Note that commits which start empty will cause the cherry-pick to fail (unless
> +`--allow-empty` is specified).
> ++
> +
> +--keep-redundant-commits::
> +	Deprecated synonym for `--empty=keep`.
>   
>   --strategy=<strategy>::
>   	Use the given merge strategy.  Should only be used once.
> diff --git a/builtin/revert.c b/builtin/revert.c
> index b2cfde7a87..1491c45e26 100644
> --- a/builtin/revert.c
> +++ b/builtin/revert.c
> @@ -45,6 +45,30 @@ static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts)
>   	return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage;
>   }
>   
> +enum empty_action {
> +	STOP_ON_EMPTY_COMMIT = 0,  /* output errors and stop in the middle of a cherry-pick */
> +	DROP_EMPTY_COMMIT,         /* skip with a notice message */
> +	KEEP_EMPTY_COMMIT,         /* keep recording as empty commits */
> +};
> +
> +static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
> +{
> +	int *opt_value = opt->value;
> +
> +	BUG_ON_OPT_NEG(unset);
> +
> +	if (!strcmp(arg, "stop"))
> +		*opt_value = STOP_ON_EMPTY_COMMIT;
> +	else if (!strcmp(arg, "drop"))
> +		*opt_value = DROP_EMPTY_COMMIT;
> +	else if (!strcmp(arg, "keep"))
> +		*opt_value = KEEP_EMPTY_COMMIT;
> +	else
> +		return error(_("invalid value for '%s': '%s'"), "--empty", arg);
> +
> +	return 0;
> +}
> +
>   static int option_parse_m(const struct option *opt,
>   			  const char *arg, int unset)
>   {
> @@ -87,6 +111,7 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
>   	const char * const * usage_str = revert_or_cherry_pick_usage(opts);
>   	const char *me = action_name(opts);
>   	const char *cleanup_arg = NULL;
> +	enum empty_action empty_opt;
>   	int cmd = 0;
>   	struct option base_options[] = {
>   		OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
> @@ -116,7 +141,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
>   			OPT_BOOL(0, "ff", &opts->allow_ff, N_("allow fast-forward")),
>   			OPT_BOOL(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
>   			OPT_BOOL(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
> -			OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
> +			OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("deprecated: use --empty=keep instead")),
> +			OPT_CALLBACK_F(0, "empty", &empty_opt, "(stop|drop|keep)",
> +				       N_("how to handle commits that become empty"),
> +				       PARSE_OPT_NONEG, parse_opt_empty),
>   			OPT_END(),
>   		};
>   		options = parse_options_concat(options, cp_extra);
> @@ -136,6 +164,11 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
>   	prepare_repo_settings(the_repository);
>   	the_repository->settings.command_requires_full_index = 0;
>   
> +	if (opts->action == REPLAY_PICK) {
> +		opts->drop_redundant_commits = (empty_opt == DROP_EMPTY_COMMIT);
> +		opts->keep_redundant_commits = opts->keep_redundant_commits || (empty_opt == KEEP_EMPTY_COMMIT);
> +	}

The code changes look good but I think we want to update 
verify_opt_compatible() to check for "--empty" being combined with 
"--continue" etc. as well.

>   	if (cleanup_arg) {
>   		opts->default_msg_cleanup = get_cleanup_mode(cleanup_arg, 1);
>   		opts->explicit_cleanup = 1;
> diff --git a/sequencer.c b/sequencer.c
> index 582bde8d46..c49c27c795 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -2934,6 +2934,9 @@ static int populate_opts_cb(const char *key, const char *value,
>   	else if (!strcmp(key, "options.allow-empty-message"))
>   		opts->allow_empty_message =
>   			git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
> +	else if (!strcmp(key, "options.drop-redundant-commits"))
> +		opts->drop_redundant_commits =
> +			git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
>   	else if (!strcmp(key, "options.keep-redundant-commits"))
>   		opts->keep_redundant_commits =
>   			git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
> @@ -3478,6 +3481,9 @@ static int save_opts(struct replay_opts *opts)
>   	if (opts->allow_empty_message)
>   		res |= git_config_set_in_file_gently(opts_file,
>   				"options.allow-empty-message", "true");
> +	if (opts->drop_redundant_commits)
> +		res |= git_config_set_in_file_gently(opts_file,
> +				"options.drop-redundant-commits", "true");

It is good that we're saving the option - it would be good to add a test 
to check that we remember --empty after stopping for a conflict resolution.

>   	if (opts->keep_redundant_commits)
>   		res |= git_config_set_in_file_gently(opts_file,
>   				"options.keep-redundant-commits", "true");
> diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh
> index 6adfd25351..ae0cf7886a 100755
> --- a/t/t3505-cherry-pick-empty.sh
> +++ b/t/t3505-cherry-pick-empty.sh
> @@ -89,7 +89,7 @@ test_expect_success 'cherry-pick a commit that becomes no-op (prep)' '
>   	git commit -m "add file2 on the side"
>   '
>   
> -test_expect_success 'cherry-pick a no-op without --keep-redundant' '
> +test_expect_success 'cherry-pick a no-op with neither --keep-redundant nor --empty' '
>   	git reset --hard &&
>   	git checkout fork^0 &&
>   	test_must_fail git cherry-pick main
> @@ -104,4 +104,28 @@ test_expect_success 'cherry-pick a no-op with --keep-redundant' '
>   	test_cmp expect actual
>   '
>   
> +test_expect_success 'cherry-pick a no-op with --empty=ask' '
> +	git reset --hard &&
> +	git checkout fork^0 &&
> +	test_must_fail git cherry-pick --empty=ask main

This is an example of why it is a good idea to check the error message 
when using "test_must_fail" as here the test will fail due to a bad 
value passed to "--empty" rather than for the reason we want the test to 
check. It would be good to add a separate test to check that we reject 
invalid "--empty" values.

> +'
> +
> +test_expect_success 'cherry-pick a no-op with --empty=drop' '
> +	git reset --hard &&
> +	git checkout fork^0 &&
> +	git cherry-pick --empty=drop main &&
> +	git show -s --format=%s >actual &&
> +	echo "add file2 on the side" >expect &&
> +	test_cmp expect actual

I think you could simplify this by using test_commit_message

Best Wishes

Phillip



  parent reply	other threads:[~2024-01-23 14:26 UTC|newest]

Thread overview: 118+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-19  5:59 [PATCH 1/4] sequencer: Do not require `allow_empty` for redundant commit options brianmlyles
2024-01-19  5:59 ` [PATCH 2/4] docs: Clean up `--empty` formatting in `git-rebase` and `git-am` brianmlyles
2024-01-23 14:24   ` Phillip Wood
2024-01-27 21:22     ` Brian Lyles
2024-02-01 14:02       ` Phillip Wood
2024-01-19  5:59 ` [PATCH 3/4] rebase: Update `--empty=ask` to `--empty=drop` brianmlyles
2024-01-23 14:24   ` Phillip Wood
2024-01-27 21:49     ` Brian Lyles
2024-02-01 14:02       ` Phillip Wood
2024-01-19  5:59 ` [PATCH 4/4] cherry-pick: Add `--empty` for more robust redundant commit handling brianmlyles
2024-01-20 20:24   ` Kristoffer Haugsbakk
2024-01-21 18:28     ` Brian Lyles
2024-01-21 22:05       ` Kristoffer Haugsbakk
2024-01-21 22:41       ` Junio C Hamano
2024-01-22 10:40       ` Phillip Wood
2024-01-22 20:55       ` Kristoffer Haugsbakk
2024-01-23  5:23         ` Brian Lyles
2024-01-23  7:11           ` Kristoffer Haugsbakk
2024-01-23 17:32           ` Junio C Hamano
2024-01-23 18:41             ` Subject: [PATCH] CoC: whitespace fix Junio C Hamano
2024-01-24  3:06               ` Elijah Newren
2024-01-23 18:49             ` [PATCH 4/4] cherry-pick: Add `--empty` for more robust redundant commit handling Junio C Hamano
2024-01-23 14:25   ` Phillip Wood [this message]
2024-01-23 18:01     ` Junio C Hamano
2024-01-28  0:07       ` Brian Lyles
2024-01-27 23:56     ` Brian Lyles
2024-01-20 21:38 ` [PATCH 1/4] sequencer: Do not require `allow_empty` for redundant commit options Kristoffer Haugsbakk
2024-01-21 18:19   ` Brian Lyles
2024-01-23 14:23 ` Phillip Wood
2024-01-23 18:18   ` Junio C Hamano
2024-01-24 11:01   ` Phillip Wood
2024-01-24 11:01 ` Phillip Wood
2024-01-27 23:30   ` Brian Lyles
2024-01-28 16:36     ` Brian Lyles
2024-01-29 10:55       ` Phillip Wood
2024-02-10  5:50         ` Brian Lyles
2024-02-01 10:57     ` Phillip Wood
2024-02-10  4:34       ` Brian Lyles
2024-02-10  7:43 ` [PATCH v2 0/8] cherry-pick: add `--empty` Brian Lyles
2024-02-22 16:39   ` phillip.wood123
2024-02-10  7:43 ` [PATCH v2 1/8] docs: address inaccurate `--empty` default with `--exec` Brian Lyles
2024-02-10  7:43 ` [PATCH v2 2/8] docs: clean up `--empty` formatting in git-rebase(1) and git-am(1) Brian Lyles
2024-02-10  7:43 ` [PATCH v2 3/8] rebase: update `--empty=ask` to `--empty=drop` Brian Lyles
2024-02-11  4:54   ` Brian Lyles
2024-02-14 11:05     ` Phillip Wood
2024-02-22 16:34   ` phillip.wood123
2024-02-22 18:27     ` Junio C Hamano
2024-02-10  7:43 ` [PATCH v2 4/8] sequencer: treat error reading HEAD as unborn branch Brian Lyles
2024-02-22 16:34   ` phillip.wood123
2024-02-23  5:28     ` Brian Lyles
2024-02-25 16:57       ` phillip.wood123
2024-02-10  7:43 ` [PATCH v2 5/8] sequencer: do not require `allow_empty` for redundant commit options Brian Lyles
2024-02-22 16:35   ` phillip.wood123
2024-02-10  7:43 ` [PATCH v2 6/8] cherry-pick: decouple `--allow-empty` and `--keep-redundant-commits` Brian Lyles
2024-02-22 16:35   ` Phillip Wood
2024-02-22 18:41     ` Junio C Hamano
2024-02-10  7:43 ` [PATCH v2 7/8] cherry-pick: enforce `--keep-redundant-commits` incompatibility Brian Lyles
2024-02-22 16:35   ` Phillip Wood
2024-02-23  6:23     ` Brian Lyles
2024-02-23 17:41       ` Junio C Hamano
2024-02-25 16:58       ` phillip.wood123
2024-02-26  3:04         ` Brian Lyles
2024-02-10  7:43 ` [PATCH v2 8/8] cherry-pick: add `--empty` for more robust redundant commit handling Brian Lyles
2024-02-11 20:50   ` Jean-Noël AVILA
2024-02-12  1:35     ` Brian Lyles
2024-02-22 16:36   ` phillip.wood123
2024-02-23  6:58     ` Brian Lyles
2024-02-25 16:57       ` phillip.wood123
2024-02-26  2:21         ` Brian Lyles
2024-02-26  3:32         ` Brian Lyles
2024-02-27 10:39           ` phillip.wood123
2024-02-27 17:33             ` Junio C Hamano
2024-03-10 18:41 ` [PATCH v3 0/7] " Brian Lyles
2024-03-13 16:12   ` phillip.wood123
2024-03-10 18:42 ` [PATCH v3 1/7] docs: address inaccurate `--empty` default with `--exec` Brian Lyles
2024-03-10 18:42 ` [PATCH v3 2/7] docs: clean up `--empty` formatting in git-rebase(1) and git-am(1) Brian Lyles
2024-03-10 18:42 ` [PATCH v3 3/7] rebase: update `--empty=ask` to `--empty=stop` Brian Lyles
2024-03-10 18:42 ` [PATCH v3 4/7] sequencer: treat error reading HEAD as unborn branch Brian Lyles
2024-03-11  0:07   ` Junio C Hamano
2024-03-11 16:54     ` Junio C Hamano
2024-03-12  2:04       ` Brian Lyles
2024-03-12 22:25         ` Junio C Hamano
2024-03-16  3:05           ` Brian Lyles
2024-03-13 15:10   ` phillip.wood123
2024-03-16  3:07     ` Brian Lyles
2024-03-10 18:42 ` [PATCH v3 5/7] sequencer: do not require `allow_empty` for redundant commit options Brian Lyles
2024-03-10 18:42 ` [PATCH v3 6/7] cherry-pick: enforce `--keep-redundant-commits` incompatibility Brian Lyles
2024-03-10 18:42 ` [PATCH v3 7/7] cherry-pick: add `--empty` for more robust redundant commit handling Brian Lyles
2024-03-13 16:10   ` phillip.wood123
2024-03-13 17:17     ` Junio C Hamano
2024-03-16  5:20       ` Brian Lyles
2024-03-20 19:35         ` phillip.wood123
2024-03-20 23:36 ` [PATCH v4 0/7] " Brian Lyles
2024-03-25 14:38   ` phillip.wood123
2024-03-25 16:12     ` Brian Lyles
2024-03-25 19:36       ` phillip.wood123
2024-03-25 20:57         ` Junio C Hamano
2024-03-20 23:36 ` [PATCH v4 1/7] docs: address inaccurate `--empty` default with `--exec` Brian Lyles
2024-03-20 23:36 ` [PATCH v4 2/7] docs: clean up `--empty` formatting in git-rebase(1) and git-am(1) Brian Lyles
2024-03-20 23:36 ` [PATCH v4 3/7] rebase: update `--empty=ask` to `--empty=stop` Brian Lyles
2024-03-20 23:36 ` [PATCH v4 4/7] sequencer: handle unborn branch with `--allow-empty` Brian Lyles
2024-03-21  9:52   ` Dirk Gouders
2024-03-21 16:22     ` Junio C Hamano
2024-03-21 19:45       ` Dirk Gouders
2024-03-20 23:37 ` [PATCH v4 5/7] sequencer: do not require `allow_empty` for redundant commit options Brian Lyles
2024-03-20 23:37 ` [PATCH v4 6/7] cherry-pick: enforce `--keep-redundant-commits` incompatibility Brian Lyles
2024-03-20 23:37 ` [PATCH v4 7/7] cherry-pick: add `--empty` for more robust redundant commit handling Brian Lyles
2024-03-25 23:16 ` [PATCH v5 0/7] " Brian Lyles
2024-03-26 14:45   ` phillip.wood123
2024-03-26 18:28     ` Junio C Hamano
2024-03-27 16:37       ` phillip.wood123
2024-03-25 23:16 ` [PATCH v5 1/7] docs: address inaccurate `--empty` default with `--exec` Brian Lyles
2024-03-25 23:16 ` [PATCH v5 2/7] docs: clean up `--empty` formatting in git-rebase(1) and git-am(1) Brian Lyles
2024-03-25 23:16 ` [PATCH v5 3/7] rebase: update `--empty=ask` to `--empty=stop` Brian Lyles
2024-03-25 23:16 ` [PATCH v5 4/7] sequencer: handle unborn branch with `--allow-empty` Brian Lyles
2024-03-25 23:16 ` [PATCH v5 5/7] sequencer: do not require `allow_empty` for redundant commit options Brian Lyles
2024-03-25 23:16 ` [PATCH v5 6/7] cherry-pick: enforce `--keep-redundant-commits` incompatibility Brian Lyles
2024-03-25 23:16 ` [PATCH v5 7/7] cherry-pick: add `--empty` for more robust redundant commit handling Brian Lyles

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=b897771e-c60e-4e41-bfae-3bcfdd832be1@gmail.com \
    --to=phillip.wood123@gmail.com \
    --cc=brianmlyles@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=me@ttaylorr.com \
    --cc=newren@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    /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).