git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Phillip Wood <phillip.wood123@gmail.com>
To: Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>,
	git@vger.kernel.org
Cc: Johannes.Schindelin@gmx.de, phillip.wood@dunelm.org.uk,
	liu.denton@gmail.com, gitster@pobox.com, plroskin@gmail.com,
	alban.gruin@gmail.com, szeder.dev@gmail.com, jrnieder@gmail.com,
	emilyshaffer@google.com, Elijah Newren <newren@gmail.com>
Subject: Re: [PATCH v4 04/19] rebase (interactive-backend): fix handling of commits that become empty
Date: Mon, 10 Feb 2020 14:27:23 +0000	[thread overview]
Message-ID: <4da2874e-b96a-e81c-c2ac-4b3f06c9926d@gmail.com> (raw)
In-Reply-To: <c9542a2abe0da284c28f1c71566db8fc5c47c1a5.1579155273.git.gitgitgadget@gmail.com>

Hi Elijah

On 16/01/2020 06:14, Elijah Newren via GitGitGadget wrote:
> From: Elijah Newren <newren@gmail.com>
> 
> As established in the previous commit and commit b00bf1c9a8dd
> (git-rebase: make --allow-empty-message the default, 2018-06-27), the
> behavior for rebase with different backends in various edge or corner
> cases is often more happenstance than design.  This commit addresses
> another such corner case: commits which "become empty".
> 
> A careful reader may note that there are two types of commits which would
> become empty due to a rebase:
> 
>    * [clean cherry-pick] Commits which are clean cherry-picks of upstream
>      commits, as determined by `git log --cherry-mark ...`.  Re-applying
>      these commits would result in an empty set of changes and a
>      duplicative commit message; i.e. these are commits that have
>      "already been applied" upstream.
> 
>    * [become empty] Commits which are not empty to start, are not clean
>      cherry-picks of upstream commits, but which still become empty after
>      being rebased.  This happens e.g. when a commit has changes which
>      are a strict subset of the changes in an upstream commit, or when
>      the changes of a commit can be found spread across or among several
>      upstream commits.
> 
> Clearly, in both cases the changes in the commit in question are found
> upstream already, but the commit message may not be in the latter case.
> 
> When cherry-mark can determine a commit is already upstream, then
> because of how cherry-mark works this means the upstream commit message
> was about the *exact* same set of changes.  Thus, the commit messages
> can be assumed to be fully interchangeable (and are in fact likely to be
> completely identical).  As such, the clean cherry-pick case represents a
> case when there is no information to be gained by keeping the extra
> commit around.  All rebase types have always dropped these commits, and
> no one to my knowledge has ever requested that we do otherwise.
> 
> For many of the become empty cases (and likely even most), we will also
> be able to drop the commit without loss of information -- but this isn't
> quite always the case.  Since these commits represent cases that were
> not clean cherry-picks, there is no upstream commit message explaining
> the same set of changes.  Projects with good commit message hygiene will
> likely have the explanation from our commit message contained within or
> spread among the relevant upstream commits, but not all projects run
> that way.  As such, the commit message of the commit being rebased may
> have reasoning that suggests additional changes that should be made to
> adapt to the new base, or it may have information that someone wants to
> add as a note to another commit, or perhaps someone even wants to create
> an empty commit with the commit message as-is.
> 
> Junio commented on the "become-empty" types of commits as follows[1]:
> 
>      WRT a change that ends up being empty (as opposed to a change that
>      is empty from the beginning), I'd think that the current behaviour
>      is desireable one.  "am" based rebase is solely to transplant an
>      existing history and want to stop much less than "interactive" one
>      whose purpose is to polish a series before making it publishable,
>      and asking for confirmation ("this has become empty--do you want to
>      drop it?") is more appropriate from the workflow point of view.
> 
> [1] https://lore.kernel.org/git/xmqqfu1fswdh.fsf@gitster-ct.c.googlers.com/
> 
> I would simply add that his arguments for "am"-based rebases actually
> apply to all non-explicitly-interactive rebases.  Also, since we are
> stating that different cases should have different defaults, it may be
> worth providing a flag to allow users to select which behavior they want
> for these commits.
> 
> Introduce a new command line flag for selecting the desired behavior:
>      --empty={drop,keep,ask}
> with the definitions:
>      drop: drop commits which become empty
>      keep: keep commits which become empty
>      ask:  provide the user a chance to interact and pick what to do with
>            commits which become empty on a case-by-case basis
> 
> In line with Junio's suggestion, if the --empty flag is not specified,
> pick defaults as follows:
>      explicitly interactive: ask
>      otherwise: drop

Looking at the implementation there is a third option - if `--exec` is 
given without `-i` then the default is "keep". I'm not sure if having 
different defaults is convenient or confusing but don't feel that 
strongly about it. I've got a few minor comments below (the mains ones 
are saying which commit has been dropped and testing the default 
behavior when --empty is not given) but basically I like the new patch. 
Thanks for working on this, the commit message does a good job of 
explaining the changes.

> Signed-off-by: Elijah Newren <newren@gmail.com>
> ---
>   Documentation/git-rebase.txt | 27 ++++++++++++++++---
>   builtin/rebase.c             | 52 ++++++++++++++++++++++++++++++++++++
>   sequencer.c                  | 48 +++++++++++++++++++++++++--------
>   sequencer.h                  |  1 +
>   t/t3424-rebase-empty.sh      | 50 +++++++++++++++++++++++++++++-----
>   t/t3427-rebase-subtree.sh    |  8 +++---
>   6 files changed, 161 insertions(+), 25 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 1d19542d79..551a91d764 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -258,6 +258,22 @@ See also INCOMPATIBLE OPTIONS below.
>   	original branch. The index and working tree are also left
>   	unchanged as a result.
>   
> +--empty={drop,keep,ask}::
> +	How to handle commits that are not empty to start and are not
> +	clean cherry-picks of any upstream commit, but which become
> +	empty after rebasing (because they contain a subset of already
> +	upstream changes).  With drop (the default), commits that
> +	become empty are dropped.  With keep, such commits are kept.
> +	With ask (implied by --interactive), the rebase will halt when
> +	an empty commit is applied allowing you to choose whether to
> +	drop it, edit files more, or just commit the empty changes.

We should probably document the default for --exec without -i

> +Note that commits which start empty are kept, and commits which are
> +clean cherry-picks (as determined by `git log --cherry-mark ...`) are
> +always dropped.
> ++
> +See also INCOMPATIBLE OPTIONS below.
> +
>   --keep-empty::
>   	No-op.  Rebasing commits that started empty (had no change
>   	relative to their parent) used to fail and this option would
> @@ -561,6 +577,7 @@ are incompatible with the following options:
>    * --interactive
>    * --exec
>    * --keep-empty
> + * --empty=
>    * --edit-todo
>    * --root when used in combination with --onto
>   
> @@ -569,6 +586,7 @@ In addition, the following pairs of options are incompatible:
>    * --preserve-merges and --interactive
>    * --preserve-merges and --signoff
>    * --preserve-merges and --rebase-merges
> + * --preserve-merges and --empty=
>    * --keep-base and --onto
>    * --keep-base and --root
>   
> @@ -585,9 +603,12 @@ commits that started empty, though these are rare in practice.  It
>   also drops commits that become empty and has no option for controlling
>   this behavior.
>   
> -The interactive backend keeps intentionally empty commits.
> -Unfortunately, it always halts whenever it runs across a commit that
> -becomes empty, even when the rebase is not explicitly interactive.
> +The interactive backend keeps intentionally empty commits.  Similar to
> +the am backend, by default the interactive backend drops commits that
> +become empty unless -i/--interactive is specified (in which case it
> +stops and asks the user what to do).  The interactive backend also has
> +an --empty={drop,keep,ask} option for changing the behavior of
> +handling commits that become empty.
>   
>   Directory rename detection
>   ~~~~~~~~~~~~~~~~~~~~~~~~~~
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 537b3241ce..c299869e7b 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -50,8 +50,16 @@ enum rebase_type {
>   	REBASE_PRESERVE_MERGES
>   };
>   
> +enum empty_type {
> +	EMPTY_UNSPECIFIED = -1,
> +	EMPTY_DROP,
> +	EMPTY_KEEP,
> +	EMPTY_ASK
> +};
> +
>   struct rebase_options {
>   	enum rebase_type type;
> +	enum empty_type empty;
>   	const char *state_dir;
>   	struct commit *upstream;
>   	const char *upstream_name;
> @@ -91,6 +99,7 @@ struct rebase_options {
>   
>   #define REBASE_OPTIONS_INIT {			  	\
>   		.type = REBASE_UNSPECIFIED,	  	\
> +		.empty = EMPTY_UNSPECIFIED,	  	\
>   		.flags = REBASE_NO_QUIET, 		\
>   		.git_am_opts = ARGV_ARRAY_INIT,		\
>   		.git_format_patch_opt = STRBUF_INIT	\
> @@ -109,6 +118,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>   		replay.allow_rerere_auto = opts->allow_rerere_autoupdate;
>   	replay.allow_empty = 1;
>   	replay.allow_empty_message = opts->allow_empty_message;
> +	replay.drop_redundant_commits = (opts->empty == EMPTY_DROP);
> +	replay.keep_redundant_commits = (opts->empty == EMPTY_KEEP);
>   	replay.verbose = opts->flags & REBASE_VERBOSE;
>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
> @@ -444,6 +455,10 @@ static int parse_opt_keep_empty(const struct option *opt, const char *arg,
>   
>   	BUG_ON_OPT_ARG(arg);
>   
> +	/*
> +	 * If we ever want to remap --keep-empty to --empty=keep, insert:
> +	 * 	opts->empty = unset ? EMPTY_UNSPECIFIED : EMPTY_KEEP;
> +	 */
>   	opts->type = REBASE_INTERACTIVE;
>   	return 0;
>   }
> @@ -1350,6 +1365,29 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
>   	return 0;
>   }
>   
> +static enum empty_type parse_empty_value(const char *value)
> +{
> +	if (!strcasecmp(value, "drop"))
> +		return EMPTY_DROP;
> +	else if (!strcasecmp(value, "keep"))
> +		return EMPTY_KEEP;
> +	else if (!strcasecmp(value, "ask"))
> +		return EMPTY_ASK;
> +
> +	die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value);
> +}
> +
> +static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
> +{
> +	struct rebase_options *options = opt->value;
> +	enum empty_type value = parse_empty_value(arg);
> +
> +	BUG_ON_OPT_NEG(unset);
> +
> +	options->empty = value;
> +	return 0;
> +}
> +
>   static void NORETURN error_on_missing_default_upstream(void)
>   {
>   	struct branch *current_branch = branch_get(NULL);
> @@ -1494,6 +1532,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   				 "ignoring them"),
>   			      REBASE_PRESERVE_MERGES, PARSE_OPT_HIDDEN),
>   		OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
> +		OPT_CALLBACK_F(0, "empty", &options, N_("{drop,keep,ask}"),
> +			       N_("how to handle empty commits"),

Maybe we should say "how to handle commits that become empty" to 
distinguish them from commits that start empty which we always keep

> +			       PARSE_OPT_NONEG, parse_opt_empty),
>   		{ OPTION_CALLBACK, 'k', "keep-empty", &options, NULL,
>   			N_("(DEPRECATED) keep empty commits"),
>   			PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
> @@ -1760,6 +1801,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   	if (!(options.flags & REBASE_NO_QUIET))
>   		argv_array_push(&options.git_am_opts, "-q");
>   
> +	if (options.empty != EMPTY_UNSPECIFIED)
> +		imply_interactive(&options, "--empty");
> +
>   	if (gpg_sign) {
>   		free(options.gpg_sign_opt);
>   		options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
> @@ -1843,6 +1887,14 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>   		break;
>   	}
>   
> +	if (options.empty == EMPTY_UNSPECIFIED) {
> +		if (options.flags & REBASE_INTERACTIVE_EXPLICIT)
> +			options.empty = EMPTY_ASK;
> +		else if (exec.nr > 0)
> +			options.empty = EMPTY_KEEP;
> +		else
> +			options.empty = EMPTY_DROP;
> +	}
>   	if (reschedule_failed_exec > 0 && !is_interactive(&options))
>   		die(_("--reschedule-failed-exec requires "
>   		      "--exec or --interactive"));
> diff --git a/sequencer.c b/sequencer.c
> index c21fc202b1..354d0b5a38 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -158,6 +158,8 @@ static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
>   static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
>   static GIT_PATH_FUNC(rebase_path_allow_rerere_autoupdate, "rebase-merge/allow_rerere_autoupdate")
>   static GIT_PATH_FUNC(rebase_path_reschedule_failed_exec, "rebase-merge/reschedule-failed-exec")
> +static GIT_PATH_FUNC(rebase_path_drop_redundant_commits, "rebase-merge/drop_redundant_commits")
> +static GIT_PATH_FUNC(rebase_path_keep_redundant_commits, "rebase-merge/keep_redundant_commits")
>   
>   static int git_sequencer_config(const char *k, const char *v, void *cb)
>   {
> @@ -1483,7 +1485,11 @@ static int is_original_commit_empty(struct commit *commit)
>   }
>   
>   /*
> - * Do we run "git commit" with "--allow-empty"?
> + * Should empty commits be allowed?  Return status:
> + *    <0: Error in is_index_unchanged(r) or is_original_commit_empty(commit)
> + *     0: Halt on empty commit
> + *     1: Allow empty commit
> + *     2: Drop empty commit
>    */
>   static int allow_empty(struct repository *r,
>   		       struct replay_opts *opts,
> @@ -1492,14 +1498,17 @@ static int allow_empty(struct repository *r,
>   	int index_unchanged, originally_empty;
>   
>   	/*
> -	 * Three cases:
> +	 * Four cases:
>   	 *
>   	 * (1) we do not allow empty at all and error out.
>   	 *
> -	 * (2) we allow ones that were initially empty, but
> -	 * forbid the ones that become empty;
> +	 * (2) we allow ones that were initially empty, and
> +	 *     just drop the ones that become empty
>   	 *
> -	 * (3) we allow both.
> +	 * (3) we allow ones that were initially empty, but
> +	 *     halt for the ones that become empty;
> +	 *
> +	 * (4) we allow both.
>   	 */
>   	if (!opts->allow_empty)
>   		return 0; /* let "git commit" barf as necessary */
> @@ -1516,10 +1525,12 @@ static int allow_empty(struct repository *r,
>   	originally_empty = is_original_commit_empty(commit);
>   	if (originally_empty < 0)
>   		return originally_empty;
> -	if (!originally_empty)
> -		return 0;
> -	else
> +	if (originally_empty)
>   		return 1;
> +	else if (opts->drop_redundant_commits)
> +		return 2;
> +	else
> +		return 0;
>   }
>   
>   static struct {
> @@ -1730,7 +1741,7 @@ static int do_pick_commit(struct repository *r,
>   	char *author = NULL;
>   	struct commit_message msg = { NULL, NULL, NULL, NULL };
>   	struct strbuf msgbuf = STRBUF_INIT;
> -	int res, unborn = 0, reword = 0, allow;
> +	int res, unborn = 0, reword = 0, allow, drop_commit;
>   
>   	if (opts->no_commit) {
>   		/*
> @@ -1935,13 +1946,18 @@ static int do_pick_commit(struct repository *r,
>   		goto leave;
>   	}
>   
> +	drop_commit = 0;
>   	allow = allow_empty(r, opts, commit);
>   	if (allow < 0) {
>   		res = allow;
>   		goto leave;
> -	} else if (allow)
> +	} else if (allow == 1) {
>   		flags |= ALLOW_EMPTY;
> -	if (!opts->no_commit) {
> +	} else if (allow == 2) {
> +		drop_commit = 1;
> +		fprintf(stderr, _("No changes -- Patch already applied.\n"));

nit pick - usually messages start with a lowercase letter. Would it be 
helpful to explicitly state which commit is being dropped as well as 
why? Something like
   dropping <oid> <subject> - patch contents already upstream

> +	} // else allow == 0 and there's nothing special to do

We don't use // for comments

> +	if (!opts->no_commit && !drop_commit) {
>   		if (author || command == TODO_REVERT || (flags & AMEND_MSG))
>   			res = do_commit(r, msg_file, author, opts, flags);
>   		else
> @@ -2495,6 +2511,12 @@ static int read_populate_opts(struct replay_opts *opts)
>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>   			opts->reschedule_failed_exec = 1;
>   
> +		if (file_exists(rebase_path_drop_redundant_commits()))
> +			opts->drop_redundant_commits = 1;
> +
> +		if (file_exists(rebase_path_keep_redundant_commits()))
> +			opts->keep_redundant_commits = 1;
> +
>   		read_strategy_opts(opts, &buf);
>   		strbuf_release(&buf);
>   
> @@ -2574,6 +2596,10 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>   		write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
>   	if (opts->signoff)
>   		write_file(rebase_path_signoff(), "--signoff\n");
> +	if (opts->drop_redundant_commits)
> +		write_file(rebase_path_drop_redundant_commits(), "%s", "");
> +	if (opts->keep_redundant_commits)
> +		write_file(rebase_path_keep_redundant_commits(), "%s", "");
>   	if (opts->reschedule_failed_exec)
>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>   
> diff --git a/sequencer.h b/sequencer.h
> index c165e0ff25..3b0ab9141f 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -39,6 +39,7 @@ struct replay_opts {
>   	int allow_rerere_auto;
>   	int allow_empty;
>   	int allow_empty_message;
> +	int drop_redundant_commits;
>   	int keep_redundant_commits;
>   	int verbose;
>   	int quiet;
> diff --git a/t/t3424-rebase-empty.sh b/t/t3424-rebase-empty.sh
> index 22d97e143b..dcb4cb4751 100755
> --- a/t/t3424-rebase-empty.sh
> +++ b/t/t3424-rebase-empty.sh
> @@ -34,7 +34,7 @@ test_expect_success 'setup test repository' '
>   	git commit -m "Five letters ought to be enough for anybody"
>   '
>   
> -test_expect_failure 'rebase (am-backend) with a variety of empty commits' '
> +test_expect_failure 'rebase (am-backend)' '
>   	test_when_finished "git rebase --abort" &&
>   	git checkout -B testing localmods &&
>   	# rebase (--am) should not drop commits that start empty
> @@ -45,11 +45,29 @@ test_expect_failure 'rebase (am-backend) with a variety of empty commits' '
>   	test_cmp expect actual
>   '
>   
> -test_expect_failure 'rebase --merge with a variety of empty commits' '
> -	test_when_finished "git rebase --abort" &&
> +test_expect_success 'rebase --merge --empty=drop' '
>   	git checkout -B testing localmods &&
> -	# rebase --merge should not halt on the commit that becomes empty
> -	git rebase --merge upstream &&
> +	git rebase --merge --empty=drop upstream &&
> +
> +	test_write_lines D C B A >expect &&
> +	git log --format=%s >actual &&
> +	test_cmp expect actual
> +'
> +
> +test_expect_success 'rebase --merge --empty=keep' '
> +	git checkout -B testing localmods &&
> +	git rebase --merge --empty=keep upstream &&
> +
> +	test_write_lines D C2 C B A >expect &&
> +	git log --format=%s >actual &&
> +	test_cmp expect actual
> +'
> +
> +test_expect_success 'rebase --merge --empty=ask' '
> +	git checkout -B testing localmods &&
> +	test_must_fail git rebase --merge --empty=ask upstream &&
> +
> +	git rebase --skip &&
>   
>   	test_write_lines D C B A >expect &&
>   	git log --format=%s >actual &&
> @@ -58,9 +76,27 @@ test_expect_failure 'rebase --merge with a variety of empty commits' '
>   
>   GIT_SEQUENCE_EDITOR=: && export GIT_SEQUENCE_EDITOR
>   
> -test_expect_success 'rebase --interactive with a variety of empty commits' '
> +test_expect_success 'rebase --interactive --empty=drop' '
> +	git checkout -B testing localmods &&
> +	git rebase --interactive --empty=drop upstream &&
> +
> +	test_write_lines D C B A >expect &&
> +	git log --format=%s >actual &&
> +	test_cmp expect actual
> +'
> +
> +test_expect_success 'rebase --interactive --empty=keep' '
> +	git checkout -B testing localmods &&
> +	git rebase --interactive --empty=keep upstream &&
> +
> +	test_write_lines D C2 C B A >expect &&
> +	git log --format=%s >actual &&
> +	test_cmp expect actual
> +'
> +
> +test_expect_success 'rebase --interactive --empty=ask' '
>   	git checkout -B testing localmods &&
> -	test_must_fail git rebase --interactive upstream &&
> +	test_must_fail git rebase --interactive --empty=ask upstream &&
>   
>   	git rebase --skip &&

As the default if --empty is not given is supposed to vary depending on 
the other options given it would be good to test that I think

Best Wishes

Phillip

> diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh
> index 8dceef61cf..79e43a370b 100755
> --- a/t/t3427-rebase-subtree.sh
> +++ b/t/t3427-rebase-subtree.sh
> @@ -85,10 +85,10 @@ test_expect_failure REBASE_P 'Rebase -Xsubtree --keep-empty --preserve-merges --
>   	verbose test "$(commit_message HEAD)" = "Empty commit"
>   '
>   
> -test_expect_success 'Rebase -Xsubtree --onto commit' '
> +test_expect_success 'Rebase -Xsubtree --empty=ask --onto commit' '
>   	reset_rebase &&
>   	git checkout -b rebase-onto to-rebase &&
> -	test_must_fail git rebase -Xsubtree=files_subtree --onto files-master master &&
> +	test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --onto files-master master &&
>   	: first pick results in no changes &&
>   	git rebase --skip &&
>   	verbose test "$(commit_message HEAD~2)" = "master4" &&
> @@ -96,10 +96,10 @@ test_expect_success 'Rebase -Xsubtree --onto commit' '
>   	verbose test "$(commit_message HEAD)" = "Empty commit"
>   '
>   
> -test_expect_success 'Rebase -Xsubtree --rebase-merges --onto commit' '
> +test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit' '
>   	reset_rebase &&
>   	git checkout -b rebase-merges-onto to-rebase &&
> -	test_must_fail git rebase -Xsubtree=files_subtree --rebase-merges --onto files-master --root &&
> +	test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --rebase-merges --onto files-master --root &&
>   	: first pick results in no changes &&
>   	git rebase --skip &&
>   	verbose test "$(commit_message HEAD~2)" = "master4" &&
> 

  reply	other threads:[~2020-02-10 14:27 UTC|newest]

Thread overview: 161+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-20 17:09 [PATCH 00/15] rebase: make the default backend configurable Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 01/15] rebase: extend the options for handling of empty commits Elijah Newren via GitGitGadget
2019-12-20 21:29   ` Junio C Hamano
2019-12-21  0:32     ` Elijah Newren
2019-12-21 18:52       ` Elijah Newren
2019-12-21 23:49       ` Junio C Hamano
2019-12-20 17:09 ` [PATCH 02/15] t3406: simplify an already simple test Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 03/15] rebase, sequencer: remove the broken GIT_QUIET handling Elijah Newren via GitGitGadget
2019-12-20 21:34   ` Junio C Hamano
2019-12-20 17:09 ` [PATCH 04/15] rebase: make sure to pass along the quiet flag to the sequencer Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 05/15] rebase: fix handling of restrict_revision Elijah Newren via GitGitGadget
2019-12-20 21:37   ` Junio C Hamano
2019-12-20 17:09 ` [PATCH 06/15] t3432: make these tests work with either am or merge backends Elijah Newren via GitGitGadget
2019-12-22  5:11   ` Denton Liu
2019-12-23 17:17     ` Elijah Newren
2019-12-20 17:09 ` [PATCH 07/15] rebase: allow more types of rebases to fast-forward Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 08/15] git-rebase.txt: add more details about behavioral differences of backends Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 09/15] rebase: move incompatibility checks between backend options a bit earlier Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 10/15] rebase: add an --am option Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 11/15] contrib: change the prompt for am-based rebases Elijah Newren via GitGitGadget
2019-12-20 23:07   ` SZEDER Gábor
2019-12-21  0:17     ` Elijah Newren
2019-12-20 17:09 ` [PATCH 12/15] rebase tests: mark tests specific to the am-backend with --am Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 13/15] rebase tests: repeat some tests using the merge backend instead of am Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 14/15] rebase: make the backend configurable via config setting Elijah Newren via GitGitGadget
2019-12-20 17:09 ` [PATCH 15/15] rebase: change the default backend from "am" to "merge" Elijah Newren via GitGitGadget
2019-12-20 18:51 ` [PATCH 00/15] rebase: make the default backend configurable Alban Gruin
2019-12-20 18:55   ` Elijah Newren
2019-12-23 18:49 ` [PATCH v2 " Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 01/15] rebase: extend the options for handling of empty commits Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 02/15] t3406: simplify an already simple test Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 03/15] rebase, sequencer: remove the broken GIT_QUIET handling Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 04/15] rebase: make sure to pass along the quiet flag to the sequencer Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 05/15] rebase: fix handling of restrict_revision Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 06/15] t3432: make these tests work with either am or merge backends Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 07/15] rebase: allow more types of rebases to fast-forward Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 08/15] git-rebase.txt: add more details about behavioral differences of backends Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 09/15] rebase: move incompatibility checks between backend options a bit earlier Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 10/15] rebase: add an --am option Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 11/15] contrib: change the prompt for interactive-based rebases Elijah Newren via GitGitGadget
2019-12-23 22:00     ` Denton Liu
2019-12-23 18:49   ` [PATCH v2 12/15] rebase tests: mark tests specific to the am-backend with --am Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 13/15] rebase tests: repeat some tests using the merge backend instead of am Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 14/15] rebase: make the backend configurable via config setting Elijah Newren via GitGitGadget
2019-12-23 18:49   ` [PATCH v2 15/15] rebase: change the default backend from "am" to "merge" Elijah Newren via GitGitGadget
2019-12-24 19:54   ` [PATCH v3 00/15] rebase: make the default backend configurable Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 01/15] rebase: extend the options for handling of empty commits Elijah Newren via GitGitGadget
2020-01-07 14:37       ` Phillip Wood
2020-01-07 19:15         ` Elijah Newren
2020-01-08 14:27           ` Phillip Wood
2020-01-09 21:32             ` Johannes Schindelin
2019-12-24 19:54     ` [PATCH v3 02/15] t3406: simplify an already simple test Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 03/15] rebase, sequencer: remove the broken GIT_QUIET handling Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 04/15] rebase: make sure to pass along the quiet flag to the sequencer Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 05/15] rebase: fix handling of restrict_revision Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 06/15] t3432: make these tests work with either am or merge backends Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 07/15] rebase: allow more types of rebases to fast-forward Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 08/15] git-rebase.txt: add more details about behavioral differences of backends Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 09/15] rebase: move incompatibility checks between backend options a bit earlier Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 10/15] rebase: add an --am option Elijah Newren via GitGitGadget
2020-01-07 14:43       ` Phillip Wood
2020-01-07 19:26         ` Elijah Newren
2020-01-07 20:11           ` Junio C Hamano
2020-01-08 14:32             ` Phillip Wood
2020-01-08 17:18               ` Junio C Hamano
2020-01-08 18:55                 ` Phillip Wood
2019-12-24 19:54     ` [PATCH v3 11/15] git-prompt: change the prompt for interactive-based rebases Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 12/15] rebase tests: mark tests specific to the am-backend with --am Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 13/15] rebase tests: repeat some tests using the merge backend instead of am Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 14/15] rebase: make the backend configurable via config setting Elijah Newren via GitGitGadget
2019-12-24 19:54     ` [PATCH v3 15/15] rebase: change the default backend from "am" to "merge" Elijah Newren via GitGitGadget
2020-01-10 23:14       ` Jonathan Nieder
2020-01-11  1:16         ` Elijah Newren
2020-01-11 14:41           ` Phillip Wood
2020-01-12 17:59             ` Johannes Schindelin
2020-01-16  6:32               ` Elijah Newren
2020-01-16  7:58                 ` Jonathan Nieder
2020-01-16  8:06                   ` Jonathan Nieder
2020-01-16 16:18                     ` Elijah Newren
2020-01-16 20:35                       ` Jonathan Nieder
2020-01-16 21:30                         ` Elijah Newren
2020-01-16 22:39                           ` Jonathan Nieder
2020-01-16 23:19                             ` Elijah Newren
2020-01-16 23:25                           ` Junio C Hamano
2020-01-17  0:51                             ` Elijah Newren
2020-01-16 15:35                   ` Elijah Newren
2020-01-16 20:05                   ` Junio C Hamano
2020-01-16 10:48                 ` Johannes Schindelin
2020-01-12 21:23             ` Junio C Hamano
2020-01-15 19:50             ` Jonathan Nieder
2020-01-15 21:59               ` Emily Shaffer
2020-01-16  6:14     ` [PATCH v4 00/19] rebase: make the default backend configurable Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 01/19] git-rebase.txt: update description of --allow-empty-message Elijah Newren via GitGitGadget
2020-02-09 15:59         ` Phillip Wood
2020-02-13 18:35           ` Elijah Newren
2020-01-16  6:14       ` [PATCH v4 02/19] t3404: directly test the behavior of interest Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 03/19] rebase (interactive-backend): make --keep-empty the default Elijah Newren via GitGitGadget
2020-02-09 15:59         ` Phillip Wood
2020-02-13 18:52           ` Elijah Newren
2020-01-16  6:14       ` [PATCH v4 04/19] rebase (interactive-backend): fix handling of commits that become empty Elijah Newren via GitGitGadget
2020-02-10 14:27         ` Phillip Wood [this message]
2020-02-13 18:54           ` Elijah Newren
2020-02-16 14:46             ` Phillip Wood
2020-01-16  6:14       ` [PATCH v4 05/19] t3406: simplify an already simple test Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 06/19] rebase, sequencer: remove the broken GIT_QUIET handling Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 07/19] rebase: make sure to pass along the quiet flag to the sequencer Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 08/19] rebase: fix handling of restrict_revision Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 09/19] t3432: make these tests work with either am or merge backends Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 10/19] rebase: allow more types of rebases to fast-forward Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 11/19] git-rebase.txt: add more details about behavioral differences of backends Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 12/19] rebase: move incompatibility checks between backend options a bit earlier Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 13/19] rebase: add an --am option Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 14/19] git-prompt: change the prompt for interactive-based rebases Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 15/19] rebase: drop '-i' from the reflog " Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 16/19] rebase tests: mark tests specific to the am-backend with --am Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 17/19] rebase tests: repeat some tests using the merge backend instead of am Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 18/19] rebase: make the backend configurable via config setting Elijah Newren via GitGitGadget
2020-01-16  6:14       ` [PATCH v4 19/19] rebase: change the default backend from "am" to "merge" Elijah Newren via GitGitGadget
2020-01-17 16:58       ` [PATCH v4 00/19] rebase: make the default backend configurable Phillip Wood
2020-02-05 21:06         ` Junio C Hamano
2020-02-05 22:38           ` Elijah Newren
2020-02-15 21:36       ` [PATCH v5 00/20] rebase: make the default backend configurable and change the default Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 01/20] git-rebase.txt: update description of --allow-empty-message Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 02/20] t3404: directly test the behavior of interest Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 03/20] rebase (interactive-backend): make --keep-empty the default Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 04/20] rebase (interactive-backend): fix handling of commits that become empty Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 05/20] t3406: simplify an already simple test Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 06/20] rebase, sequencer: remove the broken GIT_QUIET handling Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 07/20] rebase: make sure to pass along the quiet flag to the sequencer Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 08/20] rebase: fix handling of restrict_revision Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 09/20] t3432: make these tests work with either am or merge backends Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 10/20] rebase: allow more types of rebases to fast-forward Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 11/20] git-rebase.txt: add more details about behavioral differences of backends Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 12/20] rebase: move incompatibility checks between backend options a bit earlier Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 13/20] rebase: add an --am option Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 14/20] git-prompt: change the prompt for interactive-based rebases Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 15/20] rebase: drop '-i' from the reflog " Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 16/20] rebase tests: mark tests specific to the am-backend with --am Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 17/20] rebase tests: repeat some tests using the merge backend instead of am Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 18/20] rebase: make the backend configurable via config setting Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 19/20] rebase: change the default backend from "am" to "merge" Elijah Newren via GitGitGadget
2020-02-15 21:36         ` [PATCH v5 20/20] rebase: rename the two primary rebase backends Elijah Newren via GitGitGadget
2020-03-12 15:13           ` Emily Shaffer
2020-03-12 16:33             ` Elijah Newren
2020-03-12 17:55               ` Jonathan Nieder
2020-03-12 18:39                 ` Elijah Newren
2020-03-12 18:46                   ` Jonathan Nieder
2020-03-12 19:31                     ` Elijah Newren
2020-03-17  2:58                       ` Jonathan Nieder
2020-03-17  4:45                         ` Elijah Newren
2020-03-12 19:54                     ` Junio C Hamano
2020-03-12 19:07               ` Junio C Hamano
2020-03-12 19:12                 ` Jonathan Nieder
2020-03-12 19:12               ` Junio C Hamano
2020-03-12 19:29                 ` Elijah Newren
2020-03-12 20:37                   ` Jeff King
2020-03-12 21:27                     ` Junio C Hamano
2020-03-12 22:06                       ` Elijah Newren
2020-03-13  0:04                         ` Junio C Hamano
2020-03-12 23:30                       ` Jonathan Nieder
2020-02-16 15:01         ` [PATCH v5 00/20] rebase: make the default backend configurable and change the default Phillip Wood

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

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4da2874e-b96a-e81c-c2ac-4b3f06c9926d@gmail.com \
    --to=phillip.wood123@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=alban.gruin@gmail.com \
    --cc=emilyshaffer@google.com \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=gitster@pobox.com \
    --cc=jrnieder@gmail.com \
    --cc=liu.denton@gmail.com \
    --cc=newren@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    --cc=plroskin@gmail.com \
    --cc=szeder.dev@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.
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 NNTP newsgroup(s).