git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] fixup ra/rebase-i-more-options
@ 2020-04-07 14:11 Phillip Wood
  2020-04-07 14:11 ` [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'"" Phillip Wood
                   ` (14 more replies)
  0 siblings, 15 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 14:11 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

The tests for ra/rebase-i-more-options were not as comprehensive as
they could have been and some of the tests that we did have didn't do
a good job of testing what they purported to. This series cleans up
the tests and fixes a couple of bugs (thanks to Jonathan Nieder for
reporting one of them). The bug fix reworks the code to try and make
it clearer.

I've opted to add some cleanup commits on top of Rohit's work rather
than reworking his patches. These are based on top of 4d924528d8
("Revert "Merge branch 'ra/rebase-i-more-options'"", 2020-01-12) there
are some conflicts when merging into pu. I had a quick look at the
conflicts and they appeared to be relatively straight forward to
resolve. If that impression is wrong let me know and I can rebase onto
master or try doing the merge myself and pushing it to github.

Phillip Wood (6):
  Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  t3433: remove loops from tests
  t3433: only compare commit dates
  rebase -i: fix --committer-date-is-author-date
  Revert "sequencer: allow callers of read_author_script() to ignore
    fields"
  t3433: improve coverage

 Documentation/git-rebase.txt            |  27 +++-
 builtin/rebase.c                        |  49 ++++--
 sequencer.c                             | 109 ++++++++++++-
 sequencer.h                             |   2 +
 t/t3422-rebase-incompatible-options.sh  |   2 -
 t/t3433-rebase-options-compatibility.sh | 201 ++++++++++++++++++++++++
 7 files changed, 368 insertions(+), 25 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

-- 
2.26.0


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
@ 2020-04-07 14:11 ` Phillip Wood
  2020-04-07 15:16   ` Elijah Newren
  2020-04-07 14:11 ` [PATCH 2/6] t3433: remove loops from tests Phillip Wood
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 14:11 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.

This is being reverted to enable some fixups for
ra/rebase-i-more-options to be built on this commit.
---
 Documentation/git-rebase.txt            |  27 ++++-
 builtin/rebase.c                        |  49 ++++++--
 sequencer.c                             | 141 ++++++++++++++++++++++--
 sequencer.h                             |   2 +
 t/t3422-rebase-incompatible-options.sh  |   2 -
 t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++
 7 files changed, 327 insertions(+), 28 deletions(-)
 create mode 100755 t/t3433-rebase-options-compatibility.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 0c4f038dd6..1d0e2d27cc 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -393,16 +393,31 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Behaves differently depending on which backend is selected.
++
+'am' backend: When applying a patch, ignore changes in whitespace in
+context lines if necessary.
++
+'interactive' backend: Treat lines with only whitespace changes as
+unchanged for the sake of a three-way merge.
+
 --whitespace=<option>::
-	These flag are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 +
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of recording the time the rebased commits are
+	created as the committer date, reuse the author date
+	as the committer date. This implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+--reset-author-date::
+	By default, the author date of the original commit is used
+	as the author date for the resulting commit.  This option
+	tells Git to use the current timestamp instead and implies
+	`--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -539,10 +554,7 @@ INCOMPATIBLE OPTIONS
 
 The following options:
 
- * --committer-date-is-author-date
- * --ignore-date
  * --whitespace
- * --ignore-whitespace
  * -C
 
 are incompatible with the following options:
@@ -565,6 +577,9 @@ 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 --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 8081741f8a..e354ec84bb 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -79,8 +79,11 @@ struct rebase_options {
 	int allow_rerere_autoupdate;
 	int keep_empty;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -99,6 +102,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	struct strbuf strategy_buf = STRBUF_INIT;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -112,10 +116,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.allow_empty_message = opts->allow_empty_message;
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
+	if (opts->ignore_whitespace)
+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
+	if (strategy_buf.len)
+		parse_strategy_opts(&replay, strategy_buf.buf);
+
+	strbuf_release(&strategy_buf);
 
 	if (opts->squash_onto) {
 		oidcpy(&replay.squash_onto, opts->squash_onto);
@@ -517,6 +531,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -970,6 +986,12 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1437,16 +1459,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1719,11 +1742,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
+	if (options.committer_date_is_author_date ||
+	    options.ignore_date)
+		options.flags |= REBASE_FORCE;
+
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			options.flags |= REBASE_FORCE;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index b9dbf1adb0..763ccbbc45 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -147,6 +147,8 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -823,9 +825,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 		error(_("missing 'GIT_AUTHOR_DATE'"));
 	if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 		goto finish;
-	*name = kv.items[name_i].util;
-	*email = kv.items[email_i].util;
-	*date = kv.items[date_i].util;
+
+	if (name)
+		*name = kv.items[name_i].util;
+	else
+		free(kv.items[name_i].util);
+	if (email)
+		*email = kv.items[email_i].util;
+	else
+		free(kv.items[email_i].util);
+	if (date)
+		*date = kv.items[date_i].util;
+	else
+		free(kv.items[date_i].util);
 	retval = 0;
 finish:
 	string_list_clear(&kv, !!retval);
@@ -868,6 +880,47 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+/* Returns a "date" string that needs to be free()'d by the caller */
+static char *read_author_date_or_null(void)
+{
+	char *date;
+
+	if (read_author_script(rebase_path_author_script(),
+			       NULL, NULL, &date, 0))
+		return NULL;
+	return date;
+}
+
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, len) < 0) {
+		error(_("malformed ident line"));
+		return NULL;
+	}
+	len = ident.mail_end - ident.name_begin + 1;
+
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
+static void push_dates(struct child_process *child, int change_committer_date)
+{
+	time_t now = time(NULL);
+	struct strbuf date = STRBUF_INIT;
+
+	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
+	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
+	if (change_committer_date)
+		argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
+	strbuf_release(&date);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -927,6 +980,25 @@ static int run_git_commit(struct repository *r,
 
 	cmd.git_cmd = 1;
 
+	if (opts->committer_date_is_author_date) {
+		int res = -1;
+		struct strbuf datebuf = STRBUF_INIT;
+		char *date = read_author_date_or_null();
+
+		if (!date)
+			return -1;
+
+		strbuf_addf(&datebuf, "@%s", date);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : datebuf.buf, 1);
+
+		strbuf_release(&datebuf);
+		free(date);
+
+		if (res)
+			return -1;
+	}
+
 	if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
 		const char *gpg_opt = gpg_sign_opt_quoted(opts);
 
@@ -942,6 +1014,8 @@ static int run_git_commit(struct repository *r,
 		argv_array_push(&cmd.args, "--amend");
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+	if (opts->ignore_date)
+		push_dates(&cmd, opts->committer_date_is_author_date);
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -1310,14 +1384,13 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
 
 	if (parse_head(r, &current_head))
 		return -1;
-
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
 		const char *out_enc = get_commit_output_encoding();
@@ -1332,7 +1405,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1345,6 +1418,31 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, len) < 0) {
+			res = error(_("malformed ident line"));
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -1404,6 +1502,15 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -1424,7 +1531,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
@@ -2492,6 +2599,16 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2574,6 +2691,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->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3514,6 +3635,8 @@ static int do_merge(struct repository *r,
 		argv_array_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
 			argv_array_push(&cmd.args, opts->gpg_sign);
+		if (opts->ignore_date)
+			push_dates(&cmd, opts->committer_date_is_author_date);
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
@@ -3786,7 +3909,9 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 9f9ae291e3..e9a0e03ea2 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -43,6 +43,8 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,8 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
new file mode 100755
index 0000000000..5166f158dd
--- /dev/null
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -0,0 +1,131 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
+
+	git checkout --orphan master &&
+	git rm --cached foo &&
+	rm foo &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with am backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase main side &&
+	git rebase --abort &&
+	git rebase --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with interactive backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--committer-date-is-author-date works with am backend' '
+	git commit --amend &&
+	git rebase --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with interactive backend' '
+	git commit --amend &&
+	git rebase -i --committer-date-is-author-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	git show HEAD --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	git rev-list HEAD >rev_list &&
+	while read HASH
+	do
+		git show $HASH --pretty="format:%ai" >authortime
+		git show $HASH --pretty="format:%ci" >committertime
+		test_cmp authortime committertime
+	done <rev_list
+'
+
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with am backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with interactive backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -i HEAD^ &&
+	git show HEAD --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	git rev-list HEAD >rev_list &&
+	while read HASH
+	do
+		git show $HASH --pretty="format:%ai" >authortime
+		grep "+0000" authortime
+	done <rev_list
+'
+
+test_done
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 2/6] t3433: remove loops from tests
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
  2020-04-07 14:11 ` [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'"" Phillip Wood
@ 2020-04-07 14:11 ` Phillip Wood
  2020-04-07 14:30   ` Elijah Newren
  2020-04-07 14:11 ` [PATCH 3/6] t3433: only compare commit dates Phillip Wood
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 14:11 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Looping inside a test is asking for trouble as we only detect any
failure on the last iteration. Instead get all the dates at once which
is also more efficient. Note the previous code accidentally compared the
diffs as well as the dates this is fixed as well.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 t/t3433-rebase-options-compatibility.sh | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 5166f158dd..2b4d75f1ef 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -90,13 +90,9 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
 	git rebase -r --root --committer-date-is-author-date &&
-	git rev-list HEAD >rev_list &&
-	while read HASH
-	do
-		git show $HASH --pretty="format:%ai" >authortime
-		git show $HASH --pretty="format:%ci" >committertime
-		test_cmp authortime committertime
-	done <rev_list
+	git log --pretty="format:%ai" >authortime &&
+	git log --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
 '
 
 # Checking for +0000 in author time is enough since default
@@ -120,12 +116,8 @@ test_expect_success '--ignore-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
 	git rebase -r --root --ignore-date &&
-	git rev-list HEAD >rev_list &&
-	while read HASH
-	do
-		git show $HASH --pretty="format:%ai" >authortime
-		grep "+0000" authortime
-	done <rev_list
+	git log --pretty=%ai >authortime &&
+	! grep -v "+0000" authortime
 '
 
 test_done
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 3/6] t3433: only compare commit dates
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
  2020-04-07 14:11 ` [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'"" Phillip Wood
  2020-04-07 14:11 ` [PATCH 2/6] t3433: remove loops from tests Phillip Wood
@ 2020-04-07 14:11 ` Phillip Wood
  2020-04-07 14:11 ` [PATCH 4/6] rebase -i: fix --committer-date-is-author-date Phillip Wood
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 14:11 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

`git show` shows the diff by default so these tests which are about
checking dates were also comparing the diffs. Fix that by switching to
`git log -1`

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 t/t3433-rebase-options-compatibility.sh | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 2b4d75f1ef..132f577fc9 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -73,16 +73,16 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 test_expect_success '--committer-date-is-author-date works with am backend' '
 	git commit --amend &&
 	git rebase --committer-date-is-author-date HEAD^ &&
-	git show HEAD --pretty="format:%ai" >authortime &&
-	git show HEAD --pretty="format:%ci" >committertime &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ci" >committertime &&
 	test_cmp authortime committertime
 '
 
 test_expect_success '--committer-date-is-author-date works with interactive backend' '
 	git commit --amend &&
 	git rebase -i --committer-date-is-author-date HEAD^ &&
-	git show HEAD --pretty="format:%ai" >authortime &&
-	git show HEAD --pretty="format:%ci" >committertime &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ci" >committertime &&
 	test_cmp authortime committertime
 '
 
@@ -101,14 +101,14 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '
 test_expect_success '--ignore-date works with am backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
 	git rebase --ignore-date HEAD^ &&
-	git show HEAD --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ai" >authortime &&
 	grep "+0000" authortime
 '
 
 test_expect_success '--ignore-date works with interactive backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
 	git rebase --ignore-date -i HEAD^ &&
-	git show HEAD --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ai" >authortime &&
 	grep "+0000" authortime
 '
 
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 4/6] rebase -i: fix --committer-date-is-author-date
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (2 preceding siblings ...)
  2020-04-07 14:11 ` [PATCH 3/6] t3433: only compare commit dates Phillip Wood
@ 2020-04-07 14:11 ` Phillip Wood
  2020-04-07 15:05   ` Elijah Newren
  2020-04-07 14:11 ` [PATCH 5/6] Revert "sequencer: allow callers of read_author_script() to ignore fields" Phillip Wood
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 14:11 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Johanathan Nieder reported that `rebase --committer-date-is-author-date`
failed with the error "invalid date format: @@2592000 +0000" when the
backend was switched to use the sequencer [1]. This is because when we
read the date from the author script file is already prefixed by '@' so
we do not need to add one. This did not show up in our tests
because once match_object_header_date() fails to match because of the
extra '@' parse_date_basic() strips the prefix and a date with more than
8 digits is parsed as a number of seconds by match_digit().

While fixing this I also noticed that we were not setting
GIT_COMMITTER_DATE in the environment when forking `git merge`. This was
untested. The tests we did have used commits where the author date was
the same as the current value $GIT_COMMITTER_DATE in the environment so
they did not test that we were actually using the author date when
creating the commit.

As we have already read GIT_AUTHOR_DATE into cmd.env_array we now use
that rather than re-reading the author-script file. I've moved the code
that handles opts->ignore date so that all the code setting the child
environment is together and changed it so we no longer set
GIT_COMMITTER_DATE twice when --ignore-date is combined with
--committer-date-is-author-date.

[1] https://lore.kernel.org/git/<20200110231436.GA24315@google.com>

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 sequencer.c                             | 68 ++++++++++---------------
 t/t3433-rebase-options-compatibility.sh | 29 +++++++++--
 2 files changed, 52 insertions(+), 45 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 763ccbbc45..56f6e49289 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -880,17 +880,6 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
-/* Returns a "date" string that needs to be free()'d by the caller */
-static char *read_author_date_or_null(void)
-{
-	char *date;
-
-	if (read_author_script(rebase_path_author_script(),
-			       NULL, NULL, &date, 0))
-		return NULL;
-	return date;
-}
-
 /* Construct a free()able author string with current time as the author date */
 static char *ignore_author_date(const char *author)
 {
@@ -909,16 +898,20 @@ static char *ignore_author_date(const char *author)
 	return strbuf_detach(&new_author, NULL);
 }
 
-static void push_dates(struct child_process *child, int change_committer_date)
+static const char *author_date_from_env_array(const struct argv_array *env)
 {
-	time_t now = time(NULL);
-	struct strbuf date = STRBUF_INIT;
+	int i;
+	const char *date;
 
-	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
-	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
-	if (change_committer_date)
-		argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
-	strbuf_release(&date);
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
 }
 
 static const char staged_changes_advice[] =
@@ -980,31 +973,19 @@ static int run_git_commit(struct repository *r,
 
 	cmd.git_cmd = 1;
 
-	if (opts->committer_date_is_author_date) {
-		int res = -1;
-		struct strbuf datebuf = STRBUF_INIT;
-		char *date = read_author_date_or_null();
-
-		if (!date)
-			return -1;
-
-		strbuf_addf(&datebuf, "@%s", date);
-		res = setenv("GIT_COMMITTER_DATE",
-			     opts->ignore_date ? "" : datebuf.buf, 1);
-
-		strbuf_release(&datebuf);
-		free(date);
-
-		if (res)
-			return -1;
-	}
-
 	if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
 		const char *gpg_opt = gpg_sign_opt_quoted(opts);
 
 		return error(_(staged_changes_advice),
 			     gpg_opt, gpg_opt);
 	}
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
+				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1014,8 +995,6 @@ static int run_git_commit(struct repository *r,
 		argv_array_push(&cmd.args, "--amend");
 	if (opts->gpg_sign)
 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
-	if (opts->ignore_date)
-		push_dates(&cmd, opts->committer_date_is_author_date);
 	if (defmsg)
 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 	else if (!(flags & EDIT_MSG))
@@ -3615,6 +3594,13 @@ static int do_merge(struct repository *r,
 			ret = error(_(staged_changes_advice), gpg_opt, gpg_opt);
 			goto leave_merge;
 		}
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
+					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3635,8 +3621,6 @@ static int do_merge(struct repository *r,
 		argv_array_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
 			argv_array_push(&cmd.args, opts->gpg_sign);
-		if (opts->ignore_date)
-			push_dates(&cmd, opts->committer_date_is_author_date);
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 132f577fc9..8247d01442 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -71,15 +71,15 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 '
 
 test_expect_success '--committer-date-is-author-date works with am backend' '
-	git commit --amend &&
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
 	git rebase --committer-date-is-author-date HEAD^ &&
 	git log -1 --pretty="format:%ai" >authortime &&
 	git log -1 --pretty="format:%ci" >committertime &&
 	test_cmp authortime committertime
 '
 
 test_expect_success '--committer-date-is-author-date works with interactive backend' '
-	git commit --amend &&
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
 	git rebase -i --committer-date-is-author-date HEAD^ &&
 	git log -1 --pretty="format:%ai" >authortime &&
 	git log -1 --pretty="format:%ci" >committertime &&
@@ -88,13 +88,36 @@ test_expect_success '--committer-date-is-author-date works with interactive back
 
 test_expect_success '--committer-date-is-author-date works with rebase -r' '
 	git checkout side &&
-	git merge --no-ff commit3 &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
 	git rebase -r --root --committer-date-is-author-date &&
 	git log --pretty="format:%ai" >authortime &&
 	git log --pretty="format:%ci" >committertime &&
 	test_cmp authortime committertime
 '
 
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
+	git log --pretty="format:%ai" >authortime &&
+	git log --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	git log -1 --format=%at HEAD >expect &&
+	test_must_fail git rebase -i --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -1 --format=%ct HEAD >actual &&
+	test_cmp expect actual
+'
+
 # Checking for +0000 in author time is enough since default
 # timezone is UTC, but the timezone used while committing
 # sets to +0530.
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 5/6] Revert "sequencer: allow callers of read_author_script() to ignore fields"
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (3 preceding siblings ...)
  2020-04-07 14:11 ` [PATCH 4/6] rebase -i: fix --committer-date-is-author-date Phillip Wood
@ 2020-04-07 14:11 ` Phillip Wood
  2020-04-07 15:06   ` Elijah Newren
  2020-04-07 14:11 ` [PATCH 6/6] t3433: improve coverage Phillip Wood
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 14:11 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

This reverts commit c068bcc59b4f16322a77b6a47b53d44b05c51fec.

This functionality is no longer used as since the last commit we always
want all of the fields returned.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 sequencer.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 56f6e49289..17c7b18245 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -825,19 +825,9 @@ int read_author_script(const char *path, char **name, char **email, char **date,
 		error(_("missing 'GIT_AUTHOR_DATE'"));
 	if (date_i < 0 || email_i < 0 || date_i < 0 || err)
 		goto finish;
-
-	if (name)
-		*name = kv.items[name_i].util;
-	else
-		free(kv.items[name_i].util);
-	if (email)
-		*email = kv.items[email_i].util;
-	else
-		free(kv.items[email_i].util);
-	if (date)
-		*date = kv.items[date_i].util;
-	else
-		free(kv.items[date_i].util);
+	*name = kv.items[name_i].util;
+	*email = kv.items[email_i].util;
+	*date = kv.items[date_i].util;
 	retval = 0;
 finish:
 	string_list_clear(&kv, !!retval);
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH 6/6] t3433: improve coverage
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (4 preceding siblings ...)
  2020-04-07 14:11 ` [PATCH 5/6] Revert "sequencer: allow callers of read_author_script() to ignore fields" Phillip Wood
@ 2020-04-07 14:11 ` Phillip Wood
  2020-04-07 15:13   ` Elijah Newren
  2020-04-07 15:17 ` [PATCH 0/6] fixup ra/rebase-i-more-options Elijah Newren
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 14:11 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Add tests to check --ignore-whitespace and --ignore-date are remembered
when running `rebase --continue` and to check
--committer-date-is-author-date with --ignore-date gives the expected
result.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 t/t3433-rebase-options-compatibility.sh | 55 +++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
index 8247d01442..a13c341301 100755
--- a/t/t3433-rebase-options-compatibility.sh
+++ b/t/t3433-rebase-options-compatibility.sh
@@ -7,6 +7,8 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . ./test-lib.sh
 
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
 GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
 export GIT_AUTHOR_DATE
 
@@ -70,6 +72,22 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
 	test_cmp expect file
 '
 
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" &&
+		export FAKE_LINES &&
+		git rebase -i --ignore-whitespace main side
+	) &&
+	git rebase --continue &&
+	test_cmp expect file
+'
+
 test_expect_success '--committer-date-is-author-date works with am backend' '
 	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
 	git rebase --committer-date-is-author-date HEAD^ &&
@@ -135,6 +153,16 @@ test_expect_success '--ignore-date works with interactive backend' '
 	grep "+0000" authortime
 '
 
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -i \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log --pretty=%ai >authortime &&
+	grep +0000 authortime
+'
+
 test_expect_success '--ignore-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
@@ -143,4 +171,31 @@ test_expect_success '--ignore-date works with rebase -r' '
 	! grep -v "+0000" authortime
 '
 
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -i --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -2 --pretty=%ai >authortime &&
+	git log -2 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	! grep -v "+0000" authortime
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		git rebase -i --strategy=resolve --ignore-date \
+		--committer-date-is-author-date side side &&
+	git log -1 --pretty=%ai >authortime &&
+	git log -1 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	grep "+0000" authortime
+ '
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
 test_done
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH 2/6] t3433: remove loops from tests
  2020-04-07 14:11 ` [PATCH 2/6] t3433: remove loops from tests Phillip Wood
@ 2020-04-07 14:30   ` Elijah Newren
  0 siblings, 0 replies; 130+ messages in thread
From: Elijah Newren @ 2020-04-07 14:30 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Looping inside a test is asking for trouble as we only detect any
> failure on the last iteration. Instead get all the dates at once which
> is also more efficient. Note the previous code accidentally compared the
> diffs as well as the dates this is fixed as well.

Add a semicolon between "dates" and "this" in the last sentence?

>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  t/t3433-rebase-options-compatibility.sh | 18 +++++-------------
>  1 file changed, 5 insertions(+), 13 deletions(-)
>
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index 5166f158dd..2b4d75f1ef 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -90,13 +90,9 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '
>         git checkout side &&
>         git merge --no-ff commit3 &&
>         git rebase -r --root --committer-date-is-author-date &&
> -       git rev-list HEAD >rev_list &&
> -       while read HASH
> -       do
> -               git show $HASH --pretty="format:%ai" >authortime
> -               git show $HASH --pretty="format:%ci" >committertime
> -               test_cmp authortime committertime
> -       done <rev_list
> +       git log --pretty="format:%ai" >authortime &&
> +       git log --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
>  '
>
>  # Checking for +0000 in author time is enough since default
> @@ -120,12 +116,8 @@ test_expect_success '--ignore-date works with rebase -r' '
>         git checkout side &&
>         git merge --no-ff commit3 &&
>         git rebase -r --root --ignore-date &&
> -       git rev-list HEAD >rev_list &&
> -       while read HASH
> -       do
> -               git show $HASH --pretty="format:%ai" >authortime
> -               grep "+0000" authortime
> -       done <rev_list
> +       git log --pretty=%ai >authortime &&
> +       ! grep -v "+0000" authortime
>  '

The new form is much more readable (and more correct and efficient, as
you point out).  Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 4/6] rebase -i: fix --committer-date-is-author-date
  2020-04-07 14:11 ` [PATCH 4/6] rebase -i: fix --committer-date-is-author-date Phillip Wood
@ 2020-04-07 15:05   ` Elijah Newren
  2020-04-07 18:11     ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Elijah Newren @ 2020-04-07 15:05 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Johanathan Nieder reported that `rebase --committer-date-is-author-date`
> failed with the error "invalid date format: @@2592000 +0000" when the
> backend was switched to use the sequencer [1]. This is because when we
> read the date from the author script file is already prefixed by '@' so
> we do not need to add one. This did not show up in our tests
> because once match_object_header_date() fails to match because of the
> extra '@' parse_date_basic() strips the prefix and a date with more than
> 8 digits is parsed as a number of seconds by match_digit().
>
> While fixing this I also noticed that we were not setting
> GIT_COMMITTER_DATE in the environment when forking `git merge`. This was
> untested. The tests we did have used commits where the author date was
> the same as the current value $GIT_COMMITTER_DATE in the environment so
> they did not test that we were actually using the author date when
> creating the commit.
>
> As we have already read GIT_AUTHOR_DATE into cmd.env_array we now use
> that rather than re-reading the author-script file. I've moved the code
> that handles opts->ignore date so that all the code setting the child
> environment is together and changed it so we no longer set
> GIT_COMMITTER_DATE twice when --ignore-date is combined with
> --committer-date-is-author-date.
>
> [1] https://lore.kernel.org/git/<20200110231436.GA24315@google.com>
>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  sequencer.c                             | 68 ++++++++++---------------
>  t/t3433-rebase-options-compatibility.sh | 29 +++++++++--
>  2 files changed, 52 insertions(+), 45 deletions(-)
>
> diff --git a/sequencer.c b/sequencer.c
> index 763ccbbc45..56f6e49289 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -880,17 +880,6 @@ static char *get_author(const char *message)
>         return NULL;
>  }
>
> -/* Returns a "date" string that needs to be free()'d by the caller */
> -static char *read_author_date_or_null(void)
> -{
> -       char *date;
> -
> -       if (read_author_script(rebase_path_author_script(),
> -                              NULL, NULL, &date, 0))
> -               return NULL;
> -       return date;
> -}
> -
>  /* Construct a free()able author string with current time as the author date */
>  static char *ignore_author_date(const char *author)
>  {
> @@ -909,16 +898,20 @@ static char *ignore_author_date(const char *author)
>         return strbuf_detach(&new_author, NULL);
>  }
>
> -static void push_dates(struct child_process *child, int change_committer_date)
> +static const char *author_date_from_env_array(const struct argv_array *env)
>  {
> -       time_t now = time(NULL);
> -       struct strbuf date = STRBUF_INIT;
> +       int i;
> +       const char *date;
>
> -       strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
> -       argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
> -       if (change_committer_date)
> -               argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
> -       strbuf_release(&date);
> +       for (i = 0; i < env->argc; i++)
> +               if (skip_prefix(env->argv[i],
> +                               "GIT_AUTHOR_DATE=", &date))
> +                       return date;

Is there any risk that GIT_AUTHOR_DATE=<somedate> will appear twice in
@child->env_array ?  If there is, should we read through the whole
list to make sure we take the last one?

> +       /*
> +        * If GIT_AUTHOR_DATE is missing we should have already errored out when
> +        * reading the script
> +        */
> +       BUG("GIT_AUTHOR_DATE missing from author script");
>  }
>
>  static const char staged_changes_advice[] =
> @@ -980,31 +973,19 @@ static int run_git_commit(struct repository *r,
>
>         cmd.git_cmd = 1;
>
> -       if (opts->committer_date_is_author_date) {
> -               int res = -1;
> -               struct strbuf datebuf = STRBUF_INIT;
> -               char *date = read_author_date_or_null();
> -
> -               if (!date)
> -                       return -1;
> -
> -               strbuf_addf(&datebuf, "@%s", date);
> -               res = setenv("GIT_COMMITTER_DATE",
> -                            opts->ignore_date ? "" : datebuf.buf, 1);
> -
> -               strbuf_release(&datebuf);
> -               free(date);
> -
> -               if (res)
> -                       return -1;
> -       }
> -
>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);
>
>                 return error(_(staged_changes_advice),
>                              gpg_opt, gpg_opt);
>         }
> +       if (opts->committer_date_is_author_date)
> +               argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +                                opts->ignore_date ?
> +                                "" :
> +                                author_date_from_env_array(&cmd.env_array));
> +       if (opts->ignore_date)
> +               argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>
>         argv_array_push(&cmd.args, "commit");
>
> @@ -1014,8 +995,6 @@ static int run_git_commit(struct repository *r,
>                 argv_array_push(&cmd.args, "--amend");
>         if (opts->gpg_sign)
>                 argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> -       if (opts->ignore_date)
> -               push_dates(&cmd, opts->committer_date_is_author_date);
>         if (defmsg)
>                 argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>         else if (!(flags & EDIT_MSG))
> @@ -3615,6 +3594,13 @@ static int do_merge(struct repository *r,
>                         ret = error(_(staged_changes_advice), gpg_opt, gpg_opt);
>                         goto leave_merge;
>                 }
> +               if (opts->committer_date_is_author_date)
> +                       argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +                                        opts->ignore_date ?
> +                                        "" :
> +                                        author_date_from_env_array(&cmd.env_array));
> +               if (opts->ignore_date)
> +                       argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>
>                 cmd.git_cmd = 1;
>                 argv_array_push(&cmd.args, "merge");
> @@ -3635,8 +3621,6 @@ static int do_merge(struct repository *r,
>                 argv_array_push(&cmd.args, git_path_merge_msg(r));
>                 if (opts->gpg_sign)
>                         argv_array_push(&cmd.args, opts->gpg_sign);
> -               if (opts->ignore_date)
> -                       push_dates(&cmd, opts->committer_date_is_author_date);
>
>                 /* Add the tips to be merged */
>                 for (j = to_merge; j; j = j->next)
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index 132f577fc9..8247d01442 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -71,15 +71,15 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>  '
>
>  test_expect_success '--committer-date-is-author-date works with am backend' '
> -       git commit --amend &&
> +       GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>         git rebase --committer-date-is-author-date HEAD^ &&
>         git log -1 --pretty="format:%ai" >authortime &&
>         git log -1 --pretty="format:%ci" >committertime &&
>         test_cmp authortime committertime
>  '
>
>  test_expect_success '--committer-date-is-author-date works with interactive backend' '
> -       git commit --amend &&
> +       GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>         git rebase -i --committer-date-is-author-date HEAD^ &&
>         git log -1 --pretty="format:%ai" >authortime &&
>         git log -1 --pretty="format:%ci" >committertime &&
> @@ -88,13 +88,36 @@ test_expect_success '--committer-date-is-author-date works with interactive back
>
>  test_expect_success '--committer-date-is-author-date works with rebase -r' '
>         git checkout side &&
> -       git merge --no-ff commit3 &&
> +       GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>         git rebase -r --root --committer-date-is-author-date &&
>         git log --pretty="format:%ai" >authortime &&
>         git log --pretty="format:%ci" >committertime &&
>         test_cmp authortime committertime
>  '
>
> +test_expect_success '--committer-date-is-author-date works when forking merge' '
> +       git checkout side &&
> +       GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +       git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
> +       git log --pretty="format:%ai" >authortime &&
> +       git log --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
> +
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
> +       git checkout commit2 &&
> +       GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
> +       git log -1 --format=%at HEAD >expect &&
> +       test_must_fail git rebase -i --committer-date-is-author-date \
> +               --onto HEAD^^ HEAD^ &&
> +       echo resolved > foo &&
> +       git add foo &&
> +       git rebase --continue &&
> +       git log -1 --format=%ct HEAD >actual &&
> +       test_cmp expect actual
> +'
> +
>  # Checking for +0000 in author time is enough since default
>  # timezone is UTC, but the timezone used while committing
>  # sets to +0530.
> --
> 2.26.0
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 5/6] Revert "sequencer: allow callers of read_author_script() to ignore fields"
  2020-04-07 14:11 ` [PATCH 5/6] Revert "sequencer: allow callers of read_author_script() to ignore fields" Phillip Wood
@ 2020-04-07 15:06   ` Elijah Newren
  0 siblings, 0 replies; 130+ messages in thread
From: Elijah Newren @ 2020-04-07 15:06 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> This reverts commit c068bcc59b4f16322a77b6a47b53d44b05c51fec.
>
> This functionality is no longer used as since the last commit we always
> want all of the fields returned.

That's a little hard to parse.  Maybe s/used as since/used; since/ ?

>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  sequencer.c | 16 +++-------------
>  1 file changed, 3 insertions(+), 13 deletions(-)
>
> diff --git a/sequencer.c b/sequencer.c
> index 56f6e49289..17c7b18245 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -825,19 +825,9 @@ int read_author_script(const char *path, char **name, char **email, char **date,
>                 error(_("missing 'GIT_AUTHOR_DATE'"));
>         if (date_i < 0 || email_i < 0 || date_i < 0 || err)
>                 goto finish;
> -
> -       if (name)
> -               *name = kv.items[name_i].util;
> -       else
> -               free(kv.items[name_i].util);
> -       if (email)
> -               *email = kv.items[email_i].util;
> -       else
> -               free(kv.items[email_i].util);
> -       if (date)
> -               *date = kv.items[date_i].util;
> -       else
> -               free(kv.items[date_i].util);
> +       *name = kv.items[name_i].util;
> +       *email = kv.items[email_i].util;
> +       *date = kv.items[date_i].util;
>         retval = 0;
>  finish:
>         string_list_clear(&kv, !!retval);
> --
> 2.26.0
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 6/6] t3433: improve coverage
  2020-04-07 14:11 ` [PATCH 6/6] t3433: improve coverage Phillip Wood
@ 2020-04-07 15:13   ` Elijah Newren
  2020-04-07 18:16     ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Elijah Newren @ 2020-04-07 15:13 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Add tests to check --ignore-whitespace and --ignore-date are remembered
> when running `rebase --continue` and to check
> --committer-date-is-author-date with --ignore-date gives the expected
> result.

Thanks for adding these.

>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  t/t3433-rebase-options-compatibility.sh | 55 +++++++++++++++++++++++++

t3433 is taken by t3433-rebase-across-mode-change.sh in upstream.
When you revert the reversion of Rohit's changes, perhaps you need to
rename his t3433 to some other file?

Also, the name "rebase-options-compatibility" suggest to me that it's
just checking whether certain options can be used together.  Perhaps
the --ignore-whitespace and --ignore-date tests you add should go
somewhere else?

>  1 file changed, 55 insertions(+)
>
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> index 8247d01442..a13c341301 100755
> --- a/t/t3433-rebase-options-compatibility.sh
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -7,6 +7,8 @@ test_description='tests to ensure compatibility between am and interactive backe
>
>  . ./test-lib.sh
>
> +. "$TEST_DIRECTORY"/lib-rebase.sh
> +
>  GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>  export GIT_AUTHOR_DATE
>
> @@ -70,6 +72,22 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>         test_cmp expect file
>  '
>
> +test_expect_success '--ignore-whitespace is remembered when continuing' '
> +       cat >expect <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       (
> +               set_fake_editor &&
> +               FAKE_LINES="break 1" &&
> +               export FAKE_LINES &&
> +               git rebase -i --ignore-whitespace main side
> +       ) &&
> +       git rebase --continue &&
> +       test_cmp expect file
> +'
> +
>  test_expect_success '--committer-date-is-author-date works with am backend' '
>         GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>         git rebase --committer-date-is-author-date HEAD^ &&
> @@ -135,6 +153,16 @@ test_expect_success '--ignore-date works with interactive backend' '
>         grep "+0000" authortime
>  '
>
> +test_expect_success '--ignore-date works after conflict resolution' '
> +       test_must_fail git rebase --ignore-date -i \
> +               --onto commit2^^ commit2^ commit2 &&

I don't see any todo list here; is there a reason you are using -i
instead of say -m?  (Similar question applies for the subsequent tests
you add below too?)

> +       echo resolved >foo &&
> +       git add foo &&
> +       git rebase --continue &&
> +       git log --pretty=%ai >authortime &&
> +       grep +0000 authortime
> +'
> +
>  test_expect_success '--ignore-date works with rebase -r' '
>         git checkout side &&
>         git merge --no-ff commit3 &&
> @@ -143,4 +171,31 @@ test_expect_success '--ignore-date works with rebase -r' '
>         ! grep -v "+0000" authortime
>  '
>
> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '
> +       test_must_fail git rebase -i --committer-date-is-author-date \
> +               --ignore-date --onto commit2^^ commit2^ commit3 &&
> +       git checkout --theirs foo &&
> +       git add foo &&
> +       git rebase --continue &&
> +       git log -2 --pretty=%ai >authortime &&
> +       git log -2 --pretty=%ci >committertime &&
> +       test_cmp authortime committertime &&
> +       ! grep -v "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
> +       GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
> +               git rebase -i --strategy=resolve --ignore-date \
> +               --committer-date-is-author-date side side &&
> +       git log -1 --pretty=%ai >authortime &&
> +       git log -1 --pretty=%ci >committertime &&
> +       test_cmp authortime committertime &&
> +       grep "+0000" authortime
> + '
> +
> +# This must be the last test in this file
> +test_expect_success '$EDITOR and friends are unchanged' '
> +       test_editor_unchanged
> +'
> +
>  test_done
> --
> 2.26.0
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-07 14:11 ` [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'"" Phillip Wood
@ 2020-04-07 15:16   ` Elijah Newren
  2020-04-07 18:01     ` Phillip Wood
  2020-04-07 21:04     ` Junio C Hamano
  0 siblings, 2 replies; 130+ messages in thread
From: Elijah Newren @ 2020-04-07 15:16 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.
>
> This is being reverted to enable some fixups for
> ra/rebase-i-more-options to be built on this commit.

This makes sense to me, but it will be only the second 'Revert
"Revert..."' commit in all of git.git and I'm curious if Junio will be
unhappy with it.

> ---
>  Documentation/git-rebase.txt            |  27 ++++-
>  builtin/rebase.c                        |  49 ++++++--
>  sequencer.c                             | 141 ++++++++++++++++++++++--
>  sequencer.h                             |   2 +
>  t/t3422-rebase-incompatible-options.sh  |   2 -
>  t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++
>  7 files changed, 327 insertions(+), 28 deletions(-)
>  create mode 100755 t/t3433-rebase-options-compatibility.sh
>
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 0c4f038dd6..1d0e2d27cc 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -393,16 +393,31 @@ your branch contains commits which were dropped, this option can be used
>  with `--keep-base` in order to drop those commits from your branch.
>
>  --ignore-whitespace::
> +       Behaves differently depending on which backend is selected.
> ++
> +'am' backend: When applying a patch, ignore changes in whitespace in
> +context lines if necessary.
> ++
> +'interactive' backend: Treat lines with only whitespace changes as
> +unchanged for the sake of a three-way merge.
> +
>  --whitespace=<option>::
> -       These flag are passed to the 'git apply' program
> +       This flag is passed to the 'git apply' program
>         (see linkgit:git-apply[1]) that applies the patch.
>  +
>  See also INCOMPATIBLE OPTIONS below.
>
>  --committer-date-is-author-date::
> +       Instead of recording the time the rebased commits are
> +       created as the committer date, reuse the author date
> +       as the committer date. This implies --force-rebase.
> +
>  --ignore-date::
> -       These flags are passed to 'git am' to easily change the dates
> -       of the rebased commits (see linkgit:git-am[1]).
> +--reset-author-date::
> +       By default, the author date of the original commit is used
> +       as the author date for the resulting commit.  This option
> +       tells Git to use the current timestamp instead and implies
> +       `--force-rebase`.
>  +
>  See also INCOMPATIBLE OPTIONS below.
>
> @@ -539,10 +554,7 @@ INCOMPATIBLE OPTIONS
>
>  The following options:
>
> - * --committer-date-is-author-date
> - * --ignore-date
>   * --whitespace
> - * --ignore-whitespace
>   * -C
>
>  are incompatible with the following options:
> @@ -565,6 +577,9 @@ 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 --ignore-whitespace
> + * --preserve-merges and --committer-date-is-author-date
> + * --preserve-merges and --ignore-date
>   * --keep-base and --onto
>   * --keep-base and --root
>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 8081741f8a..e354ec84bb 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -79,8 +79,11 @@ struct rebase_options {
>         int allow_rerere_autoupdate;
>         int keep_empty;
>         int autosquash;
> +       int ignore_whitespace;
>         char *gpg_sign_opt;
>         int autostash;
> +       int committer_date_is_author_date;
> +       int ignore_date;
>         char *cmd;
>         int allow_empty_message;
>         int rebase_merges, rebase_cousins;
> @@ -99,6 +102,7 @@ struct rebase_options {
>
>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  {
> +       struct strbuf strategy_buf = STRBUF_INIT;
>         struct replay_opts replay = REPLAY_OPTS_INIT;
>
>         replay.action = REPLAY_INTERACTIVE_REBASE;
> @@ -112,10 +116,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>         replay.allow_empty_message = opts->allow_empty_message;
>         replay.verbose = opts->flags & REBASE_VERBOSE;
>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +       replay.committer_date_is_author_date =
> +                                       opts->committer_date_is_author_date;
> +       replay.ignore_date = opts->ignore_date;
>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>         replay.strategy = opts->strategy;
> +
>         if (opts->strategy_opts)
> -               parse_strategy_opts(&replay, opts->strategy_opts);
> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);
> +       if (opts->ignore_whitespace)
> +               strbuf_addstr(&strategy_buf, " --ignore-space-change");
> +       if (strategy_buf.len)
> +               parse_strategy_opts(&replay, strategy_buf.buf);
> +
> +       strbuf_release(&strategy_buf);
>
>         if (opts->squash_onto) {
>                 oidcpy(&replay.squash_onto, opts->squash_onto);
> @@ -517,6 +531,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>         argc = parse_options(argc, argv, prefix, options,
>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>
> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
> +
>         if (!is_null_oid(&squash_onto))
>                 opts.squash_onto = &squash_onto;
>
> @@ -970,6 +986,12 @@ static int run_am(struct rebase_options *opts)
>         am.git_cmd = 1;
>         argv_array_push(&am.args, "am");
>
> +       if (opts->ignore_whitespace)
> +               argv_array_push(&am.args, "--ignore-whitespace");
> +       if (opts->committer_date_is_author_date)
> +               argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
> +       if (opts->ignore_date)
> +               argv_array_push(&opts->git_am_opts, "--ignore-date");
>         if (opts->action && !strcmp("continue", opts->action)) {
>                 argv_array_push(&am.args, "--resolved");
>                 argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1437,16 +1459,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>                 OPT_BOOL(0, "signoff", &options.signoff,
>                          N_("add a Signed-off-by: line to each commit")),
> -               OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -                                 NULL, N_("passed to 'git am'"),
> -                                 PARSE_OPT_NOARG),
> -               OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -                                 &options.git_am_opts, NULL,
> -                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
> -               OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
> -                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +               OPT_BOOL(0, "committer-date-is-author-date",
> +                        &options.committer_date_is_author_date,
> +                        N_("make committer date match author date")),
> +               OPT_BOOL(0, "reset-author-date", &options.ignore_date,
> +                        N_("ignore author date and use current date")),
> +               OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
> +                               N_("synonym of --reset-author-date")),
>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>                                   N_("passed to 'git apply'"), 0),
> +               OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> +                        N_("ignore changes in whitespace")),
>                 OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>                                   N_("action"), N_("passed to 'git apply'"), 0),
>                 OPT_BIT('f', "force-rebase", &options.flags,
> @@ -1719,11 +1742,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>                     state_dir_base, cmd_live_rebase, buf.buf);
>         }
>
> +       if (options.committer_date_is_author_date ||
> +           options.ignore_date)
> +               options.flags |= REBASE_FORCE;
> +
>         for (i = 0; i < options.git_am_opts.argc; i++) {
>                 const char *option = options.git_am_opts.argv[i], *p;
> -               if (!strcmp(option, "--committer-date-is-author-date") ||
> -                   !strcmp(option, "--ignore-date") ||
> -                   !strcmp(option, "--whitespace=fix") ||
> +               if (!strcmp(option, "--whitespace=fix") ||
>                     !strcmp(option, "--whitespace=strip"))
>                         options.flags |= REBASE_FORCE;
>                 else if (skip_prefix(option, "-C", &p)) {
> diff --git a/sequencer.c b/sequencer.c
> index b9dbf1adb0..763ccbbc45 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -147,6 +147,8 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   * command-line.
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -823,9 +825,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
>                 error(_("missing 'GIT_AUTHOR_DATE'"));
>         if (date_i < 0 || email_i < 0 || date_i < 0 || err)
>                 goto finish;
> -       *name = kv.items[name_i].util;
> -       *email = kv.items[email_i].util;
> -       *date = kv.items[date_i].util;
> +
> +       if (name)
> +               *name = kv.items[name_i].util;
> +       else
> +               free(kv.items[name_i].util);
> +       if (email)
> +               *email = kv.items[email_i].util;
> +       else
> +               free(kv.items[email_i].util);
> +       if (date)
> +               *date = kv.items[date_i].util;
> +       else
> +               free(kv.items[date_i].util);
>         retval = 0;
>  finish:
>         string_list_clear(&kv, !!retval);
> @@ -868,6 +880,47 @@ static char *get_author(const char *message)
>         return NULL;
>  }
>
> +/* Returns a "date" string that needs to be free()'d by the caller */
> +static char *read_author_date_or_null(void)
> +{
> +       char *date;
> +
> +       if (read_author_script(rebase_path_author_script(),
> +                              NULL, NULL, &date, 0))
> +               return NULL;
> +       return date;
> +}
> +
> +/* Construct a free()able author string with current time as the author date */
> +static char *ignore_author_date(const char *author)
> +{
> +       int len = strlen(author);
> +       struct ident_split ident;
> +       struct strbuf new_author = STRBUF_INIT;
> +
> +       if (split_ident_line(&ident, author, len) < 0) {
> +               error(_("malformed ident line"));
> +               return NULL;
> +       }
> +       len = ident.mail_end - ident.name_begin + 1;
> +
> +       strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
> +       datestamp(&new_author);
> +       return strbuf_detach(&new_author, NULL);
> +}
> +
> +static void push_dates(struct child_process *child, int change_committer_date)
> +{
> +       time_t now = time(NULL);
> +       struct strbuf date = STRBUF_INIT;
> +
> +       strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
> +       argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
> +       if (change_committer_date)
> +               argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
> +       strbuf_release(&date);
> +}
> +
>  static const char staged_changes_advice[] =
>  N_("you have staged changes in your working tree\n"
>  "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -927,6 +980,25 @@ static int run_git_commit(struct repository *r,
>
>         cmd.git_cmd = 1;
>
> +       if (opts->committer_date_is_author_date) {
> +               int res = -1;
> +               struct strbuf datebuf = STRBUF_INIT;
> +               char *date = read_author_date_or_null();
> +
> +               if (!date)
> +                       return -1;
> +
> +               strbuf_addf(&datebuf, "@%s", date);
> +               res = setenv("GIT_COMMITTER_DATE",
> +                            opts->ignore_date ? "" : datebuf.buf, 1);
> +
> +               strbuf_release(&datebuf);
> +               free(date);
> +
> +               if (res)
> +                       return -1;
> +       }
> +
>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);
>
> @@ -942,6 +1014,8 @@ static int run_git_commit(struct repository *r,
>                 argv_array_push(&cmd.args, "--amend");
>         if (opts->gpg_sign)
>                 argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
> +       if (opts->ignore_date)
> +               push_dates(&cmd, opts->committer_date_is_author_date);
>         if (defmsg)
>                 argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>         else if (!(flags & EDIT_MSG))
> @@ -1310,14 +1384,13 @@ static int try_to_commit(struct repository *r,
>         struct commit_extra_header *extra = NULL;
>         struct strbuf err = STRBUF_INIT;
>         struct strbuf commit_msg = STRBUF_INIT;
> -       char *amend_author = NULL;
> +       char *author_to_free = NULL;
>         const char *hook_commit = NULL;
>         enum commit_msg_cleanup_mode cleanup;
>         int res = 0;
>
>         if (parse_head(r, &current_head))
>                 return -1;
> -
>         if (flags & AMEND_MSG) {
>                 const char *exclude_gpgsig[] = { "gpgsig", NULL };
>                 const char *out_enc = get_commit_output_encoding();
> @@ -1332,7 +1405,7 @@ static int try_to_commit(struct repository *r,
>                         strbuf_addstr(msg, orig_message);
>                         hook_commit = "HEAD";
>                 }
> -               author = amend_author = get_author(message);
> +               author = author_to_free = get_author(message);
>                 unuse_commit_buffer(current_head, message);
>                 if (!author) {
>                         res = error(_("unable to parse commit author"));
> @@ -1345,6 +1418,31 @@ static int try_to_commit(struct repository *r,
>                 commit_list_insert(current_head, &parents);
>         }
>
> +       if (opts->committer_date_is_author_date) {
> +               int len = strlen(author);
> +               struct ident_split ident;
> +               struct strbuf date = STRBUF_INIT;
> +
> +               if (split_ident_line(&ident, author, len) < 0) {
> +                       res = error(_("malformed ident line"));
> +                       goto out;
> +               }
> +               if (!ident.date_begin) {
> +                       res = error(_("corrupted author without date information"));
> +                       goto out;
> +               }
> +
> +               strbuf_addf(&date, "@%.*s %.*s",
> +                           (int)(ident.date_end - ident.date_begin), ident.date_begin,
> +                           (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> +               res = setenv("GIT_COMMITTER_DATE",
> +                            opts->ignore_date ? "" : date.buf, 1);
> +               strbuf_release(&date);
> +
> +               if (res)
> +                       goto out;
> +       }
> +
>         if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>                 res = error(_("git write-tree failed to write a tree"));
>                 goto out;
> @@ -1404,6 +1502,15 @@ static int try_to_commit(struct repository *r,
>
>         reset_ident_date();
>
> +       if (opts->ignore_date) {
> +               author = ignore_author_date(author);
> +               if (!author) {
> +                       res = -1;
> +                       goto out;
> +               }
> +               free(author_to_free);
> +               author_to_free = (char *)author;
> +       }
>         if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>                                  oid, author, opts->gpg_sign, extra)) {
>                 res = error(_("failed to write commit object"));
> @@ -1424,7 +1531,7 @@ static int try_to_commit(struct repository *r,
>         free_commit_extra_headers(extra);
>         strbuf_release(&err);
>         strbuf_release(&commit_msg);
> -       free(amend_author);
> +       free(author_to_free);
>
>         return res;
>  }
> @@ -2492,6 +2599,16 @@ static int read_populate_opts(struct replay_opts *opts)
>                         opts->signoff = 1;
>                 }
>
> +               if (file_exists(rebase_path_cdate_is_adate())) {
> +                       opts->allow_ff = 0;
> +                       opts->committer_date_is_author_date = 1;
> +               }
> +
> +               if (file_exists(rebase_path_ignore_date())) {
> +                       opts->allow_ff = 0;
> +                       opts->ignore_date = 1;
> +               }
> +
>                 if (file_exists(rebase_path_reschedule_failed_exec()))
>                         opts->reschedule_failed_exec = 1;
>
> @@ -2574,6 +2691,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->committer_date_is_author_date)
> +               write_file(rebase_path_cdate_is_adate(), "%s", "");
> +       if (opts->ignore_date)
> +               write_file(rebase_path_ignore_date(), "%s", "");
>         if (opts->reschedule_failed_exec)
>                 write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>
> @@ -3514,6 +3635,8 @@ static int do_merge(struct repository *r,
>                 argv_array_push(&cmd.args, git_path_merge_msg(r));
>                 if (opts->gpg_sign)
>                         argv_array_push(&cmd.args, opts->gpg_sign);
> +               if (opts->ignore_date)
> +                       push_dates(&cmd, opts->committer_date_is_author_date);
>
>                 /* Add the tips to be merged */
>                 for (j = to_merge; j; j = j->next)
> @@ -3786,7 +3909,9 @@ static int pick_commits(struct repository *r,
>         setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>         if (opts->allow_ff)
>                 assert(!(opts->signoff || opts->no_commit ||
> -                               opts->record_origin || opts->edit));
> +                               opts->record_origin || opts->edit ||
> +                               opts->committer_date_is_author_date ||
> +                               opts->ignore_date));
>         if (read_and_refresh_cache(r, opts))
>                 return -1;
>
> diff --git a/sequencer.h b/sequencer.h
> index 9f9ae291e3..e9a0e03ea2 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -43,6 +43,8 @@ struct replay_opts {
>         int verbose;
>         int quiet;
>         int reschedule_failed_exec;
> +       int committer_date_is_author_date;
> +       int ignore_date;
>
>         int mainline;
>
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 50e7960702..c8234062c6 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,8 +61,6 @@ test_rebase_am_only () {
>  }
>
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
> -test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>
>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
> new file mode 100755
> index 0000000000..5166f158dd
> --- /dev/null
> +++ b/t/t3433-rebase-options-compatibility.sh
> @@ -0,0 +1,131 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2019 Rohit Ashiwal
> +#
> +
> +test_description='tests to ensure compatibility between am and interactive backends'
> +
> +. ./test-lib.sh
> +
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
> +# This is a special case in which both am and interactive backends
> +# provide the same output. It was done intentionally because
> +# both the backends fall short of optimal behaviour.
> +test_expect_success 'setup' '
> +       git checkout -b topic &&
> +       q_to_tab >file <<-\EOF &&
> +       line 1
> +       Qline 2
> +       line 3
> +       EOF
> +       git add file &&
> +       git commit -m "add file" &&
> +       cat >file <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       git commit -am "update file" &&
> +       git tag side &&
> +       test_commit commit1 foo foo1 &&
> +       test_commit commit2 foo foo2 &&
> +       test_commit commit3 foo foo3 &&
> +
> +       git checkout --orphan master &&
> +       git rm --cached foo &&
> +       rm foo &&
> +       sed -e "s/^|//" >file <<-\EOF &&
> +       |line 1
> +       |        line 2
> +       |line 3
> +       EOF
> +       git add file &&
> +       git commit -m "add file" &&
> +       git tag main
> +'
> +
> +test_expect_success '--ignore-whitespace works with am backend' '
> +       cat >expect <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       test_must_fail git rebase main side &&
> +       git rebase --abort &&
> +       git rebase --ignore-whitespace main side &&
> +       test_cmp expect file
> +'
> +
> +test_expect_success '--ignore-whitespace works with interactive backend' '
> +       cat >expect <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       test_must_fail git rebase --merge main side &&
> +       git rebase --abort &&
> +       git rebase --merge --ignore-whitespace main side &&
> +       test_cmp expect file
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with am backend' '
> +       git commit --amend &&
> +       git rebase --committer-date-is-author-date HEAD^ &&
> +       git show HEAD --pretty="format:%ai" >authortime &&
> +       git show HEAD --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with interactive backend' '
> +       git commit --amend &&
> +       git rebase -i --committer-date-is-author-date HEAD^ &&
> +       git show HEAD --pretty="format:%ai" >authortime &&
> +       git show HEAD --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
> +       git checkout side &&
> +       git merge --no-ff commit3 &&
> +       git rebase -r --root --committer-date-is-author-date &&
> +       git rev-list HEAD >rev_list &&
> +       while read HASH
> +       do
> +               git show $HASH --pretty="format:%ai" >authortime
> +               git show $HASH --pretty="format:%ci" >committertime
> +               test_cmp authortime committertime
> +       done <rev_list
> +'
> +
> +# Checking for +0000 in author time is enough since default
> +# timezone is UTC, but the timezone used while committing
> +# sets to +0530.
> +test_expect_success '--ignore-date works with am backend' '
> +       git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +       git rebase --ignore-date HEAD^ &&
> +       git show HEAD --pretty="format:%ai" >authortime &&
> +       grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works with interactive backend' '
> +       git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +       git rebase --ignore-date -i HEAD^ &&
> +       git show HEAD --pretty="format:%ai" >authortime &&
> +       grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works with rebase -r' '
> +       git checkout side &&
> +       git merge --no-ff commit3 &&
> +       git rebase -r --root --ignore-date &&
> +       git rev-list HEAD >rev_list &&
> +       while read HASH
> +       do
> +               git show $HASH --pretty="format:%ai" >authortime
> +               grep "+0000" authortime
> +       done <rev_list
> +'
> +
> +test_done
> --
> 2.26.0
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 0/6] fixup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (5 preceding siblings ...)
  2020-04-07 14:11 ` [PATCH 6/6] t3433: improve coverage Phillip Wood
@ 2020-04-07 15:17 ` Elijah Newren
  2020-04-07 18:18   ` Phillip Wood
  2020-04-07 23:04 ` Junio C Hamano
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 130+ messages in thread
From: Elijah Newren @ 2020-04-07 15:17 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

Hi Phillip,

On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> The tests for ra/rebase-i-more-options were not as comprehensive as
> they could have been and some of the tests that we did have didn't do
> a good job of testing what they purported to. This series cleans up
> the tests and fixes a couple of bugs (thanks to Jonathan Nieder for
> reporting one of them). The bug fix reworks the code to try and make
> it clearer.
>
> I've opted to add some cleanup commits on top of Rohit's work rather
> than reworking his patches. These are based on top of 4d924528d8
> ("Revert "Merge branch 'ra/rebase-i-more-options'"", 2020-01-12) there
> are some conflicts when merging into pu. I had a quick look at the
> conflicts and they appeared to be relatively straight forward to
> resolve. If that impression is wrong let me know and I can rebase onto
> master or try doing the merge myself and pushing it to github.
>
> Phillip Wood (6):
>   Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
>   t3433: remove loops from tests
>   t3433: only compare commit dates
>   rebase -i: fix --committer-date-is-author-date
>   Revert "sequencer: allow callers of read_author_script() to ignore
>     fields"
>   t3433: improve coverage
>
>  Documentation/git-rebase.txt            |  27 +++-
>  builtin/rebase.c                        |  49 ++++--
>  sequencer.c                             | 109 ++++++++++++-
>  sequencer.h                             |   2 +
>  t/t3422-rebase-incompatible-options.sh  |   2 -
>  t/t3433-rebase-options-compatibility.sh | 201 ++++++++++++++++++++++++
>  7 files changed, 368 insertions(+), 25 deletions(-)
>  create mode 100755 t/t3433-rebase-options-compatibility.sh
>
> --
> 2.26.0

Thanks for working on this!  I took a look over the series and noted a
few minor issues and questions, but it mostly looked good to me.

Elijah

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-07 15:16   ` Elijah Newren
@ 2020-04-07 18:01     ` Phillip Wood
  2020-04-07 21:04     ` Junio C Hamano
  1 sibling, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 18:01 UTC (permalink / raw)
  To: Elijah Newren, Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

Hi Elijah

On 07/04/2020 16:16, Elijah Newren wrote:
> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.
>>
>> This is being reverted to enable some fixups for
>> ra/rebase-i-more-options to be built on this commit.
> 
> This makes sense to me, but it will be only the second 'Revert
> "Revert..."' commit in all of git.git and I'm curious if Junio will be
> unhappy with it.

I wasn't sure what to do for the best, this seemed to be reasonable
(originally I just based the patches on top of ra/rebase-i-more-options
but then they would be a pain to merge into pu because of the revert)
but if Junio has other ideas I'm happy to re-roll

Thanks for taking a look at this series

Phillip

>> ---
>>  Documentation/git-rebase.txt            |  27 ++++-
>>  builtin/rebase.c                        |  49 ++++++--
>>  sequencer.c                             | 141 ++++++++++++++++++++++--
>>  sequencer.h                             |   2 +
>>  t/t3422-rebase-incompatible-options.sh  |   2 -
>>  t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++
>>  7 files changed, 327 insertions(+), 28 deletions(-)
>>  create mode 100755 t/t3433-rebase-options-compatibility.sh
>>
>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
>> index 0c4f038dd6..1d0e2d27cc 100644
>> --- a/Documentation/git-rebase.txt
>> +++ b/Documentation/git-rebase.txt
>> @@ -393,16 +393,31 @@ your branch contains commits which were dropped, this option can be used
>>  with `--keep-base` in order to drop those commits from your branch.
>>
>>  --ignore-whitespace::
>> +       Behaves differently depending on which backend is selected.
>> ++
>> +'am' backend: When applying a patch, ignore changes in whitespace in
>> +context lines if necessary.
>> ++
>> +'interactive' backend: Treat lines with only whitespace changes as
>> +unchanged for the sake of a three-way merge.
>> +
>>  --whitespace=<option>::
>> -       These flag are passed to the 'git apply' program
>> +       This flag is passed to the 'git apply' program
>>         (see linkgit:git-apply[1]) that applies the patch.
>>  +
>>  See also INCOMPATIBLE OPTIONS below.
>>
>>  --committer-date-is-author-date::
>> +       Instead of recording the time the rebased commits are
>> +       created as the committer date, reuse the author date
>> +       as the committer date. This implies --force-rebase.
>> +
>>  --ignore-date::
>> -       These flags are passed to 'git am' to easily change the dates
>> -       of the rebased commits (see linkgit:git-am[1]).
>> +--reset-author-date::
>> +       By default, the author date of the original commit is used
>> +       as the author date for the resulting commit.  This option
>> +       tells Git to use the current timestamp instead and implies
>> +       `--force-rebase`.
>>  +
>>  See also INCOMPATIBLE OPTIONS below.
>>
>> @@ -539,10 +554,7 @@ INCOMPATIBLE OPTIONS
>>
>>  The following options:
>>
>> - * --committer-date-is-author-date
>> - * --ignore-date
>>   * --whitespace
>> - * --ignore-whitespace
>>   * -C
>>
>>  are incompatible with the following options:
>> @@ -565,6 +577,9 @@ 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 --ignore-whitespace
>> + * --preserve-merges and --committer-date-is-author-date
>> + * --preserve-merges and --ignore-date
>>   * --keep-base and --onto
>>   * --keep-base and --root
>>
>> diff --git a/builtin/rebase.c b/builtin/rebase.c
>> index 8081741f8a..e354ec84bb 100644
>> --- a/builtin/rebase.c
>> +++ b/builtin/rebase.c
>> @@ -79,8 +79,11 @@ struct rebase_options {
>>         int allow_rerere_autoupdate;
>>         int keep_empty;
>>         int autosquash;
>> +       int ignore_whitespace;
>>         char *gpg_sign_opt;
>>         int autostash;
>> +       int committer_date_is_author_date;
>> +       int ignore_date;
>>         char *cmd;
>>         int allow_empty_message;
>>         int rebase_merges, rebase_cousins;
>> @@ -99,6 +102,7 @@ struct rebase_options {
>>
>>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>  {
>> +       struct strbuf strategy_buf = STRBUF_INIT;
>>         struct replay_opts replay = REPLAY_OPTS_INIT;
>>
>>         replay.action = REPLAY_INTERACTIVE_REBASE;
>> @@ -112,10 +116,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>         replay.allow_empty_message = opts->allow_empty_message;
>>         replay.verbose = opts->flags & REBASE_VERBOSE;
>>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>> +       replay.committer_date_is_author_date =
>> +                                       opts->committer_date_is_author_date;
>> +       replay.ignore_date = opts->ignore_date;
>>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>>         replay.strategy = opts->strategy;
>> +
>>         if (opts->strategy_opts)
>> -               parse_strategy_opts(&replay, opts->strategy_opts);
>> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);
>> +       if (opts->ignore_whitespace)
>> +               strbuf_addstr(&strategy_buf, " --ignore-space-change");
>> +       if (strategy_buf.len)
>> +               parse_strategy_opts(&replay, strategy_buf.buf);
>> +
>> +       strbuf_release(&strategy_buf);
>>
>>         if (opts->squash_onto) {
>>                 oidcpy(&replay.squash_onto, opts->squash_onto);
>> @@ -517,6 +531,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>>         argc = parse_options(argc, argv, prefix, options,
>>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>>
>> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
>> +
>>         if (!is_null_oid(&squash_onto))
>>                 opts.squash_onto = &squash_onto;
>>
>> @@ -970,6 +986,12 @@ static int run_am(struct rebase_options *opts)
>>         am.git_cmd = 1;
>>         argv_array_push(&am.args, "am");
>>
>> +       if (opts->ignore_whitespace)
>> +               argv_array_push(&am.args, "--ignore-whitespace");
>> +       if (opts->committer_date_is_author_date)
>> +               argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
>> +       if (opts->ignore_date)
>> +               argv_array_push(&opts->git_am_opts, "--ignore-date");
>>         if (opts->action && !strcmp("continue", opts->action)) {
>>                 argv_array_push(&am.args, "--resolved");
>>                 argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
>> @@ -1437,16 +1459,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>>                 OPT_BOOL(0, "signoff", &options.signoff,
>>                          N_("add a Signed-off-by: line to each commit")),
>> -               OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
>> -                                 NULL, N_("passed to 'git am'"),
>> -                                 PARSE_OPT_NOARG),
>> -               OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>> -                                 &options.git_am_opts, NULL,
>> -                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
>> -               OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>> -                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
>> +               OPT_BOOL(0, "committer-date-is-author-date",
>> +                        &options.committer_date_is_author_date,
>> +                        N_("make committer date match author date")),
>> +               OPT_BOOL(0, "reset-author-date", &options.ignore_date,
>> +                        N_("ignore author date and use current date")),
>> +               OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
>> +                               N_("synonym of --reset-author-date")),
>>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>>                                   N_("passed to 'git apply'"), 0),
>> +               OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
>> +                        N_("ignore changes in whitespace")),
>>                 OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>>                                   N_("action"), N_("passed to 'git apply'"), 0),
>>                 OPT_BIT('f', "force-rebase", &options.flags,
>> @@ -1719,11 +1742,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>                     state_dir_base, cmd_live_rebase, buf.buf);
>>         }
>>
>> +       if (options.committer_date_is_author_date ||
>> +           options.ignore_date)
>> +               options.flags |= REBASE_FORCE;
>> +
>>         for (i = 0; i < options.git_am_opts.argc; i++) {
>>                 const char *option = options.git_am_opts.argv[i], *p;
>> -               if (!strcmp(option, "--committer-date-is-author-date") ||
>> -                   !strcmp(option, "--ignore-date") ||
>> -                   !strcmp(option, "--whitespace=fix") ||
>> +               if (!strcmp(option, "--whitespace=fix") ||
>>                     !strcmp(option, "--whitespace=strip"))
>>                         options.flags |= REBASE_FORCE;
>>                 else if (skip_prefix(option, "-C", &p)) {
>> diff --git a/sequencer.c b/sequencer.c
>> index b9dbf1adb0..763ccbbc45 100644
>> --- a/sequencer.c
>> +++ b/sequencer.c
>> @@ -147,6 +147,8 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>>   * command-line.
>>   */
>>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
>> @@ -823,9 +825,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,
>>                 error(_("missing 'GIT_AUTHOR_DATE'"));
>>         if (date_i < 0 || email_i < 0 || date_i < 0 || err)
>>                 goto finish;
>> -       *name = kv.items[name_i].util;
>> -       *email = kv.items[email_i].util;
>> -       *date = kv.items[date_i].util;
>> +
>> +       if (name)
>> +               *name = kv.items[name_i].util;
>> +       else
>> +               free(kv.items[name_i].util);
>> +       if (email)
>> +               *email = kv.items[email_i].util;
>> +       else
>> +               free(kv.items[email_i].util);
>> +       if (date)
>> +               *date = kv.items[date_i].util;
>> +       else
>> +               free(kv.items[date_i].util);
>>         retval = 0;
>>  finish:
>>         string_list_clear(&kv, !!retval);
>> @@ -868,6 +880,47 @@ static char *get_author(const char *message)
>>         return NULL;
>>  }
>>
>> +/* Returns a "date" string that needs to be free()'d by the caller */
>> +static char *read_author_date_or_null(void)
>> +{
>> +       char *date;
>> +
>> +       if (read_author_script(rebase_path_author_script(),
>> +                              NULL, NULL, &date, 0))
>> +               return NULL;
>> +       return date;
>> +}
>> +
>> +/* Construct a free()able author string with current time as the author date */
>> +static char *ignore_author_date(const char *author)
>> +{
>> +       int len = strlen(author);
>> +       struct ident_split ident;
>> +       struct strbuf new_author = STRBUF_INIT;
>> +
>> +       if (split_ident_line(&ident, author, len) < 0) {
>> +               error(_("malformed ident line"));
>> +               return NULL;
>> +       }
>> +       len = ident.mail_end - ident.name_begin + 1;
>> +
>> +       strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
>> +       datestamp(&new_author);
>> +       return strbuf_detach(&new_author, NULL);
>> +}
>> +
>> +static void push_dates(struct child_process *child, int change_committer_date)
>> +{
>> +       time_t now = time(NULL);
>> +       struct strbuf date = STRBUF_INIT;
>> +
>> +       strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
>> +       argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
>> +       if (change_committer_date)
>> +               argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
>> +       strbuf_release(&date);
>> +}
>> +
>>  static const char staged_changes_advice[] =
>>  N_("you have staged changes in your working tree\n"
>>  "If these changes are meant to be squashed into the previous commit, run:\n"
>> @@ -927,6 +980,25 @@ static int run_git_commit(struct repository *r,
>>
>>         cmd.git_cmd = 1;
>>
>> +       if (opts->committer_date_is_author_date) {
>> +               int res = -1;
>> +               struct strbuf datebuf = STRBUF_INIT;
>> +               char *date = read_author_date_or_null();
>> +
>> +               if (!date)
>> +                       return -1;
>> +
>> +               strbuf_addf(&datebuf, "@%s", date);
>> +               res = setenv("GIT_COMMITTER_DATE",
>> +                            opts->ignore_date ? "" : datebuf.buf, 1);
>> +
>> +               strbuf_release(&datebuf);
>> +               free(date);
>> +
>> +               if (res)
>> +                       return -1;
>> +       }
>> +
>>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
>>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);
>>
>> @@ -942,6 +1014,8 @@ static int run_git_commit(struct repository *r,
>>                 argv_array_push(&cmd.args, "--amend");
>>         if (opts->gpg_sign)
>>                 argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>> +       if (opts->ignore_date)
>> +               push_dates(&cmd, opts->committer_date_is_author_date);
>>         if (defmsg)
>>                 argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>>         else if (!(flags & EDIT_MSG))
>> @@ -1310,14 +1384,13 @@ static int try_to_commit(struct repository *r,
>>         struct commit_extra_header *extra = NULL;
>>         struct strbuf err = STRBUF_INIT;
>>         struct strbuf commit_msg = STRBUF_INIT;
>> -       char *amend_author = NULL;
>> +       char *author_to_free = NULL;
>>         const char *hook_commit = NULL;
>>         enum commit_msg_cleanup_mode cleanup;
>>         int res = 0;
>>
>>         if (parse_head(r, &current_head))
>>                 return -1;
>> -
>>         if (flags & AMEND_MSG) {
>>                 const char *exclude_gpgsig[] = { "gpgsig", NULL };
>>                 const char *out_enc = get_commit_output_encoding();
>> @@ -1332,7 +1405,7 @@ static int try_to_commit(struct repository *r,
>>                         strbuf_addstr(msg, orig_message);
>>                         hook_commit = "HEAD";
>>                 }
>> -               author = amend_author = get_author(message);
>> +               author = author_to_free = get_author(message);
>>                 unuse_commit_buffer(current_head, message);
>>                 if (!author) {
>>                         res = error(_("unable to parse commit author"));
>> @@ -1345,6 +1418,31 @@ static int try_to_commit(struct repository *r,
>>                 commit_list_insert(current_head, &parents);
>>         }
>>
>> +       if (opts->committer_date_is_author_date) {
>> +               int len = strlen(author);
>> +               struct ident_split ident;
>> +               struct strbuf date = STRBUF_INIT;
>> +
>> +               if (split_ident_line(&ident, author, len) < 0) {
>> +                       res = error(_("malformed ident line"));
>> +                       goto out;
>> +               }
>> +               if (!ident.date_begin) {
>> +                       res = error(_("corrupted author without date information"));
>> +                       goto out;
>> +               }
>> +
>> +               strbuf_addf(&date, "@%.*s %.*s",
>> +                           (int)(ident.date_end - ident.date_begin), ident.date_begin,
>> +                           (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
>> +               res = setenv("GIT_COMMITTER_DATE",
>> +                            opts->ignore_date ? "" : date.buf, 1);
>> +               strbuf_release(&date);
>> +
>> +               if (res)
>> +                       goto out;
>> +       }
>> +
>>         if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>>                 res = error(_("git write-tree failed to write a tree"));
>>                 goto out;
>> @@ -1404,6 +1502,15 @@ static int try_to_commit(struct repository *r,
>>
>>         reset_ident_date();
>>
>> +       if (opts->ignore_date) {
>> +               author = ignore_author_date(author);
>> +               if (!author) {
>> +                       res = -1;
>> +                       goto out;
>> +               }
>> +               free(author_to_free);
>> +               author_to_free = (char *)author;
>> +       }
>>         if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>>                                  oid, author, opts->gpg_sign, extra)) {
>>                 res = error(_("failed to write commit object"));
>> @@ -1424,7 +1531,7 @@ static int try_to_commit(struct repository *r,
>>         free_commit_extra_headers(extra);
>>         strbuf_release(&err);
>>         strbuf_release(&commit_msg);
>> -       free(amend_author);
>> +       free(author_to_free);
>>
>>         return res;
>>  }
>> @@ -2492,6 +2599,16 @@ static int read_populate_opts(struct replay_opts *opts)
>>                         opts->signoff = 1;
>>                 }
>>
>> +               if (file_exists(rebase_path_cdate_is_adate())) {
>> +                       opts->allow_ff = 0;
>> +                       opts->committer_date_is_author_date = 1;
>> +               }
>> +
>> +               if (file_exists(rebase_path_ignore_date())) {
>> +                       opts->allow_ff = 0;
>> +                       opts->ignore_date = 1;
>> +               }
>> +
>>                 if (file_exists(rebase_path_reschedule_failed_exec()))
>>                         opts->reschedule_failed_exec = 1;
>>
>> @@ -2574,6 +2691,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->committer_date_is_author_date)
>> +               write_file(rebase_path_cdate_is_adate(), "%s", "");
>> +       if (opts->ignore_date)
>> +               write_file(rebase_path_ignore_date(), "%s", "");
>>         if (opts->reschedule_failed_exec)
>>                 write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>>
>> @@ -3514,6 +3635,8 @@ static int do_merge(struct repository *r,
>>                 argv_array_push(&cmd.args, git_path_merge_msg(r));
>>                 if (opts->gpg_sign)
>>                         argv_array_push(&cmd.args, opts->gpg_sign);
>> +               if (opts->ignore_date)
>> +                       push_dates(&cmd, opts->committer_date_is_author_date);
>>
>>                 /* Add the tips to be merged */
>>                 for (j = to_merge; j; j = j->next)
>> @@ -3786,7 +3909,9 @@ static int pick_commits(struct repository *r,
>>         setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>>         if (opts->allow_ff)
>>                 assert(!(opts->signoff || opts->no_commit ||
>> -                               opts->record_origin || opts->edit));
>> +                               opts->record_origin || opts->edit ||
>> +                               opts->committer_date_is_author_date ||
>> +                               opts->ignore_date));
>>         if (read_and_refresh_cache(r, opts))
>>                 return -1;
>>
>> diff --git a/sequencer.h b/sequencer.h
>> index 9f9ae291e3..e9a0e03ea2 100644
>> --- a/sequencer.h
>> +++ b/sequencer.h
>> @@ -43,6 +43,8 @@ struct replay_opts {
>>         int verbose;
>>         int quiet;
>>         int reschedule_failed_exec;
>> +       int committer_date_is_author_date;
>> +       int ignore_date;
>>
>>         int mainline;
>>
>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>> index 50e7960702..c8234062c6 100755
>> --- a/t/t3422-rebase-incompatible-options.sh
>> +++ b/t/t3422-rebase-incompatible-options.sh
>> @@ -61,8 +61,6 @@ test_rebase_am_only () {
>>  }
>>
>>  test_rebase_am_only --whitespace=fix
>> -test_rebase_am_only --ignore-whitespace
>> -test_rebase_am_only --committer-date-is-author-date
>>  test_rebase_am_only -C4
>>
>>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
>> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
>> new file mode 100755
>> index 0000000000..5166f158dd
>> --- /dev/null
>> +++ b/t/t3433-rebase-options-compatibility.sh
>> @@ -0,0 +1,131 @@
>> +#!/bin/sh
>> +#
>> +# Copyright (c) 2019 Rohit Ashiwal
>> +#
>> +
>> +test_description='tests to ensure compatibility between am and interactive backends'
>> +
>> +. ./test-lib.sh
>> +
>> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>> +export GIT_AUTHOR_DATE
>> +
>> +# This is a special case in which both am and interactive backends
>> +# provide the same output. It was done intentionally because
>> +# both the backends fall short of optimal behaviour.
>> +test_expect_success 'setup' '
>> +       git checkout -b topic &&
>> +       q_to_tab >file <<-\EOF &&
>> +       line 1
>> +       Qline 2
>> +       line 3
>> +       EOF
>> +       git add file &&
>> +       git commit -m "add file" &&
>> +       cat >file <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       git commit -am "update file" &&
>> +       git tag side &&
>> +       test_commit commit1 foo foo1 &&
>> +       test_commit commit2 foo foo2 &&
>> +       test_commit commit3 foo foo3 &&
>> +
>> +       git checkout --orphan master &&
>> +       git rm --cached foo &&
>> +       rm foo &&
>> +       sed -e "s/^|//" >file <<-\EOF &&
>> +       |line 1
>> +       |        line 2
>> +       |line 3
>> +       EOF
>> +       git add file &&
>> +       git commit -m "add file" &&
>> +       git tag main
>> +'
>> +
>> +test_expect_success '--ignore-whitespace works with am backend' '
>> +       cat >expect <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       test_must_fail git rebase main side &&
>> +       git rebase --abort &&
>> +       git rebase --ignore-whitespace main side &&
>> +       test_cmp expect file
>> +'
>> +
>> +test_expect_success '--ignore-whitespace works with interactive backend' '
>> +       cat >expect <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       test_must_fail git rebase --merge main side &&
>> +       git rebase --abort &&
>> +       git rebase --merge --ignore-whitespace main side &&
>> +       test_cmp expect file
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with am backend' '
>> +       git commit --amend &&
>> +       git rebase --committer-date-is-author-date HEAD^ &&
>> +       git show HEAD --pretty="format:%ai" >authortime &&
>> +       git show HEAD --pretty="format:%ci" >committertime &&
>> +       test_cmp authortime committertime
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with interactive backend' '
>> +       git commit --amend &&
>> +       git rebase -i --committer-date-is-author-date HEAD^ &&
>> +       git show HEAD --pretty="format:%ai" >authortime &&
>> +       git show HEAD --pretty="format:%ci" >committertime &&
>> +       test_cmp authortime committertime
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
>> +       git checkout side &&
>> +       git merge --no-ff commit3 &&
>> +       git rebase -r --root --committer-date-is-author-date &&
>> +       git rev-list HEAD >rev_list &&
>> +       while read HASH
>> +       do
>> +               git show $HASH --pretty="format:%ai" >authortime
>> +               git show $HASH --pretty="format:%ci" >committertime
>> +               test_cmp authortime committertime
>> +       done <rev_list
>> +'
>> +
>> +# Checking for +0000 in author time is enough since default
>> +# timezone is UTC, but the timezone used while committing
>> +# sets to +0530.
>> +test_expect_success '--ignore-date works with am backend' '
>> +       git commit --amend --date="$GIT_AUTHOR_DATE" &&
>> +       git rebase --ignore-date HEAD^ &&
>> +       git show HEAD --pretty="format:%ai" >authortime &&
>> +       grep "+0000" authortime
>> +'
>> +
>> +test_expect_success '--ignore-date works with interactive backend' '
>> +       git commit --amend --date="$GIT_AUTHOR_DATE" &&
>> +       git rebase --ignore-date -i HEAD^ &&
>> +       git show HEAD --pretty="format:%ai" >authortime &&
>> +       grep "+0000" authortime
>> +'
>> +
>> +test_expect_success '--ignore-date works with rebase -r' '
>> +       git checkout side &&
>> +       git merge --no-ff commit3 &&
>> +       git rebase -r --root --ignore-date &&
>> +       git rev-list HEAD >rev_list &&
>> +       while read HASH
>> +       do
>> +               git show $HASH --pretty="format:%ai" >authortime
>> +               grep "+0000" authortime
>> +       done <rev_list
>> +'
>> +
>> +test_done
>> --
>> 2.26.0
>>


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 4/6] rebase -i: fix --committer-date-is-author-date
  2020-04-07 15:05   ` Elijah Newren
@ 2020-04-07 18:11     ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 18:11 UTC (permalink / raw)
  To: Elijah Newren, Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

Hi Elijah

On 07/04/2020 16:05, Elijah Newren wrote:
> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> Johanathan Nieder reported that `rebase --committer-date-is-author-date`
>> failed with the error "invalid date format: @@2592000 +0000" when the
>> backend was switched to use the sequencer [1]. This is because when we
>> read the date from the author script file is already prefixed by '@' so
>> we do not need to add one. This did not show up in our tests
>> because once match_object_header_date() fails to match because of the
>> extra '@' parse_date_basic() strips the prefix and a date with more than
>> 8 digits is parsed as a number of seconds by match_digit().
>>
>> While fixing this I also noticed that we were not setting
>> GIT_COMMITTER_DATE in the environment when forking `git merge`. This was
>> untested. The tests we did have used commits where the author date was
>> the same as the current value $GIT_COMMITTER_DATE in the environment so
>> they did not test that we were actually using the author date when
>> creating the commit.
>>
>> As we have already read GIT_AUTHOR_DATE into cmd.env_array we now use
>> that rather than re-reading the author-script file. I've moved the code
>> that handles opts->ignore date so that all the code setting the child
>> environment is together and changed it so we no longer set
>> GIT_COMMITTER_DATE twice when --ignore-date is combined with
>> --committer-date-is-author-date.
>>
>> [1] https://lore.kernel.org/git/<20200110231436.GA24315@google.com>
>>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>  sequencer.c                             | 68 ++++++++++---------------
>>  t/t3433-rebase-options-compatibility.sh | 29 +++++++++--
>>  2 files changed, 52 insertions(+), 45 deletions(-)
>>
>> diff --git a/sequencer.c b/sequencer.c
>> index 763ccbbc45..56f6e49289 100644
>> --- a/sequencer.c
>> +++ b/sequencer.c
>> @@ -880,17 +880,6 @@ static char *get_author(const char *message)
>>         return NULL;
>>  }
>>
>> -/* Returns a "date" string that needs to be free()'d by the caller */
>> -static char *read_author_date_or_null(void)
>> -{
>> -       char *date;
>> -
>> -       if (read_author_script(rebase_path_author_script(),
>> -                              NULL, NULL, &date, 0))
>> -               return NULL;
>> -       return date;
>> -}
>> -
>>  /* Construct a free()able author string with current time as the author date */
>>  static char *ignore_author_date(const char *author)
>>  {
>> @@ -909,16 +898,20 @@ static char *ignore_author_date(const char *author)
>>         return strbuf_detach(&new_author, NULL);
>>  }
>>
>> -static void push_dates(struct child_process *child, int change_committer_date)
>> +static const char *author_date_from_env_array(const struct argv_array *env)
>>  {
>> -       time_t now = time(NULL);
>> -       struct strbuf date = STRBUF_INIT;
>> +       int i;
>> +       const char *date;
>>
>> -       strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
>> -       argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
>> -       if (change_committer_date)
>> -               argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
>> -       strbuf_release(&date);
>> +       for (i = 0; i < env->argc; i++)
>> +               if (skip_prefix(env->argv[i],
>> +                               "GIT_AUTHOR_DATE=", &date))
>> +                       return date;
> 
> Is there any risk that GIT_AUTHOR_DATE=<somedate> will appear twice in
> @child->env_array ?  If there is, should we read through the whole
> list to make sure we take the last one?

read_author_script() errors out if GIT_AUTHOR_DATE is missing or given
more than once

Best Wishes

Phillip

> 
>> +       /*
>> +        * If GIT_AUTHOR_DATE is missing we should have already errored out when
>> +        * reading the script
>> +        */
>> +       BUG("GIT_AUTHOR_DATE missing from author script");
>>  }
>>
>>  static const char staged_changes_advice[] =
>> @@ -980,31 +973,19 @@ static int run_git_commit(struct repository *r,
>>
>>         cmd.git_cmd = 1;
>>
>> -       if (opts->committer_date_is_author_date) {
>> -               int res = -1;
>> -               struct strbuf datebuf = STRBUF_INIT;
>> -               char *date = read_author_date_or_null();
>> -
>> -               if (!date)
>> -                       return -1;
>> -
>> -               strbuf_addf(&datebuf, "@%s", date);
>> -               res = setenv("GIT_COMMITTER_DATE",
>> -                            opts->ignore_date ? "" : datebuf.buf, 1);
>> -
>> -               strbuf_release(&datebuf);
>> -               free(date);
>> -
>> -               if (res)
>> -                       return -1;
>> -       }
>> -
>>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
>>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);
>>
>>                 return error(_(staged_changes_advice),
>>                              gpg_opt, gpg_opt);
>>         }
>> +       if (opts->committer_date_is_author_date)
>> +               argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>> +                                opts->ignore_date ?
>> +                                "" :
>> +                                author_date_from_env_array(&cmd.env_array));
>> +       if (opts->ignore_date)
>> +               argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>>
>>         argv_array_push(&cmd.args, "commit");
>>
>> @@ -1014,8 +995,6 @@ static int run_git_commit(struct repository *r,
>>                 argv_array_push(&cmd.args, "--amend");
>>         if (opts->gpg_sign)
>>                 argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>> -       if (opts->ignore_date)
>> -               push_dates(&cmd, opts->committer_date_is_author_date);
>>         if (defmsg)
>>                 argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
>>         else if (!(flags & EDIT_MSG))
>> @@ -3615,6 +3594,13 @@ static int do_merge(struct repository *r,
>>                         ret = error(_(staged_changes_advice), gpg_opt, gpg_opt);
>>                         goto leave_merge;
>>                 }
>> +               if (opts->committer_date_is_author_date)
>> +                       argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>> +                                        opts->ignore_date ?
>> +                                        "" :
>> +                                        author_date_from_env_array(&cmd.env_array));
>> +               if (opts->ignore_date)
>> +                       argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>>
>>                 cmd.git_cmd = 1;
>>                 argv_array_push(&cmd.args, "merge");
>> @@ -3635,8 +3621,6 @@ static int do_merge(struct repository *r,
>>                 argv_array_push(&cmd.args, git_path_merge_msg(r));
>>                 if (opts->gpg_sign)
>>                         argv_array_push(&cmd.args, opts->gpg_sign);
>> -               if (opts->ignore_date)
>> -                       push_dates(&cmd, opts->committer_date_is_author_date);
>>
>>                 /* Add the tips to be merged */
>>                 for (j = to_merge; j; j = j->next)
>> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
>> index 132f577fc9..8247d01442 100755
>> --- a/t/t3433-rebase-options-compatibility.sh
>> +++ b/t/t3433-rebase-options-compatibility.sh
>> @@ -71,15 +71,15 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>>  '
>>
>>  test_expect_success '--committer-date-is-author-date works with am backend' '
>> -       git commit --amend &&
>> +       GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>>         git rebase --committer-date-is-author-date HEAD^ &&
>>         git log -1 --pretty="format:%ai" >authortime &&
>>         git log -1 --pretty="format:%ci" >committertime &&
>>         test_cmp authortime committertime
>>  '
>>
>>  test_expect_success '--committer-date-is-author-date works with interactive backend' '
>> -       git commit --amend &&
>> +       GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>>         git rebase -i --committer-date-is-author-date HEAD^ &&
>>         git log -1 --pretty="format:%ai" >authortime &&
>>         git log -1 --pretty="format:%ci" >committertime &&
>> @@ -88,13 +88,36 @@ test_expect_success '--committer-date-is-author-date works with interactive back
>>
>>  test_expect_success '--committer-date-is-author-date works with rebase -r' '
>>         git checkout side &&
>> -       git merge --no-ff commit3 &&
>> +       GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>>         git rebase -r --root --committer-date-is-author-date &&
>>         git log --pretty="format:%ai" >authortime &&
>>         git log --pretty="format:%ci" >committertime &&
>>         test_cmp authortime committertime
>>  '
>>
>> +test_expect_success '--committer-date-is-author-date works when forking merge' '
>> +       git checkout side &&
>> +       GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>> +       git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
>> +       git log --pretty="format:%ai" >authortime &&
>> +       git log --pretty="format:%ci" >committertime &&
>> +       test_cmp authortime committertime
>> +
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
>> +       git checkout commit2 &&
>> +       GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
>> +       git log -1 --format=%at HEAD >expect &&
>> +       test_must_fail git rebase -i --committer-date-is-author-date \
>> +               --onto HEAD^^ HEAD^ &&
>> +       echo resolved > foo &&
>> +       git add foo &&
>> +       git rebase --continue &&
>> +       git log -1 --format=%ct HEAD >actual &&
>> +       test_cmp expect actual
>> +'
>> +
>>  # Checking for +0000 in author time is enough since default
>>  # timezone is UTC, but the timezone used while committing
>>  # sets to +0530.
>> --
>> 2.26.0
>>


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 6/6] t3433: improve coverage
  2020-04-07 15:13   ` Elijah Newren
@ 2020-04-07 18:16     ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 18:16 UTC (permalink / raw)
  To: Elijah Newren, Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

Hi Elijah

On 07/04/2020 16:13, Elijah Newren wrote:
> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> Add tests to check --ignore-whitespace and --ignore-date are remembered
>> when running `rebase --continue` and to check
>> --committer-date-is-author-date with --ignore-date gives the expected
>> result.
> 
> Thanks for adding these.
> 
>>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>  t/t3433-rebase-options-compatibility.sh | 55 +++++++++++++++++++++++++
> 
> t3433 is taken by t3433-rebase-across-mode-change.sh in upstream.
> When you revert the reversion of Rohit's changes, perhaps you need to
> rename his t3433 to some other file?

Thanks for point that out I'll rename it

> Also, the name "rebase-options-compatibility" suggest to me that it's
> just checking whether certain options can be used together.  Perhaps
> the --ignore-whitespace and --ignore-date tests you add should go
> somewhere else?

I think this file is so named because it tests that the merge backend is
compatible with the apply backend for the new options (i.e. they both
give the same results) - I'll try and think of a better name

>>  1 file changed, 55 insertions(+)
>>
>> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh
>> index 8247d01442..a13c341301 100755
>> --- a/t/t3433-rebase-options-compatibility.sh
>> +++ b/t/t3433-rebase-options-compatibility.sh
>> @@ -7,6 +7,8 @@ test_description='tests to ensure compatibility between am and interactive backe
>>
>>  . ./test-lib.sh
>>
>> +. "$TEST_DIRECTORY"/lib-rebase.sh
>> +
>>  GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>>  export GIT_AUTHOR_DATE
>>
>> @@ -70,6 +72,22 @@ test_expect_success '--ignore-whitespace works with interactive backend' '
>>         test_cmp expect file
>>  '
>>
>> +test_expect_success '--ignore-whitespace is remembered when continuing' '
>> +       cat >expect <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       (
>> +               set_fake_editor &&
>> +               FAKE_LINES="break 1" &&
>> +               export FAKE_LINES &&
>> +               git rebase -i --ignore-whitespace main side
>> +       ) &&
>> +       git rebase --continue &&
>> +       test_cmp expect file
>> +'
>> +
>>  test_expect_success '--committer-date-is-author-date works with am backend' '
>>         GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>>         git rebase --committer-date-is-author-date HEAD^ &&
>> @@ -135,6 +153,16 @@ test_expect_success '--ignore-date works with interactive backend' '
>>         grep "+0000" authortime
>>  '
>>
>> +test_expect_success '--ignore-date works after conflict resolution' '
>> +       test_must_fail git rebase --ignore-date -i \
>> +               --onto commit2^^ commit2^ commit2 &&
> 
> I don't see any todo list here; is there a reason you are using -i
> instead of say -m?  (Similar question applies for the subsequent tests
> you add below too?)

Habit. (also these were originally based on an older commit and I wasn't
sure if that had your 'rebase -m' changes in it.) I'll update them to use -m

Best Wishes

Phillip

>> +       echo resolved >foo &&
>> +       git add foo &&
>> +       git rebase --continue &&
>> +       git log --pretty=%ai >authortime &&
>> +       grep +0000 authortime
>> +'
>> +
>>  test_expect_success '--ignore-date works with rebase -r' '
>>         git checkout side &&
>>         git merge --no-ff commit3 &&
>> @@ -143,4 +171,31 @@ test_expect_success '--ignore-date works with rebase -r' '
>>         ! grep -v "+0000" authortime
>>  '
>>
>> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '
>> +       test_must_fail git rebase -i --committer-date-is-author-date \
>> +               --ignore-date --onto commit2^^ commit2^ commit3 &&
>> +       git checkout --theirs foo &&
>> +       git add foo &&
>> +       git rebase --continue &&
>> +       git log -2 --pretty=%ai >authortime &&
>> +       git log -2 --pretty=%ci >committertime &&
>> +       test_cmp authortime committertime &&
>> +       ! grep -v "+0000" authortime
>> +'
>> +
>> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
>> +       GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
>> +               git rebase -i --strategy=resolve --ignore-date \
>> +               --committer-date-is-author-date side side &&
>> +       git log -1 --pretty=%ai >authortime &&
>> +       git log -1 --pretty=%ci >committertime &&
>> +       test_cmp authortime committertime &&
>> +       grep "+0000" authortime
>> + '
>> +
>> +# This must be the last test in this file
>> +test_expect_success '$EDITOR and friends are unchanged' '
>> +       test_editor_unchanged
>> +'
>> +
>>  test_done
>> --
>> 2.26.0
>>


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 0/6] fixup ra/rebase-i-more-options
  2020-04-07 15:17 ` [PATCH 0/6] fixup ra/rebase-i-more-options Elijah Newren
@ 2020-04-07 18:18   ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-07 18:18 UTC (permalink / raw)
  To: Elijah Newren, Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Junio C Hamano,
	Rohit Ashiwal, Jonathan Nieder

On 07/04/2020 16:17, Elijah Newren wrote:
> Hi Phillip,
> 
> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> The tests for ra/rebase-i-more-options were not as comprehensive as
>> they could have been and some of the tests that we did have didn't do
>> a good job of testing what they purported to. This series cleans up
>> the tests and fixes a couple of bugs (thanks to Jonathan Nieder for
>> reporting one of them). The bug fix reworks the code to try and make
>> it clearer.
>>
>> I've opted to add some cleanup commits on top of Rohit's work rather
>> than reworking his patches. These are based on top of 4d924528d8
>> ("Revert "Merge branch 'ra/rebase-i-more-options'"", 2020-01-12) there
>> are some conflicts when merging into pu. I had a quick look at the
>> conflicts and they appeared to be relatively straight forward to
>> resolve. If that impression is wrong let me know and I can rebase onto
>> master or try doing the merge myself and pushing it to github.
>>
>> Phillip Wood (6):
>>   Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
>>   t3433: remove loops from tests
>>   t3433: only compare commit dates
>>   rebase -i: fix --committer-date-is-author-date
>>   Revert "sequencer: allow callers of read_author_script() to ignore
>>     fields"
>>   t3433: improve coverage
>>
>>  Documentation/git-rebase.txt            |  27 +++-
>>  builtin/rebase.c                        |  49 ++++--
>>  sequencer.c                             | 109 ++++++++++++-
>>  sequencer.h                             |   2 +
>>  t/t3422-rebase-incompatible-options.sh  |   2 -
>>  t/t3433-rebase-options-compatibility.sh | 201 ++++++++++++++++++++++++
>>  7 files changed, 368 insertions(+), 25 deletions(-)
>>  create mode 100755 t/t3433-rebase-options-compatibility.sh
>>
>> --
>> 2.26.0
> 
> Thanks for working on this!  I took a look over the series and noted a
> few minor issues and questions, but it mostly looked good to me.

Thanks for looking at them and for your suggestions. I think I've got
reasonable test coverage now - lets see if Stolee's coverage script agrees

Best Wishes

Phillip


> Elijah
> 


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-07 15:16   ` Elijah Newren
  2020-04-07 18:01     ` Phillip Wood
@ 2020-04-07 21:04     ` Junio C Hamano
  2020-04-07 21:31       ` Junio C Hamano
  1 sibling, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-04-07 21:04 UTC (permalink / raw)
  To: Elijah Newren
  Cc: Phillip Wood, Git Mailing List, Johannes Schindelin,
	Rohit Ashiwal, Jonathan Nieder

Elijah Newren <newren@gmail.com> writes:

> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.
>>
>> This is being reverted to enable some fixups for
>> ra/rebase-i-more-options to be built on this commit.
>
> This makes sense to me, but it will be only the second 'Revert
> "Revert..."' commit in all of git.git and I'm curious if Junio will be
> unhappy with it.

Nah, there isn't much to become unhappy about.  

I however suspect that the alternative would certainly be much nicer
and easier to understand, which is to rebuild the 7-patch series
c58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this
patch to take us back to a known buggy state and then fix the result
with 5 more patches.  Is that what you meant?

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-07 21:04     ` Junio C Hamano
@ 2020-04-07 21:31       ` Junio C Hamano
  2020-04-12 17:47         ` Johannes Schindelin
  0 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-04-07 21:31 UTC (permalink / raw)
  To: Elijah Newren
  Cc: Phillip Wood, Git Mailing List, Johannes Schindelin,
	Rohit Ashiwal, Jonathan Nieder

Junio C Hamano <gitster@pobox.com> writes:

> Elijah Newren <newren@gmail.com> writes:
>
>> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>>
>>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>>
>>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.
>>>
>>> This is being reverted to enable some fixups for
>>> ra/rebase-i-more-options to be built on this commit.
>>
>> This makes sense to me, but it will be only the second 'Revert
>> "Revert..."' commit in all of git.git and I'm curious if Junio will be
>> unhappy with it.
>
> Nah, there isn't much to become unhappy about.  
>
> I however suspect that the alternative would certainly be much nicer
> and easier to understand, which is to rebuild the 7-patch series
> c58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this
> patch to take us back to a known buggy state and then fix the result
> with 5 more patches.  Is that what you meant?

After looking at the conflict resolution while merging the result of
applying these patches on top of the older codebase, I would have to
say that the approach """I've opted to add some cleanup commits on
top of Rohit's work rather than reworking his patches.""" may not
have been particularly a brilliant idea, not because the conflicts
arising from an older codebase are unpleasant to resolve (they seem
to be reasonably contained), but because it resurrects other
unwanted cruft we have cleaned up since then, and worse yet, it does
so without triggering conflicts.  For example, we'll end up seeing
mentions of "'am' backend", which have all been updated to "'apply'
backend", in the documentation, and patches [2-6/6] do not fix them.

[5/6] is an example of one more "unwanted" thing the reversion
resurrects that needed to be fixed, I guess?

The result of applying all these patches and merging it to 'master'
and/or 'pu' may be more or less right, as far as the new features
added to the "rebase -i" by the series are concerned but there may
be many small "unwanted cruft" we may be resurrecting with [1/6],
so...




^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 0/6] fixup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (6 preceding siblings ...)
  2020-04-07 15:17 ` [PATCH 0/6] fixup ra/rebase-i-more-options Elijah Newren
@ 2020-04-07 23:04 ` Junio C Hamano
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-04-07 23:04 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Git Mailing List, Johannes Schindelin, Rohit Ashiwal,
	Elijah Newren, Jonathan Nieder, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> The tests for ra/rebase-i-more-options were not as comprehensive as
> they could have been and some of the tests that we did have didn't do
> a good job of testing what they purported to. This series cleans up
> the tests and fixes a couple of bugs (thanks to Jonathan Nieder for
> reporting one of them). The bug fix reworks the code to try and make
> it clearer.

As t3433 is already taken, I've queued a SQUASH??? commit at the tip
of the topic to move it to t3436 while queuing (which is another
fallout that needs fixing while we resurrect an outdated series).

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-07 21:31       ` Junio C Hamano
@ 2020-04-12 17:47         ` Johannes Schindelin
  2020-04-13  9:58           ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Johannes Schindelin @ 2020-04-12 17:47 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Elijah Newren, Phillip Wood, Git Mailing List, Rohit Ashiwal,
	Jonathan Nieder

Hi Phillip, Elijah & Junio,

On Tue, 7 Apr 2020, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
>
> > Elijah Newren <newren@gmail.com> writes:
> >
> >> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
> >>>
> >>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
> >>>
> >>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.
> >>>
> >>> This is being reverted to enable some fixups for
> >>> ra/rebase-i-more-options to be built on this commit.
> >>
> >> This makes sense to me, but it will be only the second 'Revert
> >> "Revert..."' commit in all of git.git and I'm curious if Junio will be
> >> unhappy with it.
> >
> > Nah, there isn't much to become unhappy about.
> >
> > I however suspect that the alternative would certainly be much nicer
> > and easier to understand, which is to rebuild the 7-patch series
> > c58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this
> > patch to take us back to a known buggy state and then fix the result
> > with 5 more patches.  Is that what you meant?
>
> After looking at the conflict resolution while merging the result of
> applying these patches on top of the older codebase, I would have to
> say that the approach """I've opted to add some cleanup commits on
> top of Rohit's work rather than reworking his patches.""" may not
> have been particularly a brilliant idea, not because the conflicts
> arising from an older codebase are unpleasant to resolve (they seem
> to be reasonably contained), but because it resurrects other
> unwanted cruft we have cleaned up since then, and worse yet, it does
> so without triggering conflicts.  For example, we'll end up seeing
> mentions of "'am' backend", which have all been updated to "'apply'
> backend", in the documentation, and patches [2-6/6] do not fix them.
>
> [5/6] is an example of one more "unwanted" thing the reversion
> resurrects that needed to be fixed, I guess?
>
> The result of applying all these patches and merging it to 'master'
> and/or 'pu' may be more or less right, as far as the new features
> added to the "rebase -i" by the series are concerned but there may
> be many small "unwanted cruft" we may be resurrecting with [1/6],
> so...

I agree that it would make for a much nicer read if the entire patch
series was simply rebased on top of v2.26.0, with drops instead of
reverts. I suspect that 4/6 will not even become a fixup, but that the
resulting patch is really more of an `Initial-patch-by: Rohit` material
with Phillip as the author on record.

As to the changes, I had a brief look over them, and I have nothing to add
to Elijah's review except to stress how excited I am about the increased
test coverage. From my perspective, this makes the patch series 10x
better.

Thanks,
Dscho

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-12 17:47         ` Johannes Schindelin
@ 2020-04-13  9:58           ` Phillip Wood
  2020-04-13 22:05             ` Junio C Hamano
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-04-13  9:58 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano
  Cc: Elijah Newren, Phillip Wood, Git Mailing List, Rohit Ashiwal,
	Jonathan Nieder

Hi All

On 12/04/2020 18:47, Johannes Schindelin wrote:
> Hi Phillip, Elijah & Junio,
> 
> On Tue, 7 Apr 2020, Junio C Hamano wrote:
> 
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>>> Elijah Newren <newren@gmail.com> writes:
>>>
>>>> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>>>>
>>>>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>>>>
>>>>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.
>>>>>
>>>>> This is being reverted to enable some fixups for
>>>>> ra/rebase-i-more-options to be built on this commit.
>>>>
>>>> This makes sense to me, but it will be only the second 'Revert
>>>> "Revert..."' commit in all of git.git and I'm curious if Junio will be
>>>> unhappy with it.
>>>
>>> Nah, there isn't much to become unhappy about.
>>>
>>> I however suspect that the alternative would certainly be much nicer
>>> and easier to understand, which is to rebuild the 7-patch series
>>> c58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this
>>> patch to take us back to a known buggy state and then fix the result
>>> with 5 more patches.  Is that what you meant?
>>
>> After looking at the conflict resolution while merging the result of
>> applying these patches on top of the older codebase, I would have to
>> say that the approach """I've opted to add some cleanup commits on
>> top of Rohit's work rather than reworking his patches.""" may not
>> have been particularly a brilliant idea, not because the conflicts
>> arising from an older codebase are unpleasant to resolve (they seem
>> to be reasonably contained), but because it resurrects other
>> unwanted cruft we have cleaned up since then, and worse yet, it does
>> so without triggering conflicts.  For example, we'll end up seeing
>> mentions of "'am' backend", which have all been updated to "'apply'
>> backend", in the documentation, and patches [2-6/6] do not fix them.
>>
>> [5/6] is an example of one more "unwanted" thing the reversion
>> resurrects that needed to be fixed, I guess?
>>
>> The result of applying all these patches and merging it to 'master'
>> and/or 'pu' may be more or less right, as far as the new features
>> added to the "rebase -i" by the series are concerned but there may
>> be many small "unwanted cruft" we may be resurrecting with [1/6],
>> so...
> 
> I agree that it would make for a much nicer read if the entire patch
> series was simply rebased on top of v2.26.0, with drops instead of
> reverts. I suspect that 4/6 will not even become a fixup, but that the
> resulting patch is really more of an `Initial-patch-by: Rohit` material
> with Phillip as the author on record.
> 
> As to the changes, I had a brief look over them, and I have nothing to add
> to Elijah's review except to stress how excited I am about the increased
> test coverage. From my perspective, this makes the patch series 10x
> better.

Thanks for all your feedback, I'll reroll as a new patch series based on
master

Best Wishes

Phillip

> Thanks,
> Dscho
> 


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'""
  2020-04-13  9:58           ` Phillip Wood
@ 2020-04-13 22:05             ` Junio C Hamano
  0 siblings, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-04-13 22:05 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Phillip Wood,
	Git Mailing List, Rohit Ashiwal, Jonathan Nieder

Phillip Wood <phillip.wood123@gmail.com> writes:

>> I agree that it would make for a much nicer read if the entire patch
>> series was simply rebased on top of v2.26.0, with drops instead of
>> reverts. I suspect that 4/6 will not even become a fixup, but that the
>> resulting patch is really more of an `Initial-patch-by: Rohit` material
>> with Phillip as the author on record.
>> 
>> As to the changes, I had a brief look over them, and I have nothing to add
>> to Elijah's review except to stress how excited I am about the increased
>> test coverage. From my perspective, this makes the patch series 10x
>> better.
>
> Thanks for all your feedback, I'll reroll as a new patch series based on
> master

Thanks, all.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v2 0/5] cleanup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (7 preceding siblings ...)
  2020-04-07 23:04 ` Junio C Hamano
@ 2020-04-29 10:25 ` Phillip Wood
  2020-04-29 10:25   ` [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
                     ` (5 more replies)
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
                   ` (5 subsequent siblings)
  14 siblings, 6 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-29 10:25 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

I've rebased Rohit's patches on master and reworked them with my
fixups from v1. I've renamed the test file that was causing a
problem (as you'll see I wasn't feeling very inspired when I came
up with the name) and changed some tests from using rebase -i to
rebase -m as suggested by Elijah. I've updated the last patch to
test both --reset-author and --ignore-author.

There's a range-diff below between ra/rebase-i-more-options and
these patches though I'm not sure how useful it is in practice.

Phillip Wood (2):
  rebase -i: support --committer-date-is-author-date
  rebase -i: support --ignore-date

Rohit Ashiwal (3):
  rebase -i: add --ignore-whitespace flag
  sequencer: rename amend_author to author_to_free
  rebase: add --reset-author-date

 Documentation/git-rebase.txt           |  26 ++-
 builtin/rebase.c                       |  46 ++++--
 sequencer.c                            | 111 ++++++++++++-
 sequencer.h                            |   2 +
 t/t3422-rebase-incompatible-options.sh |   2 -
 t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++
 6 files changed, 371 insertions(+), 25 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

1:  ba51d2fb24 ! 1:  5ef315240a rebase -i: add --ignore-whitespace flag
    @@ Metadata
      ## Commit message ##
         rebase -i: add --ignore-whitespace flag
     
    -    There are two backends available for rebasing, viz, the am and the
    -    interactive. Naturally, there shall be some features that are
    -    implemented in one but not in the other. One such flag is
    -    --ignore-whitespace which indicates merge mechanism to treat lines
    -    with only whitespace changes as unchanged. Wire the interactive
    -    rebase to also understand the --ignore-whitespace flag by
    -    translating it to -Xignore-space-change.
    +    Rebase is implemented with two different backends - 'apply' and 'merge'
    +    each of which support a different set of options. In particuar the apply
    +    backend supports a number of options implemented by 'git am' that are
    +    not available to the merge backend. As part of an on going effort to
    +    remove the apply backend this patch adds support for the
    +    --ignore-whitespace option to the merge backend. This option treats
    +    lines with only whitespace changes as unchanged and is implemented in
    +    the merge backend by translating it to -Xignore-space-change.
     
         Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>
    +    Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
     
      ## Documentation/git-rebase.txt ##
    -@@ Documentation/git-rebase.txt: If either <upstream> or --root is given on the command line, then the
    - default is `--no-fork-point`, otherwise the default is `--fork-point`.
    +@@ Documentation/git-rebase.txt: your branch contains commits which were dropped, this option can be used
    + with `--keep-base` in order to drop those commits from your branch.
      
      --ignore-whitespace::
     +	Behaves differently depending on which backend is selected.
     ++
    -+'am' backend: When applying a patch, ignore changes in whitespace in
    -+context lines if necessary.
    ++apply backend: When applying a patch, ignore changes in whitespace in
    ++context lines.
     ++
    -+'interactive' backend: Treat lines with only whitespace changes as
    -+unchanged for the sake of a three-way merge.
    ++merge backend: Treat lines with only whitespace changes as unchanged
    ++when merging.
     +
      --whitespace=<option>::
    --	These flag are passed to the 'git apply' program
    +-	These flags are passed to the 'git apply' program
     +	This flag is passed to the 'git apply' program
      	(see linkgit:git-apply[1]) that applies the patch.
    + 	Implies --apply.
      +
    - See also INCOMPATIBLE OPTIONS below.
     @@ Documentation/git-rebase.txt: The following options:
    +  * --apply
       * --committer-date-is-author-date
       * --ignore-date
    -  * --whitespace
     - * --ignore-whitespace
    +  * --whitespace
       * -C
      
    - are incompatible with the following options:
     @@ Documentation/git-rebase.txt: 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=
     + * --preserve-merges and --ignore-whitespace
    -  * --rebase-merges and --strategy
    -  * --rebase-merges and --strategy-option
    +  * --keep-base and --onto
    +  * --keep-base and --root
      
     
      ## builtin/rebase.c ##
     @@ builtin/rebase.c: struct rebase_options {
    + 	int signoff;
      	int allow_rerere_autoupdate;
    - 	int keep_empty;
      	int autosquash;
     +	int ignore_whitespace;
      	char *gpg_sign_opt;
    @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_
     +	if (strategy_buf.len)
     +		parse_strategy_opts(&replay, strategy_buf.buf);
      
    + 	if (opts->squash_onto) {
    + 		oidcpy(&replay.squash_onto, opts->squash_onto);
    + 		replay.have_squash_onto = 1;
    + 	}
    + 
     +	strbuf_release(&strategy_buf);
      	return replay;
      }
      
     @@ builtin/rebase.c: int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
    - 	argc = parse_options(argc, argv, NULL, options,
    + 	argc = parse_options(argc, argv, prefix, options,
      			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
      
     +	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
    @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {
      test_rebase_am_only -C4
      
     
    - ## t/t3433-rebase-options-compatibility.sh (new) ##
    + ## t/t3436-rebase-more-options.sh (new) ##
     @@
     +#!/bin/sh
     +#
    @@ t/t3433-rebase-options-compatibility.sh (new)
     +
     +. ./test-lib.sh
     +
    ++. "$TEST_DIRECTORY"/lib-rebase.sh
    ++
     +# This is a special case in which both am and interactive backends
     +# provide the same output. It was done intentionally because
     +# both the backends fall short of optimal behaviour.
    @@ t/t3433-rebase-options-compatibility.sh (new)
     +	git tag main
     +'
     +
    -+test_expect_success '--ignore-whitespace works with am backend' '
    ++test_expect_success '--ignore-whitespace works with apply backend' '
     +	cat >expect <<-\EOF &&
     +	line 1
     +	new line 2
     +	line 3
     +	EOF
    -+	test_must_fail git rebase main side &&
    ++	test_must_fail git rebase --apply main side &&
     +	git rebase --abort &&
    -+	git rebase --ignore-whitespace main side &&
    ++	git rebase --apply --ignore-whitespace main side &&
     +	test_cmp expect file
     +'
     +
    -+test_expect_success '--ignore-whitespace works with interactive backend' '
    ++test_expect_success '--ignore-whitespace works with merge backend' '
     +	cat >expect <<-\EOF &&
     +	line 1
     +	new line 2
    @@ t/t3433-rebase-options-compatibility.sh (new)
     +	test_cmp expect file
     +'
     +
    ++test_expect_success '--ignore-whitespace is remembered when continuing' '
    ++	cat >expect <<-\EOF &&
    ++	line 1
    ++	new line 2
    ++	line 3
    ++	EOF
    ++	(
    ++		set_fake_editor &&
    ++		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
    ++	) &&
    ++	git rebase --continue &&
    ++	test_cmp expect file
    ++'
    ++
    ++# This must be the last test in this file
    ++test_expect_success '$EDITOR and friends are unchanged' '
    ++	test_editor_unchanged
    ++'
    ++
     +test_done
2:  c068bcc59b < -:  ---------- sequencer: allow callers of read_author_script() to ignore fields
3:  cbd8db17ac ! 2:  55eb3a7efc rebase -i: support --committer-date-is-author-date
    @@
      ## Metadata ##
    -Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    +Author: Phillip Wood <phillip.wood@dunelm.org.uk>
     
      ## Commit message ##
         rebase -i: support --committer-date-is-author-date
     
    -    rebase am already has this flag to "lie" about the committer date
    -    by changing it to the author date. Let's add the same for
    -    interactive machinery.
    +    As part of the on-going effort to retire the apply rebase backend teach
    +    the merge backend how to handle --committer-date-is-author-date.
     
    -    Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>
    +    Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    +    Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
     
      ## Documentation/git-rebase.txt ##
    -@@ Documentation/git-rebase.txt: unchanged for the sake of a three-way merge.
    +@@ Documentation/git-rebase.txt: when merging.
      See also INCOMPATIBLE OPTIONS below.
      
      --committer-date-is-author-date::
    -+	Instead of recording the time the rebased commits are
    -+	created as the committer date, reuse the author date
    -+	as the committer date. This implies --force-rebase.
    ++	Instead of using the current time as the committer date, use
    ++	the author date of the commit being rebased as the committer
    ++	date. This option implies --force-rebase.
     +
      --ignore-date::
     -	These flags are passed to 'git am' to easily change the dates
    @@ Documentation/git-rebase.txt: unchanged for the sake of a three-way merge.
      See also INCOMPATIBLE OPTIONS below.
      
     @@ Documentation/git-rebase.txt: INCOMPATIBLE OPTIONS
    - 
      The following options:
      
    +  * --apply
     - * --committer-date-is-author-date
       * --ignore-date
       * --whitespace
       * -C
     @@ Documentation/git-rebase.txt: In addition, the following pairs of options are incompatible:
    -  * --preserve-merges and --signoff
       * --preserve-merges and --rebase-merges
    +  * --preserve-merges and --empty=
       * --preserve-merges and --ignore-whitespace
     + * --preserve-merges and --committer-date-is-author-date
    -  * --rebase-merges and --strategy
    -  * --rebase-merges and --strategy-option
    +  * --keep-base and --onto
    +  * --keep-base and --root
      
     
      ## builtin/rebase.c ##
    @@ builtin/rebase.c: struct rebase_options {
      	int allow_empty_message;
      	int rebase_merges, rebase_cousins;
     @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_options *opts)
    - 	replay.allow_empty_message = opts->allow_empty_message;
    + 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
      	replay.verbose = opts->flags & REBASE_VERBOSE;
      	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
     +	replay.committer_date_is_author_date =
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
      		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
    - 		    state_dir_base, cmd_live_rebase, buf.buf);
    + 	    options.autosquash) {
    + 		allow_preemptive_ff = 0;
      	}
    - 
     +	if (options.committer_date_is_author_date)
     +		options.flags |= REBASE_FORCE;
    -+
    + 
      	for (i = 0; i < options.git_am_opts.argc; i++) {
      		const char *option = options.git_am_opts.argv[i], *p;
     -		if (!strcmp(option, "--committer-date-is-author-date") ||
     -		    !strcmp(option, "--ignore-date") ||
     +		if (!strcmp(option, "--ignore-date") ||
      		    !strcmp(option, "--whitespace=fix") ||
      		    !strcmp(option, "--whitespace=strip"))
    - 			options.flags |= REBASE_FORCE;
    + 			allow_preemptive_ff = 0;
     
      ## sequencer.c ##
     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
    @@ sequencer.c: static char *get_author(const char *message)
      	return NULL;
      }
      
    -+/* Returns a "date" string that needs to be free()'d by the caller */
    -+static char *read_author_date_or_null(void)
    ++static const char *author_date_from_env_array(const struct argv_array *env)
     +{
    -+	char *date;
    ++	int i;
    ++	const char *date;
     +
    -+	if (read_author_script(rebase_path_author_script(),
    -+			       NULL, NULL, &date, 0))
    -+		return NULL;
    -+	return date;
    ++	for (i = 0; i < env->argc; i++)
    ++		if (skip_prefix(env->argv[i],
    ++				"GIT_AUTHOR_DATE=", &date))
    ++			return date;
    ++	/*
    ++	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
    ++	 * reading the script
    ++	 */
    ++	BUG("GIT_AUTHOR_DATE missing from author script");
     +}
     +
      static const char staged_changes_advice[] =
      N_("you have staged changes in your working tree\n"
      "If these changes are meant to be squashed into the previous commit, run:\n"
     @@ sequencer.c: static int run_git_commit(struct repository *r,
    + 			     gpg_opt, gpg_opt);
    + 	}
      
    - 	cmd.git_cmd = 1;
    - 
    -+	if (opts->committer_date_is_author_date) {
    -+		int res = -1;
    -+		struct strbuf datebuf = STRBUF_INIT;
    -+		char *date = read_author_date_or_null();
    -+
    -+		if (!date)
    -+			return -1;
    -+
    -+		strbuf_addf(&datebuf, "@%s", date);
    -+		res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
    -+
    -+		strbuf_release(&datebuf);
    -+		free(date);
    -+
    -+		if (res)
    -+			return -1;
    -+	}
    ++	if (opts->committer_date_is_author_date)
    ++		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
    ++				 author_date_from_env_array(&cmd.env_array));
     +
    - 	if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {
    - 		const char *gpg_opt = gpg_sign_opt_quoted(opts);
    + 	argv_array_push(&cmd.args, "commit");
      
    + 	if (!(flags & VERIFY_MSG))
     @@ sequencer.c: static int try_to_commit(struct repository *r,
      
      	if (parse_head(r, &current_head))
      		return -1;
     -
      	if (flags & AMEND_MSG) {
    - 		const char *exclude_gpgsig[] = { "gpgsig", NULL };
    + 		const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
      		const char *out_enc = get_commit_output_encoding();
     @@ sequencer.c: static int try_to_commit(struct repository *r,
      		commit_list_insert(current_head, &parents);
    @@ sequencer.c: static int try_to_commit(struct repository *r,
     +		struct strbuf date = STRBUF_INIT;
     +
     +		if (split_ident_line(&ident, author, len) < 0) {
    -+			res = error(_("malformed ident line"));
    ++			res = error(_("malformed ident line '%s'"), author);
     +			goto out;
     +		}
     +		if (!ident.date_begin) {
    @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)
      			opts->reschedule_failed_exec = 1;
      
     @@ sequencer.c: 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");
    + 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
    + 	if (opts->keep_redundant_commits)
    + 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
     +	if (opts->committer_date_is_author_date)
     +		write_file(rebase_path_cdate_is_adate(), "%s", "");
      	if (opts->reschedule_failed_exec)
      		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
      
    +@@ sequencer.c: static int do_merge(struct repository *r,
    + 			goto leave_merge;
    + 		}
    + 
    ++		if (opts->committer_date_is_author_date)
    ++			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
    ++					 author_date_from_env_array(&cmd.env_array));
    ++
    + 		cmd.git_cmd = 1;
    + 		argv_array_push(&cmd.args, "merge");
    + 		argv_array_push(&cmd.args, "-s");
     @@ sequencer.c: static int pick_commits(struct repository *r,
      	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
      	if (opts->allow_ff)
    @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {
      
      test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
     
    - ## t/t3433-rebase-options-compatibility.sh ##
    -@@ t/t3433-rebase-options-compatibility.sh: test_description='tests to ensure compatibility between am and interactive backe
    + ## t/t3436-rebase-more-options.sh ##
    +@@ t/t3436-rebase-more-options.sh: test_description='tests to ensure compatibility between am and interactive backe
      
    - . ./test-lib.sh
    + . "$TEST_DIRECTORY"/lib-rebase.sh
      
     +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
     +export GIT_AUTHOR_DATE
     +
      # This is a special case in which both am and interactive backends
      # provide the same output. It was done intentionally because
      # both the backends fall short of optimal behaviour.
    -@@ t/t3433-rebase-options-compatibility.sh: test_expect_success 'setup' '
    +@@ t/t3436-rebase-more-options.sh: test_expect_success 'setup' '
      	EOF
      	git commit -am "update file" &&
      	git tag side &&
    @@ t/t3433-rebase-options-compatibility.sh: test_expect_success 'setup' '
      	sed -e "s/^|//" >file <<-\EOF &&
      	|line 1
      	|        line 2
    -@@ t/t3433-rebase-options-compatibility.sh: test_expect_success '--ignore-whitespace works with interactive backend' '
    +@@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-whitespace is remembered when continuing' '
      	test_cmp expect file
      '
      
    -+test_expect_success '--committer-date-is-author-date works with am backend' '
    -+	git commit --amend &&
    -+	git rebase --committer-date-is-author-date HEAD^ &&
    -+	git show HEAD --pretty="format:%ai" >authortime &&
    -+	git show HEAD --pretty="format:%ci" >committertime &&
    ++test_expect_success '--committer-date-is-author-date works with apply backend' '
    ++	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
    ++	git rebase --apply --committer-date-is-author-date HEAD^ &&
    ++	git log -1 --pretty="format:%ai" >authortime &&
    ++	git log -1 --pretty="format:%ci" >committertime &&
     +	test_cmp authortime committertime
     +'
     +
    -+test_expect_success '--committer-date-is-author-date works with interactive backend' '
    -+	git commit --amend &&
    -+	git rebase -i --committer-date-is-author-date HEAD^ &&
    -+	git show HEAD --pretty="format:%ai" >authortime &&
    -+	git show HEAD --pretty="format:%ci" >committertime &&
    ++test_expect_success '--committer-date-is-author-date works with merge backend' '
    ++	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
    ++	git rebase -m --committer-date-is-author-date HEAD^ &&
    ++	git log -1 --pretty="format:%ai" >authortime &&
    ++	git log -1 --pretty="format:%ci" >committertime &&
     +	test_cmp authortime committertime
     +'
     +
     +test_expect_success '--committer-date-is-author-date works with rebase -r' '
     +	git checkout side &&
    -+	git merge --no-ff commit3 &&
    ++	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
     +	git rebase -r --root --committer-date-is-author-date &&
    -+	git rev-list HEAD >rev_list &&
    -+	while read HASH
    -+	do
    -+		git show $HASH --pretty="format:%ai" >authortime
    -+		git show $HASH --pretty="format:%ci" >committertime
    -+		test_cmp authortime committertime
    -+	done <rev_list
    ++	git log --pretty="format:%ai" >authortime &&
    ++	git log --pretty="format:%ci" >committertime &&
    ++	test_cmp authortime committertime
     +'
     +
    - test_done
    ++test_expect_success '--committer-date-is-author-date works when forking merge' '
    ++	git checkout side &&
    ++	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
    ++	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
    ++	git log --pretty="format:%ai" >authortime &&
    ++	git log --pretty="format:%ci" >committertime &&
    ++	test_cmp authortime committertime
    ++
    ++'
    ++
    ++test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
    ++	git checkout commit2 &&
    ++	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
    ++	git log -1 --format=%at HEAD >expect &&
    ++	test_must_fail git rebase -m --committer-date-is-author-date \
    ++		--onto HEAD^^ HEAD^ &&
    ++	echo resolved > foo &&
    ++	git add foo &&
    ++	git rebase --continue &&
    ++	git log -1 --format=%ct HEAD >actual &&
    ++	test_cmp expect actual
    ++'
    ++
    + # This must be the last test in this file
    + test_expect_success '$EDITOR and friends are unchanged' '
    + 	test_editor_unchanged
4:  0185c683c9 ! 3:  19352fdc22 sequencer: rename amend_author to author_to_rename
    @@ Metadata
     Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
     
      ## Commit message ##
    -    sequencer: rename amend_author to author_to_rename
    +    sequencer: rename amend_author to author_to_free
     
         The purpose of amend_author was to free() the malloc()'d string
    -    obtained from get_author() while amending a commit. But we can
    +    obtained from get_author() when amending a commit. But we can
         also use the variable to free() the author at our convenience.
         Rename it to convey this meaning.
     
         Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>
     
      ## sequencer.c ##
     @@ sequencer.c: static int try_to_commit(struct repository *r,
5:  08187b4cba ! 4:  5e971abb74 rebase -i: support --ignore-date
    @@
      ## Metadata ##
    -Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    +Author: Phillip Wood <phillip.wood@dunelm.org.uk>
     
      ## Commit message ##
         rebase -i: support --ignore-date
     
    -    rebase am already has this flag to "lie" about the author date
    -    by changing it to the committer (current) date. Let's add the same
    -    for interactive machinery.
    +    As part of the on-going effort to retire the apply rebase backend
    +    teach the merge backend how to handle --ignore-date. We take care to
    +    handle the combination of --ignore-date and
    +    --committer-date-is-author-date in the same way as the apply backend.
     
    -    Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>
    +    Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
    +    Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
     
      ## Documentation/git-rebase.txt ##
     @@ Documentation/git-rebase.txt: See also INCOMPATIBLE OPTIONS below.
    - 	as the committer date. This implies --force-rebase.
    + 	date. This option implies --force-rebase.
      
      --ignore-date::
     -	This flag is passed to 'git am' to change the author date
     -	of each rebased commit (see linkgit:git-am[1]).
    -+	Instead of using the given author date, reset it to the
    -+	current time. This implies --force-rebase.
    ++	Instead of using the author date of the original commit, use
    ++	the current time as the	author date of the rebased commit.  This
    ++	option implies `--force-rebase`.
      +
      See also INCOMPATIBLE OPTIONS below.
      
     @@ Documentation/git-rebase.txt: INCOMPATIBLE OPTIONS
    - 
      The following options:
      
    +  * --apply
     - * --ignore-date
       * --whitespace
       * -C
      
     @@ Documentation/git-rebase.txt: In addition, the following pairs of options are incompatible:
    -  * --preserve-merges and --rebase-merges
    +  * --preserve-merges and --empty=
       * --preserve-merges and --ignore-whitespace
       * --preserve-merges and --committer-date-is-author-date
     + * --preserve-merges and --ignore-date
    -  * --rebase-merges and --strategy
    -  * --rebase-merges and --strategy-option
    +  * --keep-base and --onto
    +  * --keep-base and --root
      
     
      ## builtin/rebase.c ##
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      				  N_("passed to 'git apply'"), 0),
      		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
    - 		    state_dir_base, cmd_live_rebase, buf.buf);
    + 	    options.autosquash) {
    + 		allow_preemptive_ff = 0;
      	}
    - 
     -	if (options.committer_date_is_author_date)
    -+	if (options.committer_date_is_author_date ||
    -+	    options.ignore_date)
    ++	if (options.committer_date_is_author_date || options.ignore_date)
      		options.flags |= REBASE_FORCE;
      
      	for (i = 0; i < options.git_am_opts.argc; i++) {
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
     -		    !strcmp(option, "--whitespace=fix") ||
     +		if (!strcmp(option, "--whitespace=fix") ||
      		    !strcmp(option, "--whitespace=strip"))
    - 			options.flags |= REBASE_FORCE;
    + 			allow_preemptive_ff = 0;
      		else if (skip_prefix(option, "-C", &p)) {
     
      ## sequencer.c ##
    @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs
      static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
      static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
      static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
    -@@ sequencer.c: static char *read_author_date_or_null(void)
    - 	return date;
    +@@ sequencer.c: static const char *author_date_from_env_array(const struct argv_array *env)
    + 	BUG("GIT_AUTHOR_DATE missing from author script");
      }
      
     +/* Construct a free()able author string with current time as the author date */
    @@ sequencer.c: static char *read_author_date_or_null(void)
     +	struct strbuf new_author = STRBUF_INIT;
     +
     +	if (split_ident_line(&ident, author, len) < 0) {
    -+		error(_("malformed ident line"));
    ++		error(_("malformed ident line '%s'"), author);
     +		return NULL;
     +	}
     +	len = ident.mail_end - ident.name_begin + 1;
    @@ sequencer.c: static char *read_author_date_or_null(void)
     +	datestamp(&new_author);
     +	return strbuf_detach(&new_author, NULL);
     +}
    -+
    -+static void push_dates(struct child_process *child, int change_committer_date)
    -+{
    -+	time_t now = time(NULL);
    -+	struct strbuf date = STRBUF_INIT;
    -+
    -+	strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
    -+	argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
    -+	if (change_committer_date)
    -+		argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
    -+	strbuf_release(&date);
    -+}
     +
      static const char staged_changes_advice[] =
      N_("you have staged changes in your working tree\n"
      "If these changes are meant to be squashed into the previous commit, run:\n"
     @@ sequencer.c: static int run_git_commit(struct repository *r,
    - 			return -1;
      
    - 		strbuf_addf(&datebuf, "@%s", date);
    --		res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
    -+		res = setenv("GIT_COMMITTER_DATE",
    -+			     opts->ignore_date ? "" : datebuf.buf, 1);
    - 
    - 		strbuf_release(&datebuf);
    - 		free(date);
    -@@ sequencer.c: static int run_git_commit(struct repository *r,
    - 		argv_array_push(&cmd.args, "--amend");
    - 	if (opts->gpg_sign)
    - 		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
    + 	if (opts->committer_date_is_author_date)
    + 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
    ++				 opts->ignore_date ?
    ++				 "" :
    + 				 author_date_from_env_array(&cmd.env_array));
     +	if (opts->ignore_date)
    -+		push_dates(&cmd, opts->committer_date_is_author_date);
    - 	if (defmsg)
    - 		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
    - 	else if (!(flags & EDIT_MSG))
    ++		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
    + 
    + 	argv_array_push(&cmd.args, "commit");
    + 
     @@ sequencer.c: static int try_to_commit(struct repository *r,
      		strbuf_addf(&date, "@%.*s %.*s",
      			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
    @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)
      			opts->reschedule_failed_exec = 1;
      
     @@ sequencer.c: int write_basic_state(struct replay_opts *opts, const char *head_name,
    - 		write_file(rebase_path_signoff(), "--signoff\n");
    + 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
      	if (opts->committer_date_is_author_date)
      		write_file(rebase_path_cdate_is_adate(), "%s", "");
     +	if (opts->ignore_date)
    @@ sequencer.c: int write_basic_state(struct replay_opts *opts, const char *head_na
      		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
      
     @@ sequencer.c: static int do_merge(struct repository *r,
    - 		argv_array_push(&cmd.args, git_path_merge_msg(r));
    - 		if (opts->gpg_sign)
    - 			argv_array_push(&cmd.args, opts->gpg_sign);
    + 
    + 		if (opts->committer_date_is_author_date)
    + 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
    ++					 opts->ignore_date ?
    ++					 "" :
    + 					 author_date_from_env_array(&cmd.env_array));
     +		if (opts->ignore_date)
    -+			push_dates(&cmd, opts->committer_date_is_author_date);
    ++			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
      
    - 		/* Add the tips to be merged */
    - 		for (j = to_merge; j; j = j->next)
    + 		cmd.git_cmd = 1;
    + 		argv_array_push(&cmd.args, "merge");
     @@ sequencer.c: static int pick_commits(struct repository *r,
      	if (opts->allow_ff)
      		assert(!(opts->signoff || opts->no_commit ||
    @@ sequencer.h: struct replay_opts {
      	int mainline;
      
     
    - ## t/t3433-rebase-options-compatibility.sh ##
    -@@ t/t3433-rebase-options-compatibility.sh: test_expect_success '--committer-date-is-author-date works with rebase -r' '
    - 	done <rev_list
    + ## t/t3436-rebase-more-options.sh ##
    +@@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-date works when committing confl
    + 	test_cmp expect actual
      '
      
     +# Checking for +0000 in author time is enough since default
     +# timezone is UTC, but the timezone used while committing
     +# sets to +0530.
    -+test_expect_success '--ignore-date works with am backend' '
    ++test_expect_success '--ignore-date works with apply backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
    -+	git rebase --ignore-date HEAD^ &&
    -+	git show HEAD --pretty="format:%ai" >authortime &&
    ++	git rebase --apply --ignore-date HEAD^ &&
    ++	git log -1 --pretty="format:%ai" >authortime &&
     +	grep "+0000" authortime
     +'
     +
    -+test_expect_success '--ignore-date works with interactive backend' '
    ++test_expect_success '--ignore-date works with merge backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
    -+	git rebase --ignore-date -i HEAD^ &&
    -+	git show HEAD --pretty="format:%ai" >authortime &&
    ++	git rebase --ignore-date -m HEAD^ &&
    ++	git log -1 --pretty="format:%ai" >authortime &&
     +	grep "+0000" authortime
     +'
     +
    ++test_expect_success '--ignore-date works after conflict resolution' '
    ++	test_must_fail git rebase --ignore-date -m \
    ++		--onto commit2^^ commit2^ commit2 &&
    ++	echo resolved >foo &&
    ++	git add foo &&
    ++	git rebase --continue &&
    ++	git log --pretty=%ai >authortime &&
    ++	grep +0000 authortime
    ++'
    ++
     +test_expect_success '--ignore-date works with rebase -r' '
     +	git checkout side &&
     +	git merge --no-ff commit3 &&
     +	git rebase -r --root --ignore-date &&
    -+	git rev-list HEAD >rev_list &&
    -+	while read HASH
    -+	do
    -+		git show $HASH --pretty="format:%ai" >authortime
    -+		grep "+0000" authortime
    -+	done <rev_list
    ++	git log --pretty=%ai >authortime &&
    ++	! grep -v "+0000" authortime
     +'
     +
    - test_done
    ++test_expect_success '--ignore-date with --committer-date-is-author-date works' '
    ++	test_must_fail git rebase -m --committer-date-is-author-date \
    ++		--ignore-date --onto commit2^^ commit2^ commit3 &&
    ++	git checkout --theirs foo &&
    ++	git add foo &&
    ++	git rebase --continue &&
    ++	git log -2 --pretty=%ai >authortime &&
    ++	git log -2 --pretty=%ci >committertime &&
    ++	test_cmp authortime committertime &&
    ++	! grep -v "+0000" authortime
    ++'
    ++
    ++test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
    ++	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
    ++		git rebase -i --strategy=resolve --ignore-date \
    ++		--committer-date-is-author-date side side &&
    ++	git log -1 --pretty=%ai >authortime &&
    ++	git log -1 --pretty=%ci >committertime &&
    ++	test_cmp authortime committertime &&
    ++	grep "+0000" authortime
    ++ '
    ++
    + # This must be the last test in this file
    + test_expect_success '$EDITOR and friends are unchanged' '
    + 	test_editor_unchanged
6:  fe28ad8520 < -:  ---------- rebase: add --reset-author-date
7:  d82dfa7f5b < -:  ---------- rebase -i: finishing touches to --reset-author-date
-:  ---------- > 5:  43a097c583 rebase: add --reset-author-date
-- 
2.26.2


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
@ 2020-04-29 10:25   ` Phillip Wood
  2020-05-13  3:54     ` Elijah Newren
  2020-04-29 10:25   ` [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-04-29 10:25 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List
  Cc: Phillip Wood

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

Rebase is implemented with two different backends - 'apply' and 'merge'
each of which support a different set of options. In particuar the apply
backend supports a number of options implemented by 'git am' that are
not available to the merge backend. As part of an on going effort to
remove the apply backend this patch adds support for the
--ignore-whitespace option to the merge backend. This option treats
lines with only whitespace changes as unchanged and is implemented in
the merge backend by translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 12 +++-
 builtin/rebase.c                       | 19 ++++--
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++
 4 files changed, 111 insertions(+), 7 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f7a6033607..d060c143e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -422,8 +422,16 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Behaves differently depending on which backend is selected.
++
+apply backend: When applying a patch, ignore changes in whitespace in
+context lines.
++
+merge backend: Treat lines with only whitespace changes as unchanged
+when merging.
+
 --whitespace=<option>::
-	These flags are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 	Implies --apply.
 +
@@ -572,7 +580,6 @@ The following options:
  * --apply
  * --committer-date-is-author-date
  * --ignore-date
- * --ignore-whitespace
  * --whitespace
  * -C
 
@@ -598,6 +605,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 27a07d4e78..5d8e117276 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -86,6 +86,7 @@ struct rebase_options {
 	int signoff;
 	int allow_rerere_autoupdate;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -108,6 +109,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	struct strbuf strategy_buf = STRBUF_INIT;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
+	if (opts->ignore_whitespace)
+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
+	if (strategy_buf.len)
+		parse_strategy_opts(&replay, strategy_buf.buf);
 
 	if (opts->squash_onto) {
 		oidcpy(&replay.squash_onto, opts->squash_onto);
 		replay.have_squash_onto = 1;
 	}
 
+	strbuf_release(&strategy_buf);
 	return replay;
 }
 
@@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
new file mode 100755
index 0000000000..fb5e747e86
--- /dev/null
+++ b/t/t3436-rebase-more-options.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with apply backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --apply main side &&
+	git rebase --abort &&
+	git rebase --apply --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with merge backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
+	) &&
+	git rebase --continue &&
+	test_cmp expect file
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
+test_done
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
  2020-04-29 10:25   ` [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-04-29 10:25   ` Phillip Wood
  2020-05-10 11:14     ` Alban Gruin
  2020-05-13  4:08     ` Elijah Newren
  2020-04-29 10:25   ` [PATCH v2 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
                     ` (3 subsequent siblings)
  5 siblings, 2 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-29 10:25 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

As part of the on-going effort to retire the apply rebase backend teach
the merge backend how to handle --committer-date-is-author-date.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 10 +++--
 builtin/rebase.c                       | 16 ++++---
 sequencer.c                            | 60 +++++++++++++++++++++++++-
 sequencer.h                            |  1 +
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++
 6 files changed, 133 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index d060c143e6..8c62645b8c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -438,9 +438,13 @@ when merging.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of using the current time as the committer date, use
+	the author date of the commit being rebased as the committer
+	date. This option implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -578,7 +582,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -606,6 +609,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5d8e117276..357cd6acf3 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -89,6 +89,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
diff --git a/sequencer.c b/sequencer.c
index 6fd2674632..3bb80d7414 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -872,6 +873,22 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+static const char *author_date_from_env_array(const struct argv_array *env)
+{
+	int i;
+	const char *date;
+
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
 			     gpg_opt, gpg_opt);
 	}
 
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 author_date_from_env_array(&cmd.env_array));
+
 	argv_array_push(&cmd.args, "commit");
 
 	if (!(flags & VERIFY_MSG))
@@ -1321,7 +1342,6 @@ static int try_to_commit(struct repository *r,
 
 	if (parse_head(r, &current_head))
 		return -1;
-
 	if (flags & AMEND_MSG) {
 		const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
 		const char *out_enc = get_commit_output_encoding();
@@ -1349,6 +1369,30 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, len) < 0) {
+			res = error(_("malformed ident line '%s'"), author);
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2532,6 +2576,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2671,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
 	if (opts->keep_redundant_commits)
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3542,6 +3593,10 @@ static int do_merge(struct repository *r,
 			goto leave_merge;
 		}
 
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 author_date_from_env_array(&cmd.env_array));
+
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
 		argv_array_push(&cmd.args, "-s");
@@ -3819,7 +3874,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 0bee85093e..4ab94119ae 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -45,6 +45,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index fb5e747e86..84b9d5d37f 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -28,8 +31,13 @@ test_expect_success 'setup' '
 	EOF
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	git rm --cached foo &&
+	rm foo &&
 	sed -e "s/^|//" >file <<-\EOF &&
 	|line 1
 	|        line 2
@@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with apply backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase --apply --committer-date-is-author-date HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with merge backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase -m --committer-date-is-author-date HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	git log --pretty="format:%ai" >authortime &&
+	git log --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
+	git log --pretty="format:%ai" >authortime &&
+	git log --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	git log -1 --format=%at HEAD >expect &&
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -1 --format=%ct HEAD >actual &&
+	test_cmp expect actual
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 3/5] sequencer: rename amend_author to author_to_free
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
  2020-04-29 10:25   ` [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-04-29 10:25   ` [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-04-29 10:25   ` Phillip Wood
  2020-04-29 10:25   ` [PATCH v2 4/5] rebase -i: support --ignore-date Phillip Wood
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-29 10:25 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() when amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 3bb80d7414..8dff8b9b95 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1356,7 +1356,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1472,7 +1472,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 4/5] rebase -i: support --ignore-date
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                     ` (2 preceding siblings ...)
  2020-04-29 10:25   ` [PATCH v2 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
@ 2020-04-29 10:25   ` Phillip Wood
  2020-05-10 11:14     ` Alban Gruin
  2020-05-13  3:54     ` Elijah Newren
  2020-04-29 10:25   ` [PATCH v2 5/5] rebase: add --reset-author-date Phillip Wood
  2020-04-29 19:59   ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 2 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-29 10:25 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

As part of the on-going effort to retire the apply rebase backend
teach the merge backend how to handle --ignore-date. We take care to
handle the combination of --ignore-date and
--committer-date-is-author-date in the same way as the apply backend.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt   |  7 +++--
 builtin/rebase.c               | 13 +++++---
 sequencer.c                    | 49 +++++++++++++++++++++++++++--
 sequencer.h                    |  1 +
 t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 8c62645b8c..96c7125791 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -443,8 +443,9 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the author date of the original commit, use
+	the current time as the	author date of the rebased commit.  This
+	option implies `--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -582,7 +583,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --ignore-date
  * --whitespace
  * -C
 
@@ -610,6 +610,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 357cd6acf3..cf86240bc8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -90,6 +90,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date || options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index 8dff8b9b95..339dbf4a59 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
 	BUG("GIT_AUTHOR_DATE missing from author script");
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, len) < 0) {
+		error(_("malformed ident line '%s'"), author);
+		return NULL;
+	}
+	len = ident.mail_end - ident.name_begin + 1;
+
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
 
 	if (opts->committer_date_is_author_date)
 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
 				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,
 		strbuf_addf(&date, "@%.*s %.*s",
 			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
 			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
 		strbuf_release(&date);
 
 		if (res)
@@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2581,6 +2614,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2673,6 +2711,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3595,7 +3635,11 @@ static int do_merge(struct repository *r,
 
 		if (opts->committer_date_is_author_date)
 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
 					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3875,7 +3919,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 4ab94119ae..3587878e3b 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -46,6 +46,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 84b9d5d37f..6cd3848689 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 	test_cmp expect actual
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with apply backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with merge backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -m HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -m \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log --pretty=%ai >authortime &&
+	grep +0000 authortime
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	git log --pretty=%ai >authortime &&
+	! grep -v "+0000" authortime
+'
+
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -2 --pretty=%ai >authortime &&
+	git log -2 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	! grep -v "+0000" authortime
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		git rebase -i --strategy=resolve --ignore-date \
+		--committer-date-is-author-date side side &&
+	git log -1 --pretty=%ai >authortime &&
+	git log -1 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	grep "+0000" authortime
+ '
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v2 5/5] rebase: add --reset-author-date
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                     ` (3 preceding siblings ...)
  2020-04-29 10:25   ` [PATCH v2 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-04-29 10:25   ` Phillip Wood
  2020-04-29 19:59   ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-04-29 10:25 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The previous commit introduced --ignore-date flag to rebase -i, but the
name is rather vague as it does not say whether the author date or the
committer date is ignored. Add an alias to convey the precise purpose.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt   |  1 +
 builtin/rebase.c               |  6 ++++--
 t/t3436-rebase-more-options.sh | 34 ++++++++++++++++++++++------------
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 96c7125791..0020b97110 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -443,6 +443,7 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the author date of the original commit, use
 	the current time as the	author date of the rebased commit.  This
 	option implies `--force-rebase`.
diff --git a/builtin/rebase.c b/builtin/rebase.c
index cf86240bc8..911587690b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1519,8 +1519,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
-			 "ignore author date and use current date"),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 6cd3848689..2ee7346562 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -137,22 +137,22 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 # Checking for +0000 in author time is enough since default
 # timezone is UTC, but the timezone used while committing
 # sets to +0530.
-test_expect_success '--ignore-date works with apply backend' '
+test_expect_success '--reset-author-date works with apply backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --apply --ignore-date HEAD^ &&
+	git rebase --apply --reset-author-date HEAD^ &&
 	git log -1 --pretty="format:%ai" >authortime &&
 	grep "+0000" authortime
 '
 
-test_expect_success '--ignore-date works with merge backend' '
+test_expect_success '--reset-author-date works with merge backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --ignore-date -m HEAD^ &&
+	git rebase --reset-author-date -m HEAD^ &&
 	git log -1 --pretty="format:%ai" >authortime &&
 	grep "+0000" authortime
 '
 
-test_expect_success '--ignore-date works after conflict resolution' '
-	test_must_fail git rebase --ignore-date -m \
+test_expect_success '--reset-author-date works after conflict resolution' '
+	test_must_fail git rebase --reset-author-date -m \
 		--onto commit2^^ commit2^ commit2 &&
 	echo resolved >foo &&
 	git add foo &&
@@ -161,17 +161,17 @@ test_expect_success '--ignore-date works after conflict resolution' '
 	grep +0000 authortime
 '
 
-test_expect_success '--ignore-date works with rebase -r' '
+test_expect_success '--reset-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
-	git rebase -r --root --ignore-date &&
+	git rebase -r --root --reset-author-date &&
 	git log --pretty=%ai >authortime &&
 	! grep -v "+0000" authortime
 '
 
-test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
 	test_must_fail git rebase -m --committer-date-is-author-date \
-		--ignore-date --onto commit2^^ commit2^ commit3 &&
+		--reset-author-date --onto commit2^^ commit2^ commit3 &&
 	git checkout --theirs foo &&
 	git add foo &&
 	git rebase --continue &&
@@ -181,16 +181,26 @@ test_expect_success '--ignore-date with --committer-date-is-author-date works' '
 	! grep -v "+0000" authortime
 '
 
-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
 	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
-		git rebase -i --strategy=resolve --ignore-date \
+		git rebase -i --strategy=resolve --reset-author-date \
 		--committer-date-is-author-date side side &&
 	git log -1 --pretty=%ai >authortime &&
 	git log -1 --pretty=%ci >committertime &&
 	test_cmp authortime committertime &&
 	grep "+0000" authortime
  '
 
+test_expect_success '--ignore-date is an alias for --reset-author-date' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
+	git rebase -m --ignore-date HEAD^ &&
+	git log -2 --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime >output &&
+	test_line_count = 2 output
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 0/5] cleanup ra/rebase-i-more-options
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                     ` (4 preceding siblings ...)
  2020-04-29 10:25   ` [PATCH v2 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-04-29 19:59   ` Junio C Hamano
  2020-05-13  3:57     ` Elijah Newren
  5 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-04-29 19:59 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> I've rebased Rohit's patches on master and reworked them with my

OK, it took a bit of time for me to figure it out, but this does
cleanly apply on top of 048abe17 (Sync with 2.26.2, 2020-04-19).

Queued, but haven't taken any deep look at it.

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date
  2020-04-29 10:25   ` [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-05-10 11:14     ` Alban Gruin
  2020-05-13  4:08     ` Elijah Newren
  1 sibling, 0 replies; 130+ messages in thread
From: Alban Gruin @ 2020-05-10 11:14 UTC (permalink / raw)
  To: Phillip Wood, Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List

Hi Phillip,

Thank you for continuing this work.

Le 29/04/2020 à 12:25, Phillip Wood a écrit :
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
> 
> As part of the on-going effort to retire the apply rebase backend teach
> the merge backend how to handle --committer-date-is-author-date.
> 
> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt           | 10 +++--
>  builtin/rebase.c                       | 16 ++++---
>  sequencer.c                            | 60 +++++++++++++++++++++++++-
>  sequencer.h                            |  1 +
>  t/t3422-rebase-incompatible-options.sh |  1 -
>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++
>  6 files changed, 133 insertions(+), 11 deletions(-)
> 
> -%<-
>
> diff --git a/sequencer.c b/sequencer.c
> index 6fd2674632..3bb80d7414 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   * command-line.
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -872,6 +873,22 @@ static char *get_author(const char *message)
>  	return NULL;
>  }
>  
> +static const char *author_date_from_env_array(const struct argv_array *env)
> +{
> +	int i;
> +	const char *date;
> +
> +	for (i = 0; i < env->argc; i++)
> +		if (skip_prefix(env->argv[i],
> +				"GIT_AUTHOR_DATE=", &date))
> +			return date;
> +	/*
> +	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
> +	 * reading the script
> +	 */
> +	BUG("GIT_AUTHOR_DATE missing from author script");
> +}
> +

Since `GIT_AUTHOR_DATE' is set in read_env_script(), why not set
`GIT_COMMITTER_DATE' in this function too, instead of looping in the env
array just after setting it to get the value back?

>  static const char staged_changes_advice[] =
>  N_("you have staged changes in your working tree\n"
>  "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
>  			     gpg_opt, gpg_opt);
>  	}
>  
> +	if (opts->committer_date_is_author_date)
> +		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +				 author_date_from_env_array(&cmd.env_array));
> +
>  	argv_array_push(&cmd.args, "commit");
>  
>  	if (!(flags & VERIFY_MSG))
> @@ -1321,7 +1342,6 @@ static int try_to_commit(struct repository *r,
>  
>  	if (parse_head(r, &current_head))
>  		return -1;
> -

Nit: don't remove this empty line?

>  	if (flags & AMEND_MSG) {
>  		const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
>  		const char *out_enc = get_commit_output_encoding();

Cheers,
Alban


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 4/5] rebase -i: support --ignore-date
  2020-04-29 10:25   ` [PATCH v2 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-05-10 11:14     ` Alban Gruin
  2020-05-12 14:47       ` Phillip Wood
  2020-05-13  3:54     ` Elijah Newren
  1 sibling, 1 reply; 130+ messages in thread
From: Alban Gruin @ 2020-05-10 11:14 UTC (permalink / raw)
  To: Phillip Wood, Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Git Mailing List

Hi Phillip,

Le 29/04/2020 à 12:25, Phillip Wood a écrit :
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
> 
> As part of the on-going effort to retire the apply rebase backend
> teach the merge backend how to handle --ignore-date. We take care to
> handle the combination of --ignore-date and
> --committer-date-is-author-date in the same way as the apply backend.
> 
> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt   |  7 +++--
>  builtin/rebase.c               | 13 +++++---
>  sequencer.c                    | 49 +++++++++++++++++++++++++++--
>  sequencer.h                    |  1 +
>  t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++
>  5 files changed, 117 insertions(+), 10 deletions(-)
> 
> -%<-
>
> diff --git a/sequencer.c b/sequencer.c
> index 8dff8b9b95..339dbf4a59 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>  static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
>  	BUG("GIT_AUTHOR_DATE missing from author script");
>  }
>  
> +/* Construct a free()able author string with current time as the author date */
> +static char *ignore_author_date(const char *author)
> +{
> +	int len = strlen(author);
> +	struct ident_split ident;
> +	struct strbuf new_author = STRBUF_INIT;
> +
> +	if (split_ident_line(&ident, author, len) < 0) {
> +		error(_("malformed ident line '%s'"), author);
> +		return NULL;
> +	}

Nit: add an empty line here?

> +	len = ident.mail_end - ident.name_begin + 1;
> +
> +	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
> +	datestamp(&new_author);
> +	return strbuf_detach(&new_author, NULL);
> +}
> +
>  static const char staged_changes_advice[] =
>  N_("you have staged changes in your working tree\n"
>  "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
>  
>  	if (opts->committer_date_is_author_date)
>  		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +				 opts->ignore_date ?
> +				 "" :
>  				 author_date_from_env_array(&cmd.env_array));
> +	if (opts->ignore_date)
> +		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>  

Perhaps this could be done in read_env_script(), too, instead of fixing
up what this function did right after calling it, twice?  Something like
this:

---- snip ----
index 339dbf4a59..3a7a80bab7 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -840,11 +840,12 @@ int read_author_script(const char *path, char
**name, char **email, char **date,
 }

 /*
- * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL AND GIT_AUTHOR_DATE from a
- * file with shell quoting into struct argv_array. Returns -1 on
- * error, 0 otherwise.
+ * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL and GIT_AUTHOR_DATE from a
+ * file with shell quoting into struct argv_array, and set
+ * GIT_COMMITTER_DATE if needed. Returns -1 on error, 0 otherwise.
  */
-static int read_env_script(struct argv_array *env)
+static int read_env_script(struct replay_opts *opts,
+                          struct argv_array *env)
 {
        char *name, *email, *date;

@@ -854,7 +855,17 @@ static int read_env_script(struct argv_array *env)

        argv_array_pushf(env, "GIT_AUTHOR_NAME=%s", name);
        argv_array_pushf(env, "GIT_AUTHOR_EMAIL=%s", email);
-       argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
+
+       if (opts->ignore_date) {
+               argv_array_push(env, "GIT_AUTHOR_DATE=");
+               argv_array_push(env, "GIT_COMMITTER_DATE=");
+       } else {
+               argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
+
+               if (opts->committer_date_is_author_date)
+                       argv_array_pushf(env, "GIT_COMMITTER_DATE=%s",
date);
+       }
+
        free(name);
        free(email);
        free(date);
---- snap ----

>  	argv_array_push(&cmd.args, "commit");
>  
> @@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,
>  		strbuf_addf(&date, "@%.*s %.*s",
>  			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
>  			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> -		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		res = setenv("GIT_COMMITTER_DATE",
> +			     opts->ignore_date ? "" : date.buf, 1);
>  		strbuf_release(&date);
>  
>  		if (res)
> @@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,
>  
>  	reset_ident_date();
>  
> +	if (opts->ignore_date) {
> +		author = ignore_author_date(author);
> +		if (!author) {
> +			res = -1;
> +			goto out;
> +		}
> +		free(author_to_free);
> +		author_to_free = (char *)author;
> +	}

Nit: add an empty line here?

Cheers,
Alban


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 4/5] rebase -i: support --ignore-date
  2020-05-10 11:14     ` Alban Gruin
@ 2020-05-12 14:47       ` Phillip Wood
  2020-05-13 15:33         ` Junio C Hamano
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-12 14:47 UTC (permalink / raw)
  To: Alban Gruin, Phillip Wood, Johannes Schindelin, Junio C Hamano,
	Elijah Newren, Rohit Ashiwal, Git Mailing List

Hi Alban

Thanks for looking at this series

On 10/05/2020 12:14, Alban Gruin wrote:
> Hi Phillip,
> 
> Le 29/04/2020 à 12:25, Phillip Wood a écrit :
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> As part of the on-going effort to retire the apply rebase backend
>> teach the merge backend how to handle --ignore-date. We take care to
>> handle the combination of --ignore-date and
>> --committer-date-is-author-date in the same way as the apply backend.
>>
>> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>   Documentation/git-rebase.txt   |  7 +++--
>>   builtin/rebase.c               | 13 +++++---
>>   sequencer.c                    | 49 +++++++++++++++++++++++++++--
>>   sequencer.h                    |  1 +
>>   t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++
>>   5 files changed, 117 insertions(+), 10 deletions(-)
>>
>> -%<-
>>
>> diff --git a/sequencer.c b/sequencer.c
>> index 8dff8b9b95..339dbf4a59 100644
>> --- a/sequencer.c
>> +++ b/sequencer.c
>> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>>    */
>>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>>   static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
>> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
>>   	BUG("GIT_AUTHOR_DATE missing from author script");
>>   }
>>   
>> +/* Construct a free()able author string with current time as the author date */
>> +static char *ignore_author_date(const char *author)
>> +{
>> +	int len = strlen(author);
>> +	struct ident_split ident;
>> +	struct strbuf new_author = STRBUF_INIT;
>> +
>> +	if (split_ident_line(&ident, author, len) < 0) {
>> +		error(_("malformed ident line '%s'"), author);
>> +		return NULL;
>> +	}
> 
> Nit: add an empty line here?

and delete the one below?

>> +	len = ident.mail_end - ident.name_begin + 1;
>> +
>> +	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
>> +	datestamp(&new_author);
>> +	return strbuf_detach(&new_author, NULL);
>> +}
>> +
>>   static const char staged_changes_advice[] =
>>   N_("you have staged changes in your working tree\n"
>>   "If these changes are meant to be squashed into the previous commit, run:\n"
>> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
>>   
>>   	if (opts->committer_date_is_author_date)
>>   		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>> +				 opts->ignore_date ?
>> +				 "" :
>>   				 author_date_from_env_array(&cmd.env_array));
>> +	if (opts->ignore_date)
>> +		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>>   
> 
> Perhaps this could be done in read_env_script(), too, instead of fixing
> up what this function did right after calling it, twice?  Something like
> this:

Long term I'd like to stop writing the author-script file unless we're 
stopping for a conflict resolution or edit so I'm reluctant to add more 
functionality to it at the moment. Also I tend to view read_env_script() 
it as loading the author details from a file rather than setting up the 
environment for the commit.

> ---- snip ----
> index 339dbf4a59..3a7a80bab7 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -840,11 +840,12 @@ int read_author_script(const char *path, char
> **name, char **email, char **date,
>   }
> 
>   /*
> - * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL AND GIT_AUTHOR_DATE from a
> - * file with shell quoting into struct argv_array. Returns -1 on
> - * error, 0 otherwise.
> + * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL and GIT_AUTHOR_DATE from a
> + * file with shell quoting into struct argv_array, and set
> + * GIT_COMMITTER_DATE if needed. Returns -1 on error, 0 otherwise.
>    */
> -static int read_env_script(struct argv_array *env)
> +static int read_env_script(struct replay_opts *opts,
> +                          struct argv_array *env)
>   {
>          char *name, *email, *date;
> 
> @@ -854,7 +855,17 @@ static int read_env_script(struct argv_array *env)
> 
>          argv_array_pushf(env, "GIT_AUTHOR_NAME=%s", name);
>          argv_array_pushf(env, "GIT_AUTHOR_EMAIL=%s", email);
> -       argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
> +
> +       if (opts->ignore_date) {
> +               argv_array_push(env, "GIT_AUTHOR_DATE=");
> +               argv_array_push(env, "GIT_COMMITTER_DATE=");
> +       } else {
> +               argv_array_pushf(env, "GIT_AUTHOR_DATE=%s", date);
> +
> +               if (opts->committer_date_is_author_date)
> +                       argv_array_pushf(env, "GIT_COMMITTER_DATE=%s",
> date);
> +       }
> +
>          free(name);
>          free(email);
>          free(date);
> ---- snap ----
> 
>>   	argv_array_push(&cmd.args, "commit");
>>   
>> @@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,
>>   		strbuf_addf(&date, "@%.*s %.*s",
>>   			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
>>   			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
>> -		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
>> +		res = setenv("GIT_COMMITTER_DATE",
>> +			     opts->ignore_date ? "" : date.buf, 1);
>>   		strbuf_release(&date);
>>   
>>   		if (res)
>> @@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,
>>   
>>   	reset_ident_date();
>>   
>> +	if (opts->ignore_date) {
>> +		author = ignore_author_date(author);
>> +		if (!author) {
>> +			res = -1;
>> +			goto out;
>> +		}
>> +		free(author_to_free);
>> +		author_to_free = (char *)author;
>> +	}
> 
> Nit: add an empty line here?

Yes that would fit the style in the rest of the function

Best Wishes

Phillip

> 
> Cheers,
> Alban
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 4/5] rebase -i: support --ignore-date
  2020-04-29 10:25   ` [PATCH v2 4/5] rebase -i: support --ignore-date Phillip Wood
  2020-05-10 11:14     ` Alban Gruin
@ 2020-05-13  3:54     ` Elijah Newren
  1 sibling, 0 replies; 130+ messages in thread
From: Elijah Newren @ 2020-05-13  3:54 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal, Git Mailing List

On Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> As part of the on-going effort to retire the apply rebase backend
> teach the merge backend how to handle --ignore-date. We take care to
> handle the combination of --ignore-date and
> --committer-date-is-author-date in the same way as the apply backend.
>
> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt   |  7 +++--
>  builtin/rebase.c               | 13 +++++---
>  sequencer.c                    | 49 +++++++++++++++++++++++++++--
>  sequencer.h                    |  1 +
>  t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++
>  5 files changed, 117 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 8c62645b8c..96c7125791 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -443,8 +443,9 @@ See also INCOMPATIBLE OPTIONS below.
>         date. This option implies --force-rebase.
>
>  --ignore-date::
> -       This flag is passed to 'git am' to change the author date
> -       of each rebased commit (see linkgit:git-am[1]).
> +       Instead of using the author date of the original commit, use
> +       the current time as the author date of the rebased commit.  This
> +       option implies `--force-rebase`.
>  +
>  See also INCOMPATIBLE OPTIONS below.
>
> @@ -582,7 +583,6 @@ INCOMPATIBLE OPTIONS
>  The following options:
>
>   * --apply
> - * --ignore-date
>   * --whitespace
>   * -C
>
> @@ -610,6 +610,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --empty=
>   * --preserve-merges and --ignore-whitespace
>   * --preserve-merges and --committer-date-is-author-date
> + * --preserve-merges and --ignore-date
>   * --keep-base and --onto
>   * --keep-base and --root
>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 357cd6acf3..cf86240bc8 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -90,6 +90,7 @@ struct rebase_options {
>         char *gpg_sign_opt;
>         int autostash;
>         int committer_date_is_author_date;
> +       int ignore_date;
>         char *cmd;
>         int allow_empty_message;
>         int rebase_merges, rebase_cousins;
> @@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>         replay.committer_date_is_author_date =
>                                         opts->committer_date_is_author_date;
> +       replay.ignore_date = opts->ignore_date;
>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>         replay.strategy = opts->strategy;
>
> @@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)
>                 argv_array_push(&am.args, "--ignore-whitespace");
>         if (opts->committer_date_is_author_date)
>                 argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
> +       if (opts->ignore_date)
> +               argv_array_push(&opts->git_am_opts, "--ignore-date");
>         if (opts->action && !strcmp("continue", opts->action)) {
>                 argv_array_push(&am.args, "--resolved");
>                 argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>                 OPT_BOOL(0, "committer-date-is-author-date",
>                          &options.committer_date_is_author_date,
>                          N_("make committer date match author date")),
> -               OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
> -                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +               OPT_BOOL(0, "ignore-date", &options.ignore_date,
> +                        "ignore author date and use current date"),
>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>                                   N_("passed to 'git apply'"), 0),
>                 OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> @@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>             options.autosquash) {
>                 allow_preemptive_ff = 0;
>         }
> -       if (options.committer_date_is_author_date)
> +       if (options.committer_date_is_author_date || options.ignore_date)
>                 options.flags |= REBASE_FORCE;
>
>         for (i = 0; i < options.git_am_opts.argc; i++) {
>                 const char *option = options.git_am_opts.argv[i], *p;
> -               if (!strcmp(option, "--ignore-date") ||
> -                   !strcmp(option, "--whitespace=fix") ||
> +               if (!strcmp(option, "--whitespace=fix") ||
>                     !strcmp(option, "--whitespace=strip"))
>                         allow_preemptive_ff = 0;
>                 else if (skip_prefix(option, "-C", &p)) {
> diff --git a/sequencer.c b/sequencer.c
> index 8dff8b9b95..339dbf4a59 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>  static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
>         BUG("GIT_AUTHOR_DATE missing from author script");
>  }
>
> +/* Construct a free()able author string with current time as the author date */
> +static char *ignore_author_date(const char *author)
> +{
> +       int len = strlen(author);
> +       struct ident_split ident;
> +       struct strbuf new_author = STRBUF_INIT;
> +
> +       if (split_ident_line(&ident, author, len) < 0) {
> +               error(_("malformed ident line '%s'"), author);
> +               return NULL;
> +       }
> +       len = ident.mail_end - ident.name_begin + 1;
> +
> +       strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
> +       datestamp(&new_author);
> +       return strbuf_detach(&new_author, NULL);
> +}
> +
>  static const char staged_changes_advice[] =
>  N_("you have staged changes in your working tree\n"
>  "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
>
>         if (opts->committer_date_is_author_date)
>                 argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +                                opts->ignore_date ?
> +                                "" :
>                                  author_date_from_env_array(&cmd.env_array));
> +       if (opts->ignore_date)
> +               argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>
>         argv_array_push(&cmd.args, "commit");
>
> @@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,
>                 strbuf_addf(&date, "@%.*s %.*s",
>                             (int)(ident.date_end - ident.date_begin), ident.date_begin,
>                             (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> -               res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +               res = setenv("GIT_COMMITTER_DATE",
> +                            opts->ignore_date ? "" : date.buf, 1);
>                 strbuf_release(&date);
>
>                 if (res)
> @@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,
>
>         reset_ident_date();
>
> +       if (opts->ignore_date) {
> +               author = ignore_author_date(author);
> +               if (!author) {
> +                       res = -1;
> +                       goto out;
> +               }
> +               free(author_to_free);
> +               author_to_free = (char *)author;
> +       }
>         if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>                                  oid, author, opts->gpg_sign, extra)) {
>                 res = error(_("failed to write commit object"));
> @@ -2581,6 +2614,11 @@ static int read_populate_opts(struct replay_opts *opts)
>                         opts->committer_date_is_author_date = 1;
>                 }
>
> +               if (file_exists(rebase_path_ignore_date())) {
> +                       opts->allow_ff = 0;
> +                       opts->ignore_date = 1;
> +               }
> +
>                 if (file_exists(rebase_path_reschedule_failed_exec()))
>                         opts->reschedule_failed_exec = 1;
>
> @@ -2673,6 +2711,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>                 write_file(rebase_path_keep_redundant_commits(), "%s", "");
>         if (opts->committer_date_is_author_date)
>                 write_file(rebase_path_cdate_is_adate(), "%s", "");
> +       if (opts->ignore_date)
> +               write_file(rebase_path_ignore_date(), "%s", "");
>         if (opts->reschedule_failed_exec)
>                 write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>
> @@ -3595,7 +3635,11 @@ static int do_merge(struct repository *r,
>
>                 if (opts->committer_date_is_author_date)
>                         argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +                                        opts->ignore_date ?
> +                                        "" :
>                                          author_date_from_env_array(&cmd.env_array));
> +               if (opts->ignore_date)
> +                       argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>
>                 cmd.git_cmd = 1;
>                 argv_array_push(&cmd.args, "merge");
> @@ -3875,7 +3919,8 @@ static int pick_commits(struct repository *r,
>         if (opts->allow_ff)
>                 assert(!(opts->signoff || opts->no_commit ||
>                                 opts->record_origin || opts->edit ||
> -                               opts->committer_date_is_author_date));
> +                               opts->committer_date_is_author_date ||
> +                               opts->ignore_date));
>         if (read_and_refresh_cache(r, opts))
>                 return -1;
>
> diff --git a/sequencer.h b/sequencer.h
> index 4ab94119ae..3587878e3b 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -46,6 +46,7 @@ struct replay_opts {
>         int quiet;
>         int reschedule_failed_exec;
>         int committer_date_is_author_date;
> +       int ignore_date;
>
>         int mainline;
>
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 84b9d5d37f..6cd3848689 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl
>         test_cmp expect actual
>  '
>
> +# Checking for +0000 in author time is enough since default
> +# timezone is UTC, but the timezone used while committing
> +# sets to +0530.
> +test_expect_success '--ignore-date works with apply backend' '
> +       git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +       git rebase --apply --ignore-date HEAD^ &&
> +       git log -1 --pretty="format:%ai" >authortime &&
> +       grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works with merge backend' '
> +       git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +       git rebase --ignore-date -m HEAD^ &&
> +       git log -1 --pretty="format:%ai" >authortime &&
> +       grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works after conflict resolution' '
> +       test_must_fail git rebase --ignore-date -m \
> +               --onto commit2^^ commit2^ commit2 &&
> +       echo resolved >foo &&
> +       git add foo &&
> +       git rebase --continue &&
> +       git log --pretty=%ai >authortime &&
> +       grep +0000 authortime
> +'
> +
> +test_expect_success '--ignore-date works with rebase -r' '
> +       git checkout side &&
> +       git merge --no-ff commit3 &&
> +       git rebase -r --root --ignore-date &&
> +       git log --pretty=%ai >authortime &&
> +       ! grep -v "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '
> +       test_must_fail git rebase -m --committer-date-is-author-date \
> +               --ignore-date --onto commit2^^ commit2^ commit3 &&
> +       git checkout --theirs foo &&
> +       git add foo &&
> +       git rebase --continue &&
> +       git log -2 --pretty=%ai >authortime &&
> +       git log -2 --pretty=%ci >committertime &&
> +       test_cmp authortime committertime &&
> +       ! grep -v "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
> +       GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
> +               git rebase -i --strategy=resolve --ignore-date \
> +               --committer-date-is-author-date side side &&
> +       git log -1 --pretty=%ai >authortime &&
> +       git log -1 --pretty=%ci >committertime &&
> +       test_cmp authortime committertime &&
> +       grep "+0000" authortime
> + '
> +
>  # This must be the last test in this file
>  test_expect_success '$EDITOR and friends are unchanged' '
>         test_editor_unchanged
> --
> 2.26.2

Same question here as for patch 2 -- does it rely on us forking a "git
commit" subprocess which reads from the environment variable, or does
our try_to_commit() (which I'd rather we used in all cases) also work
with the environment variable?

Didn't notice any other problems or questions while reading over the patch.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag
  2020-04-29 10:25   ` [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-05-13  3:54     ` Elijah Newren
  2020-05-14  9:47       ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Elijah Newren @ 2020-05-13  3:54 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal, Git Mailing List

Sorry for taking so long to get back to you, and thanks for pushing
this forward.

On Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>
> Rebase is implemented with two different backends - 'apply' and 'merge'
> each of which support a different set of options. In particuar the apply
> backend supports a number of options implemented by 'git am' that are
> not available to the merge backend. As part of an on going effort to
> remove the apply backend this patch adds support for the
> --ignore-whitespace option to the merge backend. This option treats
> lines with only whitespace changes as unchanged and is implemented in
> the merge backend by translating it to -Xignore-space-change.
>
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt           | 12 +++-
>  builtin/rebase.c                       | 19 ++++--
>  t/t3422-rebase-incompatible-options.sh |  1 -
>  t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++
>  4 files changed, 111 insertions(+), 7 deletions(-)
>  create mode 100755 t/t3436-rebase-more-options.sh
>
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index f7a6033607..d060c143e6 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -422,8 +422,16 @@ your branch contains commits which were dropped, this option can be used
>  with `--keep-base` in order to drop those commits from your branch.
>
>  --ignore-whitespace::
> +       Behaves differently depending on which backend is selected.

I still don't like this wording; it defers answering the question,
implies that the difference is intentional, and most importantly
provides no context about *intended* behavior.  I tried to communicate
this to Rohit multiple times, but he seemed to fixate on and highlight
the differences in a way that made them sound like they were by
design, rather than highlighting the intent we want to move towards
and mentioning that this patch gets us most the way there.

As far as I can tell, the --ignore-whitespace and
-Xignore-space-change were always meant to do the same thing: ignore
differences in whitespace when doing so can avoid conflicts.

In case anyone isn't sure about my assertion that these were always
meant to do the same thing:
  * apply aliases --ignore-whitespace and --ignore-space-change; they
meant the same thing
  * commit f008cef4ab ("Merge branch 'jc/apply-ignore-whitespace'",
2014-06-03) says that apply's --ignore-space-change wasn't behaving
consistently with diff's --ignore-space-change
  * diff's --ignore-space-change goes through xdiff's XDL opts, much
like merge-recursive does.
Further, the original commit that introduced these xdiff options to
merge-recursive, 4e5dd044c6 ("merge-recursive: options to ignore
whitespace changes", 2010-08-26), it is clear that:
  * he only cared about ignore-space-at-eol and implemented
ignore-space-change at the same time only for completeness
  * it wouldn't matter to his usecase if whitespace-only changes were
stripped, thus he wouldn't have spotted the bug it has
  * the wording also suggests these options were picked to match
options of the same name elsewhere in git

I would rather we said something like:
    Ignore whitespace differences when trying to reconcile
differences.  Currently, each backend implements an approximation of
this behavior:

> ++
> +apply backend: When applying a patch, ignore changes in whitespace in
> +context lines.

Maybe add something like:
    (Unfortunately, this means that if the "old" lines being replaced
by the patch differ only in whitespace from the existing file, you
will get a merge conflict instead of a successful patch application.)

> ++
> +merge backend: Treat lines with only whitespace changes as unchanged
> +when merging.

Maybe add something like:
   (Unfortunately, this means that any patch hunks that were intended
to modify whitespace and nothing else will be dropped, even if the
other side had no changes that conflicted.)

> +
>  --whitespace=<option>::
> -       These flags are passed to the 'git apply' program
> +       This flag is passed to the 'git apply' program
>         (see linkgit:git-apply[1]) that applies the patch.
>         Implies --apply.
>  +
> @@ -572,7 +580,6 @@ The following options:
>   * --apply
>   * --committer-date-is-author-date
>   * --ignore-date
> - * --ignore-whitespace
>   * --whitespace
>   * -C
>
> @@ -598,6 +605,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --signoff
>   * --preserve-merges and --rebase-merges
>   * --preserve-merges and --empty=
> + * --preserve-merges and --ignore-whitespace
>   * --keep-base and --onto
>   * --keep-base and --root
>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 27a07d4e78..5d8e117276 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -86,6 +86,7 @@ struct rebase_options {
>         int signoff;
>         int allow_rerere_autoupdate;
>         int autosquash;
> +       int ignore_whitespace;
>         char *gpg_sign_opt;
>         int autostash;
>         char *cmd;
> @@ -108,6 +109,7 @@ struct rebase_options {
>
>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  {
> +       struct strbuf strategy_buf = STRBUF_INIT;
>         struct replay_opts replay = REPLAY_OPTS_INIT;
>
>         replay.action = REPLAY_INTERACTIVE_REBASE;
> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>         replay.strategy = opts->strategy;
> +
>         if (opts->strategy_opts)
> -               parse_strategy_opts(&replay, opts->strategy_opts);
> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);
> +       if (opts->ignore_whitespace)
> +               strbuf_addstr(&strategy_buf, " --ignore-space-change");
> +       if (strategy_buf.len)
> +               parse_strategy_opts(&replay, strategy_buf.buf);
>
>         if (opts->squash_onto) {
>                 oidcpy(&replay.squash_onto, opts->squash_onto);
>                 replay.have_squash_onto = 1;
>         }
>
> +       strbuf_release(&strategy_buf);
>         return replay;
>  }
>
> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>         argc = parse_options(argc, argv, prefix, options,
>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>
> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
> +
>         if (!is_null_oid(&squash_onto))
>                 opts.squash_onto = &squash_onto;
>
> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)
>         am.git_cmd = 1;
>         argv_array_push(&am.args, "am");
>
> +       if (opts->ignore_whitespace)
> +               argv_array_push(&am.args, "--ignore-whitespace");
>         if (opts->action && !strcmp("continue", opts->action)) {
>                 argv_array_push(&am.args, "--resolved");
>                 argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>                 OPT_BOOL(0, "signoff", &options.signoff,
>                          N_("add a Signed-off-by: line to each commit")),
> -               OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -                                 NULL, N_("passed to 'git am'"),
> -                                 PARSE_OPT_NOARG),
>                 OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>                                   &options.git_am_opts, NULL,
>                                   N_("passed to 'git am'"), PARSE_OPT_NOARG),
>                 OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>                                   N_("passed to 'git am'"), PARSE_OPT_NOARG),
>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>                                   N_("passed to 'git apply'"), 0),
> +               OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> +                        N_("ignore changes in whitespace")),
>                 OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>                                   N_("action"), N_("passed to 'git apply'"), 0),
>                 OPT_BIT('f', "force-rebase", &options.flags,
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 50e7960702..55ca46786d 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
>  test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> new file mode 100755
> index 0000000000..fb5e747e86
> --- /dev/null
> +++ b/t/t3436-rebase-more-options.sh
> @@ -0,0 +1,86 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2019 Rohit Ashiwal
> +#
> +
> +test_description='tests to ensure compatibility between am and interactive backends'
> +
> +. ./test-lib.sh
> +
> +. "$TEST_DIRECTORY"/lib-rebase.sh
> +
> +# This is a special case in which both am and interactive backends
> +# provide the same output. It was done intentionally because
> +# both the backends fall short of optimal behaviour.
> +test_expect_success 'setup' '
> +       git checkout -b topic &&
> +       q_to_tab >file <<-\EOF &&
> +       line 1
> +       Qline 2
> +       line 3
> +       EOF
> +       git add file &&
> +       git commit -m "add file" &&
> +       cat >file <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       git commit -am "update file" &&
> +       git tag side &&
> +
> +       git checkout --orphan master &&
> +       sed -e "s/^|//" >file <<-\EOF &&
> +       |line 1
> +       |        line 2
> +       |line 3
> +       EOF
> +       git add file &&
> +       git commit -m "add file" &&
> +       git tag main
> +'
> +
> +test_expect_success '--ignore-whitespace works with apply backend' '
> +       cat >expect <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       test_must_fail git rebase --apply main side &&
> +       git rebase --abort &&
> +       git rebase --apply --ignore-whitespace main side &&
> +       test_cmp expect file
> +'
> +
> +test_expect_success '--ignore-whitespace works with merge backend' '
> +       cat >expect <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       test_must_fail git rebase --merge main side &&
> +       git rebase --abort &&
> +       git rebase --merge --ignore-whitespace main side &&
> +       test_cmp expect file
> +'
> +
> +test_expect_success '--ignore-whitespace is remembered when continuing' '
> +       cat >expect <<-\EOF &&
> +       line 1
> +       new line 2
> +       line 3
> +       EOF
> +       (
> +               set_fake_editor &&
> +               FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
> +       ) &&
> +       git rebase --continue &&
> +       test_cmp expect file
> +'
> +
> +# This must be the last test in this file
> +test_expect_success '$EDITOR and friends are unchanged' '
> +       test_editor_unchanged
> +'
> +
> +test_done
> --
> 2.26.2

The rest looks good to me.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 0/5] cleanup ra/rebase-i-more-options
  2020-04-29 19:59   ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
@ 2020-05-13  3:57     ` Elijah Newren
  0 siblings, 0 replies; 130+ messages in thread
From: Elijah Newren @ 2020-05-13  3:57 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Phillip Wood, Johannes Schindelin, Rohit Ashiwal,
	Git Mailing List, Phillip Wood

On Wed, Apr 29, 2020 at 12:59 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> Phillip Wood <phillip.wood123@gmail.com> writes:
>
> > From: Phillip Wood <phillip.wood@dunelm.org.uk>
> >
> > I've rebased Rohit's patches on master and reworked them with my
>
> OK, it took a bit of time for me to figure it out, but this does
> cleanly apply on top of 048abe17 (Sync with 2.26.2, 2020-04-19).
>
> Queued, but haven't taken any deep look at it.
>
> Thanks.

Sorry for the long delay in reviewing.  I looked through all five
patches; I had the same simple question about patches 2 & 4, and had
some comments about the wording of the documentation in patch 1, but
all small stuff.  I didn't notice anything outside of those few small
comments.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date
  2020-04-29 10:25   ` [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
  2020-05-10 11:14     ` Alban Gruin
@ 2020-05-13  4:08     ` Elijah Newren
  1 sibling, 0 replies; 130+ messages in thread
From: Elijah Newren @ 2020-05-13  4:08 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal, Git Mailing List

On Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> As part of the on-going effort to retire the apply rebase backend teach
> the merge backend how to handle --committer-date-is-author-date.
>
> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt           | 10 +++--
>  builtin/rebase.c                       | 16 ++++---
>  sequencer.c                            | 60 +++++++++++++++++++++++++-
>  sequencer.h                            |  1 +
>  t/t3422-rebase-incompatible-options.sh |  1 -
>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++
>  6 files changed, 133 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index d060c143e6..8c62645b8c 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -438,9 +438,13 @@ when merging.
>  See also INCOMPATIBLE OPTIONS below.
>
>  --committer-date-is-author-date::
> +       Instead of using the current time as the committer date, use
> +       the author date of the commit being rebased as the committer
> +       date. This option implies --force-rebase.
> +
>  --ignore-date::
> -       These flags are passed to 'git am' to easily change the dates
> -       of the rebased commits (see linkgit:git-am[1]).
> +       This flag is passed to 'git am' to change the author date
> +       of each rebased commit (see linkgit:git-am[1]).
>  +
>  See also INCOMPATIBLE OPTIONS below.
>
> @@ -578,7 +582,6 @@ INCOMPATIBLE OPTIONS
>  The following options:
>
>   * --apply
> - * --committer-date-is-author-date
>   * --ignore-date
>   * --whitespace
>   * -C
> @@ -606,6 +609,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --rebase-merges
>   * --preserve-merges and --empty=
>   * --preserve-merges and --ignore-whitespace
> + * --preserve-merges and --committer-date-is-author-date
>   * --keep-base and --onto
>   * --keep-base and --root
>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 5d8e117276..357cd6acf3 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -89,6 +89,7 @@ struct rebase_options {
>         int ignore_whitespace;
>         char *gpg_sign_opt;
>         int autostash;
> +       int committer_date_is_author_date;
>         char *cmd;
>         int allow_empty_message;
>         int rebase_merges, rebase_cousins;
> @@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>         replay.quiet = !(opts->flags & REBASE_NO_QUIET);
>         replay.verbose = opts->flags & REBASE_VERBOSE;
>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +       replay.committer_date_is_author_date =
> +                                       opts->committer_date_is_author_date;
>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>         replay.strategy = opts->strategy;
>
> @@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)
>
>         if (opts->ignore_whitespace)
>                 argv_array_push(&am.args, "--ignore-whitespace");
> +       if (opts->committer_date_is_author_date)
> +               argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
>         if (opts->action && !strcmp("continue", opts->action)) {
>                 argv_array_push(&am.args, "--resolved");
>                 argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>                 OPT_BOOL(0, "signoff", &options.signoff,
>                          N_("add a Signed-off-by: line to each commit")),
> -               OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -                                 &options.git_am_opts, NULL,
> -                                 N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +               OPT_BOOL(0, "committer-date-is-author-date",
> +                        &options.committer_date_is_author_date,
> +                        N_("make committer date match author date")),
>                 OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>                                   N_("passed to 'git am'"), PARSE_OPT_NOARG),
>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> @@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>             options.autosquash) {
>                 allow_preemptive_ff = 0;
>         }
> +       if (options.committer_date_is_author_date)
> +               options.flags |= REBASE_FORCE;
>
>         for (i = 0; i < options.git_am_opts.argc; i++) {
>                 const char *option = options.git_am_opts.argv[i], *p;
> -               if (!strcmp(option, "--committer-date-is-author-date") ||
> -                   !strcmp(option, "--ignore-date") ||
> +               if (!strcmp(option, "--ignore-date") ||
>                     !strcmp(option, "--whitespace=fix") ||
>                     !strcmp(option, "--whitespace=strip"))
>                         allow_preemptive_ff = 0;
> diff --git a/sequencer.c b/sequencer.c
> index 6fd2674632..3bb80d7414 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   * command-line.
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -872,6 +873,22 @@ static char *get_author(const char *message)
>         return NULL;
>  }
>
> +static const char *author_date_from_env_array(const struct argv_array *env)
> +{
> +       int i;
> +       const char *date;
> +
> +       for (i = 0; i < env->argc; i++)
> +               if (skip_prefix(env->argv[i],
> +                               "GIT_AUTHOR_DATE=", &date))
> +                       return date;
> +       /*
> +        * If GIT_AUTHOR_DATE is missing we should have already errored out when
> +        * reading the script
> +        */
> +       BUG("GIT_AUTHOR_DATE missing from author script");
> +}
> +
>  static const char staged_changes_advice[] =
>  N_("you have staged changes in your working tree\n"
>  "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
>                              gpg_opt, gpg_opt);
>         }
>
> +       if (opts->committer_date_is_author_date)
> +               argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +                                author_date_from_env_array(&cmd.env_array));
> +
>         argv_array_push(&cmd.args, "commit");
>
>         if (!(flags & VERIFY_MSG))
> @@ -1321,7 +1342,6 @@ static int try_to_commit(struct repository *r,
>
>         if (parse_head(r, &current_head))
>                 return -1;
> -
>         if (flags & AMEND_MSG) {
>                 const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
>                 const char *out_enc = get_commit_output_encoding();
> @@ -1349,6 +1369,30 @@ static int try_to_commit(struct repository *r,
>                 commit_list_insert(current_head, &parents);
>         }
>
> +       if (opts->committer_date_is_author_date) {
> +               int len = strlen(author);
> +               struct ident_split ident;
> +               struct strbuf date = STRBUF_INIT;
> +
> +               if (split_ident_line(&ident, author, len) < 0) {
> +                       res = error(_("malformed ident line '%s'"), author);
> +                       goto out;
> +               }
> +               if (!ident.date_begin) {
> +                       res = error(_("corrupted author without date information"));
> +                       goto out;
> +               }
> +
> +               strbuf_addf(&date, "@%.*s %.*s",
> +                           (int)(ident.date_end - ident.date_begin), ident.date_begin,
> +                           (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> +               res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +               strbuf_release(&date);
> +
> +               if (res)
> +                       goto out;
> +       }
> +
>         if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>                 res = error(_("git write-tree failed to write a tree"));
>                 goto out;
> @@ -2532,6 +2576,11 @@ static int read_populate_opts(struct replay_opts *opts)
>                         opts->signoff = 1;
>                 }
>
> +               if (file_exists(rebase_path_cdate_is_adate())) {
> +                       opts->allow_ff = 0;
> +                       opts->committer_date_is_author_date = 1;
> +               }
> +
>                 if (file_exists(rebase_path_reschedule_failed_exec()))
>                         opts->reschedule_failed_exec = 1;
>
> @@ -2622,6 +2671,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>                 write_file(rebase_path_drop_redundant_commits(), "%s", "");
>         if (opts->keep_redundant_commits)
>                 write_file(rebase_path_keep_redundant_commits(), "%s", "");
> +       if (opts->committer_date_is_author_date)
> +               write_file(rebase_path_cdate_is_adate(), "%s", "");
>         if (opts->reschedule_failed_exec)
>                 write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>
> @@ -3542,6 +3593,10 @@ static int do_merge(struct repository *r,
>                         goto leave_merge;
>                 }
>
> +               if (opts->committer_date_is_author_date)
> +                       argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +                                        author_date_from_env_array(&cmd.env_array));
> +
>                 cmd.git_cmd = 1;
>                 argv_array_push(&cmd.args, "merge");
>                 argv_array_push(&cmd.args, "-s");
> @@ -3819,7 +3874,8 @@ static int pick_commits(struct repository *r,
>         setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>         if (opts->allow_ff)
>                 assert(!(opts->signoff || opts->no_commit ||
> -                               opts->record_origin || opts->edit));
> +                               opts->record_origin || opts->edit ||
> +                               opts->committer_date_is_author_date));
>         if (read_and_refresh_cache(r, opts))
>                 return -1;
>
> diff --git a/sequencer.h b/sequencer.h
> index 0bee85093e..4ab94119ae 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -45,6 +45,7 @@ struct replay_opts {
>         int verbose;
>         int quiet;
>         int reschedule_failed_exec;
> +       int committer_date_is_author_date;
>
>         int mainline;
>
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 55ca46786d..c8234062c6 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>
>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index fb5e747e86..84b9d5d37f 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>
>  . "$TEST_DIRECTORY"/lib-rebase.sh
>
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>  # This is a special case in which both am and interactive backends
>  # provide the same output. It was done intentionally because
>  # both the backends fall short of optimal behaviour.
> @@ -28,8 +31,13 @@ test_expect_success 'setup' '
>         EOF
>         git commit -am "update file" &&
>         git tag side &&
> +       test_commit commit1 foo foo1 &&
> +       test_commit commit2 foo foo2 &&
> +       test_commit commit3 foo foo3 &&
>
>         git checkout --orphan master &&
> +       git rm --cached foo &&
> +       rm foo &&
>         sed -e "s/^|//" >file <<-\EOF &&
>         |line 1
>         |        line 2
> @@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
>         test_cmp expect file
>  '
>
> +test_expect_success '--committer-date-is-author-date works with apply backend' '
> +       GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +       git rebase --apply --committer-date-is-author-date HEAD^ &&
> +       git log -1 --pretty="format:%ai" >authortime &&
> +       git log -1 --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with merge backend' '
> +       GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +       git rebase -m --committer-date-is-author-date HEAD^ &&
> +       git log -1 --pretty="format:%ai" >authortime &&
> +       git log -1 --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
> +       git checkout side &&
> +       GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +       git rebase -r --root --committer-date-is-author-date &&
> +       git log --pretty="format:%ai" >authortime &&
> +       git log --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when forking merge' '
> +       git checkout side &&
> +       GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +       git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
> +       git log --pretty="format:%ai" >authortime &&
> +       git log --pretty="format:%ci" >committertime &&
> +       test_cmp authortime committertime
> +
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
> +       git checkout commit2 &&
> +       GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
> +       git log -1 --format=%at HEAD >expect &&
> +       test_must_fail git rebase -m --committer-date-is-author-date \
> +               --onto HEAD^^ HEAD^ &&
> +       echo resolved > foo &&
> +       git add foo &&
> +       git rebase --continue &&
> +       git log -1 --format=%ct HEAD >actual &&
> +       test_cmp expect actual
> +'
> +
>  # This must be the last test in this file
>  test_expect_success '$EDITOR and friends are unchanged' '
>         test_editor_unchanged
> --
> 2.26.2

Does this implementation rely on the run_git_commit() path, i.e. is it
another place we'll need to fix up to avoid forking a subprocess, or
does it work with the try_to_commit() codepath as well?

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 4/5] rebase -i: support --ignore-date
  2020-05-12 14:47       ` Phillip Wood
@ 2020-05-13 15:33         ` Junio C Hamano
  0 siblings, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-05-13 15:33 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Alban Gruin, Phillip Wood, Johannes Schindelin, Elijah Newren,
	Rohit Ashiwal, Git Mailing List

Phillip Wood <phillip.wood123@gmail.com> writes:

>>> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
>>>     	if (opts->committer_date_is_author_date)
>>>   		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>>> +				 opts->ignore_date ?
>>> +				 "" :
>>>   				 author_date_from_env_array(&cmd.env_array));
>>> +	if (opts->ignore_date)
>>> +		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>>>   
>>
>> Perhaps this could be done in read_env_script(), too, instead of fixing
>> up what this function did right after calling it, twice?  Something like
>> this:
>
> Long term I'd like to stop writing the author-script file unless we're
> stopping for a conflict resolution or edit so I'm reluctant to add
> more functionality to it at the moment. Also I tend to view
> read_env_script() it as loading the author details from a file rather
> than setting up the environment for the commit.

Yeah, the author-script, once the program halts and returns the
control to the human-user sitting on the terminal, can be peeked at,
and it should record what the program learned from the commit; it
smells like a premature optimization to rewrite it to what the
program plans to use to replay the commit and lose the information
taken from the original.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag
  2020-05-13  3:54     ` Elijah Newren
@ 2020-05-14  9:47       ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-14  9:47 UTC (permalink / raw)
  To: Elijah Newren, Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal, Git Mailing List

On 13/05/2020 04:54, Elijah Newren wrote:
> Sorry for taking so long to get back to you, and thanks for pushing
> this forward.

Thanks for taking a look at this series

> 
> On Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>>
>> Rebase is implemented with two different backends - 'apply' and 'merge'
>> each of which support a different set of options. In particuar the apply
>> backend supports a number of options implemented by 'git am' that are
>> not available to the merge backend. As part of an on going effort to
>> remove the apply backend this patch adds support for the
>> --ignore-whitespace option to the merge backend. This option treats
>> lines with only whitespace changes as unchanged and is implemented in
>> the merge backend by translating it to -Xignore-space-change.
>>
>> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> [...]

>> ---
>>  Documentation/git-rebase.txt           | 12 +++-
>>  builtin/rebase.c                       | 19 ++++--
>>  t/t3422-rebase-incompatible-options.sh |  1 -
>>  t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++
>>  4 files changed, 111 insertions(+), 7 deletions(-)
>>  create mode 100755 t/t3436-rebase-more-options.sh
>>
>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
>> index f7a6033607..d060c143e6 100644
>> --- a/Documentation/git-rebase.txt
>> +++ b/Documentation/git-rebase.txt
>> @@ -422,8 +422,16 @@ your branch contains commits which were dropped, this option can be used
>>  with `--keep-base` in order to drop those commits from your branch.
>>
>>  --ignore-whitespace::
>> +       Behaves differently depending on which backend is selected.
> 
> I still don't like this wording; it defers answering the question,
> implies that the difference is intentional, and most importantly
> provides no context about *intended* behavior.  I tried to communicate
> this to Rohit multiple times, but he seemed to fixate on and highlight
> the differences in a way that made them sound like they were by
> design, rather than highlighting the intent we want to move towards
> and mentioning that this patch gets us most the way there.
> 
> As far as I can tell, the --ignore-whitespace and
> -Xignore-space-change were always meant to do the same thing: ignore
> differences in whitespace when doing so can avoid conflicts.
> 
> In case anyone isn't sure about my assertion that these were always
> meant to do the same thing:
>   * apply aliases --ignore-whitespace and --ignore-space-change; they
> meant the same thing
>   * commit f008cef4ab ("Merge branch 'jc/apply-ignore-whitespace'",
> 2014-06-03) says that apply's --ignore-space-change wasn't behaving
> consistently with diff's --ignore-space-change
>   * diff's --ignore-space-change goes through xdiff's XDL opts, much
> like merge-recursive does.
> Further, the original commit that introduced these xdiff options to
> merge-recursive, 4e5dd044c6 ("merge-recursive: options to ignore
> whitespace changes", 2010-08-26), it is clear that:
>   * he only cared about ignore-space-at-eol and implemented
> ignore-space-change at the same time only for completeness
>   * it wouldn't matter to his usecase if whitespace-only changes were
> stripped, thus he wouldn't have spotted the bug it has
>   * the wording also suggests these options were picked to match
> options of the same name elsewhere in git
> 
> I would rather we said something like:
>     Ignore whitespace differences when trying to reconcile
> differences.  Currently, each backend implements an approximation of
> this behavior:
> 
>> ++
>> +apply backend: When applying a patch, ignore changes in whitespace in
>> +context lines.
> 
> Maybe add something like:
>     (Unfortunately, this means that if the "old" lines being replaced
> by the patch differ only in whitespace from the existing file, you
> will get a merge conflict instead of a successful patch application.)
> 
>> ++
>> +merge backend: Treat lines with only whitespace changes as unchanged
>> +when merging.
> 
> Maybe add something like:
>    (Unfortunately, this means that any patch hunks that were intended
> to modify whitespace and nothing else will be dropped, even if the
> other side had no changes that conflicted.)

Thanks for the suggestions, I'll incorporate them into the re-roll.

Best Wishes

Phillip

>> +
>>  --whitespace=<option>::
>> -       These flags are passed to the 'git apply' program
>> +       This flag is passed to the 'git apply' program
>>         (see linkgit:git-apply[1]) that applies the patch.
>>         Implies --apply.
>>  +
>> @@ -572,7 +580,6 @@ The following options:
>>   * --apply
>>   * --committer-date-is-author-date
>>   * --ignore-date
>> - * --ignore-whitespace
>>   * --whitespace
>>   * -C
>>
>> @@ -598,6 +605,7 @@ In addition, the following pairs of options are incompatible:
>>   * --preserve-merges and --signoff
>>   * --preserve-merges and --rebase-merges
>>   * --preserve-merges and --empty=
>> + * --preserve-merges and --ignore-whitespace
>>   * --keep-base and --onto
>>   * --keep-base and --root
>>
>> diff --git a/builtin/rebase.c b/builtin/rebase.c
>> index 27a07d4e78..5d8e117276 100644
>> --- a/builtin/rebase.c
>> +++ b/builtin/rebase.c
>> @@ -86,6 +86,7 @@ struct rebase_options {
>>         int signoff;
>>         int allow_rerere_autoupdate;
>>         int autosquash;
>> +       int ignore_whitespace;
>>         char *gpg_sign_opt;
>>         int autostash;
>>         char *cmd;
>> @@ -108,6 +109,7 @@ struct rebase_options {
>>
>>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>  {
>> +       struct strbuf strategy_buf = STRBUF_INIT;
>>         struct replay_opts replay = REPLAY_OPTS_INIT;
>>
>>         replay.action = REPLAY_INTERACTIVE_REBASE;
>> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>>         replay.strategy = opts->strategy;
>> +
>>         if (opts->strategy_opts)
>> -               parse_strategy_opts(&replay, opts->strategy_opts);
>> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);
>> +       if (opts->ignore_whitespace)
>> +               strbuf_addstr(&strategy_buf, " --ignore-space-change");
>> +       if (strategy_buf.len)
>> +               parse_strategy_opts(&replay, strategy_buf.buf);
>>
>>         if (opts->squash_onto) {
>>                 oidcpy(&replay.squash_onto, opts->squash_onto);
>>                 replay.have_squash_onto = 1;
>>         }
>>
>> +       strbuf_release(&strategy_buf);
>>         return replay;
>>  }
>>
>> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>>         argc = parse_options(argc, argv, prefix, options,
>>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>>
>> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
>> +
>>         if (!is_null_oid(&squash_onto))
>>                 opts.squash_onto = &squash_onto;
>>
>> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)
>>         am.git_cmd = 1;
>>         argv_array_push(&am.args, "am");
>>
>> +       if (opts->ignore_whitespace)
>> +               argv_array_push(&am.args, "--ignore-whitespace");
>>         if (opts->action && !strcmp("continue", opts->action)) {
>>                 argv_array_push(&am.args, "--resolved");
>>                 argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
>> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>>                 OPT_BOOL(0, "signoff", &options.signoff,
>>                          N_("add a Signed-off-by: line to each commit")),
>> -               OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
>> -                                 NULL, N_("passed to 'git am'"),
>> -                                 PARSE_OPT_NOARG),
>>                 OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>>                                   &options.git_am_opts, NULL,
>>                                   N_("passed to 'git am'"), PARSE_OPT_NOARG),
>>                 OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>>                                   N_("passed to 'git am'"), PARSE_OPT_NOARG),
>>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>>                                   N_("passed to 'git apply'"), 0),
>> +               OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
>> +                        N_("ignore changes in whitespace")),
>>                 OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>>                                   N_("action"), N_("passed to 'git apply'"), 0),
>>                 OPT_BIT('f', "force-rebase", &options.flags,
>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>> index 50e7960702..55ca46786d 100755
>> --- a/t/t3422-rebase-incompatible-options.sh
>> +++ b/t/t3422-rebase-incompatible-options.sh
>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>  }
>>
>>  test_rebase_am_only --whitespace=fix
>> -test_rebase_am_only --ignore-whitespace
>>  test_rebase_am_only --committer-date-is-author-date
>>  test_rebase_am_only -C4
>>
>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>> new file mode 100755
>> index 0000000000..fb5e747e86
>> --- /dev/null
>> +++ b/t/t3436-rebase-more-options.sh
>> @@ -0,0 +1,86 @@
>> +#!/bin/sh
>> +#
>> +# Copyright (c) 2019 Rohit Ashiwal
>> +#
>> +
>> +test_description='tests to ensure compatibility between am and interactive backends'
>> +
>> +. ./test-lib.sh
>> +
>> +. "$TEST_DIRECTORY"/lib-rebase.sh
>> +
>> +# This is a special case in which both am and interactive backends
>> +# provide the same output. It was done intentionally because
>> +# both the backends fall short of optimal behaviour.
>> +test_expect_success 'setup' '
>> +       git checkout -b topic &&
>> +       q_to_tab >file <<-\EOF &&
>> +       line 1
>> +       Qline 2
>> +       line 3
>> +       EOF
>> +       git add file &&
>> +       git commit -m "add file" &&
>> +       cat >file <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       git commit -am "update file" &&
>> +       git tag side &&
>> +
>> +       git checkout --orphan master &&
>> +       sed -e "s/^|//" >file <<-\EOF &&
>> +       |line 1
>> +       |        line 2
>> +       |line 3
>> +       EOF
>> +       git add file &&
>> +       git commit -m "add file" &&
>> +       git tag main
>> +'
>> +
>> +test_expect_success '--ignore-whitespace works with apply backend' '
>> +       cat >expect <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       test_must_fail git rebase --apply main side &&
>> +       git rebase --abort &&
>> +       git rebase --apply --ignore-whitespace main side &&
>> +       test_cmp expect file
>> +'
>> +
>> +test_expect_success '--ignore-whitespace works with merge backend' '
>> +       cat >expect <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       test_must_fail git rebase --merge main side &&
>> +       git rebase --abort &&
>> +       git rebase --merge --ignore-whitespace main side &&
>> +       test_cmp expect file
>> +'
>> +
>> +test_expect_success '--ignore-whitespace is remembered when continuing' '
>> +       cat >expect <<-\EOF &&
>> +       line 1
>> +       new line 2
>> +       line 3
>> +       EOF
>> +       (
>> +               set_fake_editor &&
>> +               FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
>> +       ) &&
>> +       git rebase --continue &&
>> +       test_cmp expect file
>> +'
>> +
>> +# This must be the last test in this file
>> +test_expect_success '$EDITOR and friends are unchanged' '
>> +       test_editor_unchanged
>> +'
>> +
>> +test_done
>> --
>> 2.26.2
> 
> The rest looks good to me.
> 


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v3 0/5] cleanup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (8 preceding siblings ...)
  2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
@ 2020-05-21 10:14 ` Phillip Wood
  2020-05-21 10:14   ` [PATCH v3 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
                     ` (6 more replies)
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
                   ` (4 subsequent siblings)
  14 siblings, 7 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-21 10:14 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Thanks for the feedback on v2, I've updated the documentation as
suggested by Elijah and made the style fixes suggested by Alban but
I've not changed read_author_script() for the reasons explained in
https://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com

These patches are based on 9fadedd637 ("Merge branch
'ds/default-pack-use-sparse-to-true'", 2020-03-29)

Phillip Wood (2):
  rebase -i: support --committer-date-is-author-date
  rebase -i: support --ignore-date

Rohit Ashiwal (3):
  rebase -i: add --ignore-whitespace flag
  sequencer: rename amend_author to author_to_free
  rebase: add --reset-author-date

 Documentation/git-rebase.txt           |  33 +++-
 builtin/rebase.c                       |  46 ++++--
 sequencer.c                            | 111 ++++++++++++-
 sequencer.h                            |   2 +
 t/t3422-rebase-incompatible-options.sh |   2 -
 t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++
 6 files changed, 379 insertions(+), 24 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

Range-diff against v2:
1:  5ef315240a ! 1:  df8c4ed2e9 rebase -i: add --ignore-whitespace flag
    @@ Documentation/git-rebase.txt: your branch contains commits which were dropped, t
      with `--keep-base` in order to drop those commits from your branch.
      
      --ignore-whitespace::
    -+	Behaves differently depending on which backend is selected.
    ++	Ignore whitespace differences when trying to reconcile
    ++differences. Currently, each backend implements an approximation of
    ++this behavior:
     ++
     +apply backend: When applying a patch, ignore changes in whitespace in
    -+context lines.
    ++context lines. Unfortunately, this means that if the "old" lines being
    ++replaced by the patch differ only in whitespace from the existing
    ++file, you will get a merge conflict instead of a successful patch
    ++application.
     ++
     +merge backend: Treat lines with only whitespace changes as unchanged
    -+when merging.
    ++when merging. Unfortunately, this means that any patch hunks that were
    ++intended to modify whitespace and nothing else will be dropped, even
    ++if the other side had no changes that conflicted.
     +
      --whitespace=<option>::
     -	These flags are passed to the 'git apply' program
2:  55eb3a7efc ! 2:  df44a0bde6 rebase -i: support --committer-date-is-author-date
    @@ Commit message
         Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
     
      ## Documentation/git-rebase.txt ##
    -@@ Documentation/git-rebase.txt: when merging.
    +@@ Documentation/git-rebase.txt: if the other side had no changes that conflicted.
      See also INCOMPATIBLE OPTIONS below.
      
      --committer-date-is-author-date::
    @@ sequencer.c: static int run_git_commit(struct repository *r,
      
      	if (!(flags & VERIFY_MSG))
     @@ sequencer.c: static int try_to_commit(struct repository *r,
    - 
    - 	if (parse_head(r, &current_head))
    - 		return -1;
    --
    - 	if (flags & AMEND_MSG) {
    - 		const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
    - 		const char *out_enc = get_commit_output_encoding();
    -@@ sequencer.c: static int try_to_commit(struct repository *r,
      		commit_list_insert(current_head, &parents);
      	}
      
3:  19352fdc22 = 3:  fa3d4856b4 sequencer: rename amend_author to author_to_free
4:  5e971abb74 ! 4:  96657233d4 rebase -i: support --ignore-date
    @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr
     +		error(_("malformed ident line '%s'"), author);
     +		return NULL;
     +	}
    ++
     +	len = ident.mail_end - ident.name_begin + 1;
    -+
     +	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
     +	datestamp(&new_author);
     +	return strbuf_detach(&new_author, NULL);
    @@ sequencer.c: static int try_to_commit(struct repository *r,
     +		free(author_to_free);
     +		author_to_free = (char *)author;
     +	}
    ++
      	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
      				 oid, author, opts->gpg_sign, extra)) {
      		res = error(_("failed to write commit object"));
5:  43a097c583 = 5:  828155baba rebase: add --reset-author-date

-- 
2.26.2

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v3 1/5] rebase -i: add --ignore-whitespace flag
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
@ 2020-05-21 10:14   ` Phillip Wood
  2020-05-21 10:14   ` [PATCH v3 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-21 10:14 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

Rebase is implemented with two different backends - 'apply' and 'merge'
each of which support a different set of options. In particuar the apply
backend supports a number of options implemented by 'git am' that are
not available to the merge backend. As part of an on going effort to
remove the apply backend this patch adds support for the
--ignore-whitespace option to the merge backend. This option treats
lines with only whitespace changes as unchanged and is implemented in
the merge backend by translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 19 +++++-
 builtin/rebase.c                       | 19 ++++--
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++
 4 files changed, 118 insertions(+), 7 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f7a6033607..b003784f01 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Ignore whitespace differences when trying to reconcile
+differences. Currently, each backend implements an approximation of
+this behavior:
++
+apply backend: When applying a patch, ignore changes in whitespace in
+context lines. Unfortunately, this means that if the "old" lines being
+replaced by the patch differ only in whitespace from the existing
+file, you will get a merge conflict instead of a successful patch
+application.
++
+merge backend: Treat lines with only whitespace changes as unchanged
+when merging. Unfortunately, this means that any patch hunks that were
+intended to modify whitespace and nothing else will be dropped, even
+if the other side had no changes that conflicted.
+
 --whitespace=<option>::
-	These flags are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 	Implies --apply.
 +
@@ -572,7 +587,6 @@ The following options:
  * --apply
  * --committer-date-is-author-date
  * --ignore-date
- * --ignore-whitespace
  * --whitespace
  * -C
 
@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 27a07d4e78..5d8e117276 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -86,6 +86,7 @@ struct rebase_options {
 	int signoff;
 	int allow_rerere_autoupdate;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -108,6 +109,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	struct strbuf strategy_buf = STRBUF_INIT;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
+	if (opts->ignore_whitespace)
+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
+	if (strategy_buf.len)
+		parse_strategy_opts(&replay, strategy_buf.buf);
 
 	if (opts->squash_onto) {
 		oidcpy(&replay.squash_onto, opts->squash_onto);
 		replay.have_squash_onto = 1;
 	}
 
+	strbuf_release(&strategy_buf);
 	return replay;
 }
 
@@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
new file mode 100755
index 0000000000..fb5e747e86
--- /dev/null
+++ b/t/t3436-rebase-more-options.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with apply backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --apply main side &&
+	git rebase --abort &&
+	git rebase --apply --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with merge backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
+	) &&
+	git rebase --continue &&
+	test_cmp expect file
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
+test_done
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v3 2/5] rebase -i: support --committer-date-is-author-date
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
  2020-05-21 10:14   ` [PATCH v3 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-05-21 10:14   ` Phillip Wood
  2020-05-21 10:14   ` [PATCH v3 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-21 10:14 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

As part of the on-going effort to retire the apply rebase backend teach
the merge backend how to handle --committer-date-is-author-date.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 10 +++--
 builtin/rebase.c                       | 16 ++++---
 sequencer.c                            | 59 +++++++++++++++++++++++++-
 sequencer.h                            |  1 +
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++
 6 files changed, 133 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b003784f01..dfa70263e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of using the current time as the committer date, use
+	the author date of the commit being rebased as the committer
+	date. This option implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5d8e117276..357cd6acf3 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -89,6 +89,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
diff --git a/sequencer.c b/sequencer.c
index 6fd2674632..8826c6325b 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -872,6 +873,22 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+static const char *author_date_from_env_array(const struct argv_array *env)
+{
+	int i;
+	const char *date;
+
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
 			     gpg_opt, gpg_opt);
 	}
 
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 author_date_from_env_array(&cmd.env_array));
+
 	argv_array_push(&cmd.args, "commit");
 
 	if (!(flags & VERIFY_MSG))
@@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, len) < 0) {
+			res = error(_("malformed ident line '%s'"), author);
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
 	if (opts->keep_redundant_commits)
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,
 			goto leave_merge;
 		}
 
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 author_date_from_env_array(&cmd.env_array));
+
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
 		argv_array_push(&cmd.args, "-s");
@@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 0bee85093e..4ab94119ae 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -45,6 +45,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index fb5e747e86..84b9d5d37f 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -28,8 +31,13 @@ test_expect_success 'setup' '
 	EOF
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	git rm --cached foo &&
+	rm foo &&
 	sed -e "s/^|//" >file <<-\EOF &&
 	|line 1
 	|        line 2
@@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with apply backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase --apply --committer-date-is-author-date HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with merge backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase -m --committer-date-is-author-date HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	git log -1 --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	git log --pretty="format:%ai" >authortime &&
+	git log --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
+	git log --pretty="format:%ai" >authortime &&
+	git log --pretty="format:%ci" >committertime &&
+	test_cmp authortime committertime
+
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	git log -1 --format=%at HEAD >expect &&
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -1 --format=%ct HEAD >actual &&
+	test_cmp expect actual
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v3 3/5] sequencer: rename amend_author to author_to_free
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
  2020-05-21 10:14   ` [PATCH v3 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-05-21 10:14   ` [PATCH v3 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-05-21 10:14   ` Phillip Wood
  2020-05-21 10:14   ` [PATCH v3 4/5] rebase -i: support --ignore-date Phillip Wood
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-21 10:14 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() when amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 8826c6325b..44e0b45e53 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1473,7 +1473,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
                     ` (2 preceding siblings ...)
  2020-05-21 10:14   ` [PATCH v3 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
@ 2020-05-21 10:14   ` Phillip Wood
  2020-05-23 12:30     ` Đoàn Trần Công Danh
  2020-05-21 10:14   ` [PATCH v3 5/5] rebase: add --reset-author-date Phillip Wood
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-21 10:14 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

As part of the on-going effort to retire the apply rebase backend
teach the merge backend how to handle --ignore-date. We take care to
handle the combination of --ignore-date and
--committer-date-is-author-date in the same way as the apply backend.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt   |  7 +++--
 builtin/rebase.c               | 13 +++++---
 sequencer.c                    | 50 +++++++++++++++++++++++++++--
 sequencer.h                    |  1 +
 t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++
 5 files changed, 118 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index dfa70263e6..e2717e20e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the author date of the original commit, use
+	the current time as the	author date of the rebased commit.  This
+	option implies `--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --ignore-date
  * --whitespace
  * -C
 
@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 357cd6acf3..cf86240bc8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -90,6 +90,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date || options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index 44e0b45e53..a21364c3be 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
 	BUG("GIT_AUTHOR_DATE missing from author script");
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, len) < 0) {
+		error(_("malformed ident line '%s'"), author);
+		return NULL;
+	}
+
+	len = ident.mail_end - ident.name_begin + 1;
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
 
 	if (opts->committer_date_is_author_date)
 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
 				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1387,7 +1410,8 @@ static int try_to_commit(struct repository *r,
 		strbuf_addf(&date, "@%.*s %.*s",
 			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
 			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
 		strbuf_release(&date);
 
 		if (res)
@@ -1453,6 +1477,16 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
+
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2582,6 +2616,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2674,6 +2713,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3596,7 +3637,11 @@ static int do_merge(struct repository *r,
 
 		if (opts->committer_date_is_author_date)
 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
 					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3876,7 +3921,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 4ab94119ae..3587878e3b 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -46,6 +46,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 84b9d5d37f..6cd3848689 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 	test_cmp expect actual
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with apply backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with merge backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -m HEAD^ &&
+	git log -1 --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -m \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log --pretty=%ai >authortime &&
+	grep +0000 authortime
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	git log --pretty=%ai >authortime &&
+	! grep -v "+0000" authortime
+'
+
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -2 --pretty=%ai >authortime &&
+	git log -2 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	! grep -v "+0000" authortime
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		git rebase -i --strategy=resolve --ignore-date \
+		--committer-date-is-author-date side side &&
+	git log -1 --pretty=%ai >authortime &&
+	git log -1 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	grep "+0000" authortime
+ '
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v3 5/5] rebase: add --reset-author-date
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
                     ` (3 preceding siblings ...)
  2020-05-21 10:14   ` [PATCH v3 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-05-21 10:14   ` Phillip Wood
  2020-05-22 15:54   ` [PATCH v3 0/5] cleanup ra/rebase-i-more-options Elijah Newren
  2020-05-23  6:59   ` Johannes Schindelin
  6 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-21 10:14 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The previous commit introduced --ignore-date flag to rebase -i, but the
name is rather vague as it does not say whether the author date or the
committer date is ignored. Add an alias to convey the precise purpose.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt   |  1 +
 builtin/rebase.c               |  6 ++++--
 t/t3436-rebase-more-options.sh | 34 ++++++++++++++++++++++------------
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e2717e20e6..a5f82913fb 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the author date of the original commit, use
 	the current time as the	author date of the rebased commit.  This
 	option implies `--force-rebase`.
diff --git a/builtin/rebase.c b/builtin/rebase.c
index cf86240bc8..911587690b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1519,8 +1519,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
-			 "ignore author date and use current date"),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 6cd3848689..2ee7346562 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -137,22 +137,22 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 # Checking for +0000 in author time is enough since default
 # timezone is UTC, but the timezone used while committing
 # sets to +0530.
-test_expect_success '--ignore-date works with apply backend' '
+test_expect_success '--reset-author-date works with apply backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --apply --ignore-date HEAD^ &&
+	git rebase --apply --reset-author-date HEAD^ &&
 	git log -1 --pretty="format:%ai" >authortime &&
 	grep "+0000" authortime
 '
 
-test_expect_success '--ignore-date works with merge backend' '
+test_expect_success '--reset-author-date works with merge backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --ignore-date -m HEAD^ &&
+	git rebase --reset-author-date -m HEAD^ &&
 	git log -1 --pretty="format:%ai" >authortime &&
 	grep "+0000" authortime
 '
 
-test_expect_success '--ignore-date works after conflict resolution' '
-	test_must_fail git rebase --ignore-date -m \
+test_expect_success '--reset-author-date works after conflict resolution' '
+	test_must_fail git rebase --reset-author-date -m \
 		--onto commit2^^ commit2^ commit2 &&
 	echo resolved >foo &&
 	git add foo &&
@@ -161,17 +161,17 @@ test_expect_success '--ignore-date works after conflict resolution' '
 	grep +0000 authortime
 '
 
-test_expect_success '--ignore-date works with rebase -r' '
+test_expect_success '--reset-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
-	git rebase -r --root --ignore-date &&
+	git rebase -r --root --reset-author-date &&
 	git log --pretty=%ai >authortime &&
 	! grep -v "+0000" authortime
 '
 
-test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
 	test_must_fail git rebase -m --committer-date-is-author-date \
-		--ignore-date --onto commit2^^ commit2^ commit3 &&
+		--reset-author-date --onto commit2^^ commit2^ commit3 &&
 	git checkout --theirs foo &&
 	git add foo &&
 	git rebase --continue &&
@@ -181,16 +181,26 @@ test_expect_success '--ignore-date with --committer-date-is-author-date works' '
 	! grep -v "+0000" authortime
 '
 
-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
 	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
-		git rebase -i --strategy=resolve --ignore-date \
+		git rebase -i --strategy=resolve --reset-author-date \
 		--committer-date-is-author-date side side &&
 	git log -1 --pretty=%ai >authortime &&
 	git log -1 --pretty=%ci >committertime &&
 	test_cmp authortime committertime &&
 	grep "+0000" authortime
  '
 
+test_expect_success '--ignore-date is an alias for --reset-author-date' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
+	git rebase -m --ignore-date HEAD^ &&
+	git log -2 --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime >output &&
+	test_line_count = 2 output
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 0/5] cleanup ra/rebase-i-more-options
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
                     ` (4 preceding siblings ...)
  2020-05-21 10:14   ` [PATCH v3 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-05-22 15:54   ` Elijah Newren
  2020-05-23  8:55     ` Phillip Wood
  2020-05-23  6:59   ` Johannes Schindelin
  6 siblings, 1 reply; 130+ messages in thread
From: Elijah Newren @ 2020-05-22 15:54 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal, Alban Gruin,
	Git Mailing List

On Thu, May 21, 2020 at 3:15 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Thanks for the feedback on v2, I've updated the documentation as
> suggested by Elijah and made the style fixes suggested by Alban but
> I've not changed read_author_script() for the reasons explained in
> https://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com

All my questions were answered earlier; this round addressed my
remaining feedback and I see no new issues.

Reviewed-by: Elijah Newren <newren@gmail.com>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 0/5] cleanup ra/rebase-i-more-options
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
                     ` (5 preceding siblings ...)
  2020-05-22 15:54   ` [PATCH v3 0/5] cleanup ra/rebase-i-more-options Elijah Newren
@ 2020-05-23  6:59   ` Johannes Schindelin
  6 siblings, 0 replies; 130+ messages in thread
From: Johannes Schindelin @ 2020-05-23  6:59 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal, Alban Gruin,
	Git Mailing List

Hi Phillip,

On Thu, 21 May 2020, Phillip Wood wrote:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Thanks for the feedback on v2, I've updated the documentation as
> suggested by Elijah and made the style fixes suggested by Alban but
> I've not changed read_author_script() for the reasons explained in
> https://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com
>
> These patches are based on 9fadedd637 ("Merge branch
> 'ds/default-pack-use-sparse-to-true'", 2020-03-29)

Thank you for working on these patches! TBH what I was looking to most in
that GSoC project was the ability to combine `--interactive` with Sverre's
`--whitespace=fix` option, but it never came even close to that. So I had
planned to help this patch series as much as I can.

Turns out that I do not really have any time to help this patch series,
therefore I am very happy to see Danh and Elijah jump in and review the
patch series, and that makes me think that between the three of you, it is
in good hands now.

Thanks,
Dscho

>
> Phillip Wood (2):
>   rebase -i: support --committer-date-is-author-date
>   rebase -i: support --ignore-date
>
> Rohit Ashiwal (3):
>   rebase -i: add --ignore-whitespace flag
>   sequencer: rename amend_author to author_to_free
>   rebase: add --reset-author-date
>
>  Documentation/git-rebase.txt           |  33 +++-
>  builtin/rebase.c                       |  46 ++++--
>  sequencer.c                            | 111 ++++++++++++-
>  sequencer.h                            |   2 +
>  t/t3422-rebase-incompatible-options.sh |   2 -
>  t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++
>  6 files changed, 379 insertions(+), 24 deletions(-)
>  create mode 100755 t/t3436-rebase-more-options.sh
>
> Range-diff against v2:
> 1:  5ef315240a ! 1:  df8c4ed2e9 rebase -i: add --ignore-whitespace flag
>     @@ Documentation/git-rebase.txt: your branch contains commits which were dropped, t
>       with `--keep-base` in order to drop those commits from your branch.
>
>       --ignore-whitespace::
>     -+	Behaves differently depending on which backend is selected.
>     ++	Ignore whitespace differences when trying to reconcile
>     ++differences. Currently, each backend implements an approximation of
>     ++this behavior:
>      ++
>      +apply backend: When applying a patch, ignore changes in whitespace in
>     -+context lines.
>     ++context lines. Unfortunately, this means that if the "old" lines being
>     ++replaced by the patch differ only in whitespace from the existing
>     ++file, you will get a merge conflict instead of a successful patch
>     ++application.
>      ++
>      +merge backend: Treat lines with only whitespace changes as unchanged
>     -+when merging.
>     ++when merging. Unfortunately, this means that any patch hunks that were
>     ++intended to modify whitespace and nothing else will be dropped, even
>     ++if the other side had no changes that conflicted.
>      +
>       --whitespace=<option>::
>      -	These flags are passed to the 'git apply' program
> 2:  55eb3a7efc ! 2:  df44a0bde6 rebase -i: support --committer-date-is-author-date
>     @@ Commit message
>          Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>
>       ## Documentation/git-rebase.txt ##
>     -@@ Documentation/git-rebase.txt: when merging.
>     +@@ Documentation/git-rebase.txt: if the other side had no changes that conflicted.
>       See also INCOMPATIBLE OPTIONS below.
>
>       --committer-date-is-author-date::
>     @@ sequencer.c: static int run_git_commit(struct repository *r,
>
>       	if (!(flags & VERIFY_MSG))
>      @@ sequencer.c: static int try_to_commit(struct repository *r,
>     -
>     - 	if (parse_head(r, &current_head))
>     - 		return -1;
>     --
>     - 	if (flags & AMEND_MSG) {
>     - 		const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
>     - 		const char *out_enc = get_commit_output_encoding();
>     -@@ sequencer.c: static int try_to_commit(struct repository *r,
>       		commit_list_insert(current_head, &parents);
>       	}
>
> 3:  19352fdc22 = 3:  fa3d4856b4 sequencer: rename amend_author to author_to_free
> 4:  5e971abb74 ! 4:  96657233d4 rebase -i: support --ignore-date
>     @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr
>      +		error(_("malformed ident line '%s'"), author);
>      +		return NULL;
>      +	}
>     ++
>      +	len = ident.mail_end - ident.name_begin + 1;
>     -+
>      +	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
>      +	datestamp(&new_author);
>      +	return strbuf_detach(&new_author, NULL);
>     @@ sequencer.c: static int try_to_commit(struct repository *r,
>      +		free(author_to_free);
>      +		author_to_free = (char *)author;
>      +	}
>     ++
>       	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>       				 oid, author, opts->gpg_sign, extra)) {
>       		res = error(_("failed to write commit object"));
> 5:  43a097c583 = 5:  828155baba rebase: add --reset-author-date
>
> --
> 2.26.2
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 0/5] cleanup ra/rebase-i-more-options
  2020-05-22 15:54   ` [PATCH v3 0/5] cleanup ra/rebase-i-more-options Elijah Newren
@ 2020-05-23  8:55     ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-23  8:55 UTC (permalink / raw)
  To: Elijah Newren, Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Rohit Ashiwal, Alban Gruin,
	Git Mailing List

On 22/05/2020 16:54, Elijah Newren wrote:
> On Thu, May 21, 2020 at 3:15 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> Thanks for the feedback on v2, I've updated the documentation as
>> suggested by Elijah and made the style fixes suggested by Alban but
>> I've not changed read_author_script() for the reasons explained in
>> https://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com
> 
> All my questions were answered earlier; this round addressed my
> remaining feedback and I see no new issues.
> 
> Reviewed-by: Elijah Newren <newren@gmail.com>

Thanks Elijah

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-21 10:14   ` [PATCH v3 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-05-23 12:30     ` Đoàn Trần Công Danh
  2020-05-23 15:43       ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-05-23 12:30 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Phillip,

On 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> +# Checking for +0000 in author time is enough since default
> +# timezone is UTC, but the timezone used while committing
> +# sets to +0530.
> +test_expect_success '--ignore-date works with apply backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --apply --ignore-date HEAD^ &&
> +	git log -1 --pretty="format:%ai" >authortime &&

Those --pretty="format:%ai" won't print the newline character in my
test environment.
It looks like it won't print the newline if stdout isn't a tty.

	git log -1 --pretty=%ai

doesn't have that issue.

I think there're some grep out there considers file doesn't end with
newline as non-text files.

> +	grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works with merge backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date -m HEAD^ &&
> +	git log -1 --pretty="format:%ai" >authortime &&
> +	grep "+0000" authortime
> +'
> +
> +test_expect_success '--ignore-date works after conflict resolution' '
> +	test_must_fail git rebase --ignore-date -m \
> +		--onto commit2^^ commit2^ commit2 &&
> +	echo resolved >foo &&
> +	git add foo &&
> +	git rebase --continue &&
> +	git log --pretty=%ai >authortime &&
> +	grep +0000 authortime
> +'

From the test's name, I guess git-rebase is supposed to continue
respect --ignore-date after conflict resolution.

But the content of authortime read:

	2020-05-23 12:13:58 +0000
	1999-04-02 08:03:20 +0530
	1999-04-02 08:03:20 +0530

It's still pass "grep +0000 authortime" because of first line,
I'm not sure if I missed anything.


-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-23 12:30     ` Đoàn Trần Công Danh
@ 2020-05-23 15:43       ` Phillip Wood
  2020-05-23 15:52         ` Đoàn Trần Công Danh
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-23 15:43 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 23/05/2020 13:30, Đoàn Trần Công Danh wrote:
> Hi Phillip,
> 
> On 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>> +# Checking for +0000 in author time is enough since default
>> +# timezone is UTC, but the timezone used while committing
>> +# sets to +0530.
>> +test_expect_success '--ignore-date works with apply backend' '
>> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
>> +	git rebase --apply --ignore-date HEAD^ &&
>> +	git log -1 --pretty="format:%ai" >authortime &&
> 
> Those --pretty="format:%ai" won't print the newline character in my
> test environment.
> It looks like it won't print the newline if stdout isn't a tty.
> 
> 	git log -1 --pretty=%ai
> 
> doesn't have that issue.
> 
> I think there're some grep out there considers file doesn't end with
> newline as non-text files.

Yes it would be better to print the newline, thanks

>> +	grep "+0000" authortime
>> +'
>> +
>> +test_expect_success '--ignore-date works with merge backend' '
>> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
>> +	git rebase --ignore-date -m HEAD^ &&
>> +	git log -1 --pretty="format:%ai" >authortime &&
>> +	grep "+0000" authortime
>> +'
>> +
>> +test_expect_success '--ignore-date works after conflict resolution' '
>> +	test_must_fail git rebase --ignore-date -m \
>> +		--onto commit2^^ commit2^ commit2 &&
>> +	echo resolved >foo &&
>> +	git add foo &&
>> +	git rebase --continue &&
>> +	git log --pretty=%ai >authortime &&
>> +	grep +0000 authortime
>> +'
> 
>  From the test's name, I guess git-rebase is supposed to continue
> respect --ignore-date after conflict resolution.
> 
> But the content of authortime read:
> 
> 	2020-05-23 12:13:58 +0000
> 	1999-04-02 08:03:20 +0530
> 	1999-04-02 08:03:20 +0530
> 
> It's still pass "grep +0000 authortime" because of first line,
> I'm not sure if I missed anything.

It's only rebasing one commit - the log command is missing -1. I've 
checked the log invocations in the other tests and I think they're all OK.

Junio - are you happy to fix this up (assuming there are no other 
issues) or do you want a re-roll?

Thanks

Phillip

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-23 15:43       ` Phillip Wood
@ 2020-05-23 15:52         ` Đoàn Trần Công Danh
  2020-05-23 18:50           ` Phillip Wood
  2020-05-24 16:32           ` Junio C Hamano
  0 siblings, 2 replies; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-05-23 15:52 UTC (permalink / raw)
  To: phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Phillip

On 2020-05-23 16:43:39+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> > On 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> > > +# Checking for +0000 in author time is enough since default
> > > +# timezone is UTC, but the timezone used while committing
> > > +# sets to +0530.
> > > +test_expect_success '--ignore-date works with apply backend' '
> > > +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> > > +	git rebase --apply --ignore-date HEAD^ &&
> > > +	git log -1 --pretty="format:%ai" >authortime &&
> > 
> > Those --pretty="format:%ai" won't print the newline character in my
> > test environment.
> > It looks like it won't print the newline if stdout isn't a tty.
> > 
> > 	git log -1 --pretty=%ai
> > 
> > doesn't have that issue.
> > 
> > I think there're some grep out there considers file doesn't end with
> > newline as non-text files.
> 
> Yes it would be better to print the newline, thanks
>
> Junio - are you happy to fix this up (assuming there are no other issues) or
> do you want a re-roll?

There're 11 invocation of git-log with "--pretty=format",
in 2/5 and 4/5

I think it's worth to have a re-roll to avoid mistake.

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-23 15:52         ` Đoàn Trần Công Danh
@ 2020-05-23 18:50           ` Phillip Wood
  2020-05-23 23:05             ` Đoàn Trần Công Danh
  2020-05-24 16:32           ` Junio C Hamano
  1 sibling, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-23 18:50 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 23/05/2020 16:52, Đoàn Trần Công Danh wrote:
> Hi Phillip
> 
> On 2020-05-23 16:43:39+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>>> On 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>>>> +# Checking for +0000 in author time is enough since default
>>>> +# timezone is UTC, but the timezone used while committing
>>>> +# sets to +0530.
>>>> +test_expect_success '--ignore-date works with apply backend' '
>>>> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
>>>> +	git rebase --apply --ignore-date HEAD^ &&
>>>> +	git log -1 --pretty="format:%ai" >authortime &&
>>>
>>> Those --pretty="format:%ai" won't print the newline character in my
>>> test environment.
>>> It looks like it won't print the newline if stdout isn't a tty.
>>>
>>> 	git log -1 --pretty=%ai
>>>
>>> doesn't have that issue.
>>>
>>> I think there're some grep out there considers file doesn't end with
>>> newline as non-text files.
>>
>> Yes it would be better to print the newline, thanks
>>
>> Junio - are you happy to fix this up (assuming there are no other issues) or
>> do you want a re-roll?
> 
> There're 11 invocation of git-log with "--pretty=format",
> in 2/5 and 4/5
> 
> I think it's worth to have a re-roll to avoid mistake.

The part of my reply you've cut said "I've checked the log invocations 
in the other tests and I think they're all OK." So it is just the one 
that you pointed out that needs to be fixed up (the others without -1 
are all checking the result of rebase --root). I'm happy to re-roll if 
Junio wants - lets wait and see what he says.

Best Wishes

Phillip
Phillip

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-23 18:50           ` Phillip Wood
@ 2020-05-23 23:05             ` Đoàn Trần Công Danh
  2020-05-27  9:55               ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-05-23 23:05 UTC (permalink / raw)
  To: phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Phillip,

On 2020-05-23 19:50:40+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> 
> The part of my reply you've cut said "I've checked the log invocations in
> the other tests and I think they're all OK." So it is just the one that you
> pointed out that needs to be fixed up (the others without -1 are all
> checking the result of rebase --root). I'm happy to re-roll if Junio wants -
> lets wait and see what he says.

Ah, I was thinking "they're all OK" meant that part can be left as-is,
and the only part need to change is the --pretty=format.

Sorry for the noise, (and my bad in reading).

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-23 15:52         ` Đoàn Trần Công Danh
  2020-05-23 18:50           ` Phillip Wood
@ 2020-05-24 16:32           ` Junio C Hamano
  1 sibling, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-05-24 16:32 UTC (permalink / raw)
  To: Đoàn Trần Công Danh
  Cc: phillip.wood, Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Alban Gruin, Git Mailing List

Đoàn Trần Công Danh  <congdanhqx@gmail.com> writes:

>> > I think there're some grep out there considers file doesn't end with
>> > newline as non-text files.
>> 
>> Yes it would be better to print the newline, thanks
>>
>> Junio - are you happy to fix this up (assuming there are no other issues) or
>> do you want a re-roll?
>
> There're 11 invocation of git-log with "--pretty=format",
> in 2/5 and 4/5
>
> I think it's worth to have a re-roll to avoid mistake.

It would be appropriate to send "[PATCH v3 6/5] fixup! ..." if the
fix needs to be made only to a single step.  It would be the least
error-prone approach.

Thanks.



^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v3 4/5] rebase -i: support --ignore-date
  2020-05-23 23:05             ` Đoàn Trần Công Danh
@ 2020-05-27  9:55               ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-27  9:55 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 24/05/2020 00:05, Đoàn Trần Công Danh wrote:
> Hi Phillip,
> 
> On 2020-05-23 19:50:40+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> The part of my reply you've cut said "I've checked the log invocations in
>> the other tests and I think they're all OK." So it is just the one that you
>> pointed out that needs to be fixed up (the others without -1 are all
>> checking the result of rebase --root). I'm happy to re-roll if Junio wants -
>> lets wait and see what he says.
> 
> Ah, I was thinking "they're all OK" meant that part can be left as-is,
> and the only part need to change is the --pretty=format.
> 
> Sorry for the noise, (and my bad in reading).

Looking at the patches again I think I misunderstood what you were 
saying - I had not twigged that I needed to remove the 'format:' from 
all the git log invocations. I'll send a reroll later.

Sorry for the confusion

Phillip

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v4 0/5] cleanup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (9 preceding siblings ...)
  2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
@ 2020-05-27 17:33 ` Phillip Wood
  2020-05-27 17:33   ` [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
                     ` (5 more replies)
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
                   ` (3 subsequent siblings)
  14 siblings, 6 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-27 17:33 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Thanks to Danh for the review, I've updated the tests accordingly.

Phillip Wood (2):
  rebase -i: support --committer-date-is-author-date
  rebase -i: support --ignore-date

Rohit Ashiwal (3):
  rebase -i: add --ignore-whitespace flag
  sequencer: rename amend_author to author_to_free
  rebase: add --reset-author-date

 Documentation/git-rebase.txt           |  33 +++-
 builtin/rebase.c                       |  46 ++++--
 sequencer.c                            | 111 ++++++++++++-
 sequencer.h                            |   2 +
 t/t3422-rebase-incompatible-options.sh |   2 -
 t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++
 6 files changed, 379 insertions(+), 24 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

Range-diff against v3:
1:  df8c4ed2e9 = 1:  df8c4ed2e9 rebase -i: add --ignore-whitespace flag
2:  df44a0bde6 ! 2:  ad21e5d8fb rebase -i: support --committer-date-is-author-date
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-whitespace is reme
     +test_expect_success '--committer-date-is-author-date works with apply backend' '
     +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
     +	git rebase --apply --committer-date-is-author-date HEAD^ &&
    -+	git log -1 --pretty="format:%ai" >authortime &&
    -+	git log -1 --pretty="format:%ci" >committertime &&
    ++	git log -1 --pretty=%ai >authortime &&
    ++	git log -1 --pretty=%ci >committertime &&
     +	test_cmp authortime committertime
     +'
     +
     +test_expect_success '--committer-date-is-author-date works with merge backend' '
     +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
     +	git rebase -m --committer-date-is-author-date HEAD^ &&
    -+	git log -1 --pretty="format:%ai" >authortime &&
    -+	git log -1 --pretty="format:%ci" >committertime &&
    ++	git log -1 --pretty=%ai >authortime &&
    ++	git log -1 --pretty=%ci >committertime &&
     +	test_cmp authortime committertime
     +'
     +
     +test_expect_success '--committer-date-is-author-date works with rebase -r' '
     +	git checkout side &&
     +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
     +	git rebase -r --root --committer-date-is-author-date &&
    -+	git log --pretty="format:%ai" >authortime &&
    -+	git log --pretty="format:%ci" >committertime &&
    ++	git log --pretty=%ai >authortime &&
    ++	git log --pretty=%ci >committertime &&
     +	test_cmp authortime committertime
     +'
     +
     +test_expect_success '--committer-date-is-author-date works when forking merge' '
     +	git checkout side &&
     +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
     +	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
    -+	git log --pretty="format:%ai" >authortime &&
    -+	git log --pretty="format:%ci" >committertime &&
    ++	git log --pretty=%ai >authortime &&
    ++	git log --pretty=%ci >committertime &&
     +	test_cmp authortime committertime
     +
     +'
3:  fa3d4856b4 = 3:  af92e29cf9 sequencer: rename amend_author to author_to_free
4:  96657233d4 ! 4:  4399dc19b6 rebase -i: support --ignore-date
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-
     +test_expect_success '--ignore-date works with apply backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --apply --ignore-date HEAD^ &&
    -+	git log -1 --pretty="format:%ai" >authortime &&
    ++	git log -1 --pretty=%ai >authortime &&
     +	grep "+0000" authortime
     +'
     +
     +test_expect_success '--ignore-date works with merge backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --ignore-date -m HEAD^ &&
    -+	git log -1 --pretty="format:%ai" >authortime &&
    ++	git log -1 --pretty=%ai >authortime &&
     +	grep "+0000" authortime
     +'
     +
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-
     +	echo resolved >foo &&
     +	git add foo &&
     +	git rebase --continue &&
    -+	git log --pretty=%ai >authortime &&
    ++	git log -1 --pretty=%ai >authortime &&
     +	grep +0000 authortime
     +'
     +
5:  828155baba ! 5:  a11db78eb4 rebase: add --reset-author-date
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-
      	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     -	git rebase --apply --ignore-date HEAD^ &&
     +	git rebase --apply --reset-author-date HEAD^ &&
    - 	git log -1 --pretty="format:%ai" >authortime &&
    + 	git log -1 --pretty=%ai >authortime &&
      	grep "+0000" authortime
      '
      
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-
      	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     -	git rebase --ignore-date -m HEAD^ &&
     +	git rebase --reset-author-date -m HEAD^ &&
    - 	git log -1 --pretty="format:%ai" >authortime &&
    + 	git log -1 --pretty=%ai >authortime &&
      	grep "+0000" authortime
      '
      

-- 
2.25.1.551.gd3318bf0d3.dirty


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
@ 2020-05-27 17:33   ` Phillip Wood
  2020-05-29  2:38     ` Johannes Schindelin
  2020-05-27 17:33   ` [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-27 17:33 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

Rebase is implemented with two different backends - 'apply' and 'merge'
each of which support a different set of options. In particuar the apply
backend supports a number of options implemented by 'git am' that are
not available to the merge backend. As part of an on going effort to
remove the apply backend this patch adds support for the
--ignore-whitespace option to the merge backend. This option treats
lines with only whitespace changes as unchanged and is implemented in
the merge backend by translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 19 +++++-
 builtin/rebase.c                       | 19 ++++--
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++
 4 files changed, 118 insertions(+), 7 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f7a6033607..b003784f01 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Ignore whitespace differences when trying to reconcile
+differences. Currently, each backend implements an approximation of
+this behavior:
++
+apply backend: When applying a patch, ignore changes in whitespace in
+context lines. Unfortunately, this means that if the "old" lines being
+replaced by the patch differ only in whitespace from the existing
+file, you will get a merge conflict instead of a successful patch
+application.
++
+merge backend: Treat lines with only whitespace changes as unchanged
+when merging. Unfortunately, this means that any patch hunks that were
+intended to modify whitespace and nothing else will be dropped, even
+if the other side had no changes that conflicted.
+
 --whitespace=<option>::
-	These flags are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 	Implies --apply.
 +
@@ -572,7 +587,6 @@ The following options:
  * --apply
  * --committer-date-is-author-date
  * --ignore-date
- * --ignore-whitespace
  * --whitespace
  * -C
 
@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 27a07d4e78..5d8e117276 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -86,6 +86,7 @@ struct rebase_options {
 	int signoff;
 	int allow_rerere_autoupdate;
 	int autosquash;
+	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
 	char *cmd;
@@ -108,6 +109,7 @@ struct rebase_options {
 
 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 {
+	struct strbuf strategy_buf = STRBUF_INIT;
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
-		parse_strategy_opts(&replay, opts->strategy_opts);
+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
+	if (opts->ignore_whitespace)
+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
+	if (strategy_buf.len)
+		parse_strategy_opts(&replay, strategy_buf.buf);
 
 	if (opts->squash_onto) {
 		oidcpy(&replay.squash_onto, opts->squash_onto);
 		replay.have_squash_onto = 1;
 	}
 
+	strbuf_release(&strategy_buf);
 	return replay;
 }
 
@@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options,
 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
 
+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
+
 	if (!is_null_oid(&squash_onto))
 		opts.squash_onto = &squash_onto;
 
@@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)
 	am.git_cmd = 1;
 	argv_array_push(&am.args, "am");
 
+	if (opts->ignore_whitespace)
+		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
new file mode 100755
index 0000000000..fb5e747e86
--- /dev/null
+++ b/t/t3436-rebase-more-options.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	q_to_tab >file <<-\EOF &&
+	line 1
+	Qline 2
+	line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	cat >file <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	sed -e "s/^|//" >file <<-\EOF &&
+	|line 1
+	|        line 2
+	|line 3
+	EOF
+	git add file &&
+	git commit -m "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with apply backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --apply main side &&
+	git rebase --abort &&
+	git rebase --apply --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace works with merge backend' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	test_cmp expect file
+'
+
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	cat >expect <<-\EOF &&
+	line 1
+	new line 2
+	line 3
+	EOF
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
+	) &&
+	git rebase --continue &&
+	test_cmp expect file
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
+test_done
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
  2020-05-27 17:33   ` [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-05-27 17:33   ` Phillip Wood
  2020-05-29  2:52     ` Johannes Schindelin
  2020-05-27 17:33   ` [PATCH v4 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-27 17:33 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

As part of the on-going effort to retire the apply rebase backend teach
the merge backend how to handle --committer-date-is-author-date.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 10 +++--
 builtin/rebase.c                       | 16 ++++---
 sequencer.c                            | 59 +++++++++++++++++++++++++-
 sequencer.h                            |  1 +
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++
 6 files changed, 133 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b003784f01..dfa70263e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of using the current time as the committer date, use
+	the author date of the commit being rebased as the committer
+	date. This option implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5d8e117276..357cd6acf3 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -89,6 +89,7 @@ struct rebase_options {
 	int ignore_whitespace;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)
 
 	if (opts->ignore_whitespace)
 		argv_array_push(&am.args, "--ignore-whitespace");
+	if (opts->committer_date_is_author_date)
+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
diff --git a/sequencer.c b/sequencer.c
index 6fd2674632..8826c6325b 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -872,6 +873,22 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+static const char *author_date_from_env_array(const struct argv_array *env)
+{
+	int i;
+	const char *date;
+
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
 			     gpg_opt, gpg_opt);
 	}
 
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 author_date_from_env_array(&cmd.env_array));
+
 	argv_array_push(&cmd.args, "commit");
 
 	if (!(flags & VERIFY_MSG))
@@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		int len = strlen(author);
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, len) < 0) {
+			res = error(_("malformed ident line '%s'"), author);
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
 	if (opts->keep_redundant_commits)
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,
 			goto leave_merge;
 		}
 
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 author_date_from_env_array(&cmd.env_array));
+
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
 		argv_array_push(&cmd.args, "-s");
@@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 0bee85093e..4ab94119ae 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -45,6 +45,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index fb5e747e86..7e68fb9753 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -28,8 +31,13 @@ test_expect_success 'setup' '
 	EOF
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	git rm --cached foo &&
+	rm foo &&
 	sed -e "s/^|//" >file <<-\EOF &&
 	|line 1
 	|        line 2
@@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
 	test_cmp expect file
 '
 
+test_expect_success '--committer-date-is-author-date works with apply backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase --apply --committer-date-is-author-date HEAD^ &&
+	git log -1 --pretty=%ai >authortime &&
+	git log -1 --pretty=%ci >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with merge backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase -m --committer-date-is-author-date HEAD^ &&
+	git log -1 --pretty=%ai >authortime &&
+	git log -1 --pretty=%ci >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	git log --pretty=%ai >authortime &&
+	git log --pretty=%ci >committertime &&
+	test_cmp authortime committertime
+'
+
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
+	git log --pretty=%ai >authortime &&
+	git log --pretty=%ci >committertime &&
+	test_cmp authortime committertime
+
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	git log -1 --format=%at HEAD >expect &&
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -1 --format=%ct HEAD >actual &&
+	test_cmp expect actual
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v4 3/5] sequencer: rename amend_author to author_to_free
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
  2020-05-27 17:33   ` [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-05-27 17:33   ` [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-05-27 17:33   ` Phillip Wood
  2020-05-27 17:33   ` [PATCH v4 4/5] rebase -i: support --ignore-date Phillip Wood
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-27 17:33 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() when amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 8826c6325b..44e0b45e53 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1473,7 +1473,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v4 4/5] rebase -i: support --ignore-date
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
                     ` (2 preceding siblings ...)
  2020-05-27 17:33   ` [PATCH v4 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
@ 2020-05-27 17:33   ` Phillip Wood
  2020-05-27 17:33   ` [PATCH v4 5/5] rebase: add --reset-author-date Phillip Wood
  2020-05-27 21:10   ` [PATCH v4 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-05-27 17:33 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

As part of the on-going effort to retire the apply rebase backend
teach the merge backend how to handle --ignore-date. We take care to
handle the combination of --ignore-date and
--committer-date-is-author-date in the same way as the apply backend.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt   |  7 +++--
 builtin/rebase.c               | 13 +++++---
 sequencer.c                    | 50 +++++++++++++++++++++++++++--
 sequencer.h                    |  1 +
 t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++
 5 files changed, 118 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index dfa70263e6..e2717e20e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the author date of the original commit, use
+	the current time as the	author date of the rebased commit.  This
+	option implies `--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --ignore-date
  * --whitespace
  * -C
 
@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 357cd6acf3..cf86240bc8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -90,6 +90,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)
 		argv_array_push(&am.args, "--ignore-whitespace");
 	if (opts->committer_date_is_author_date)
 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
+	if (opts->ignore_date)
+		argv_array_push(&opts->git_am_opts, "--ignore-date");
 	if (opts->action && !strcmp("continue", opts->action)) {
 		argv_array_push(&am.args, "--resolved");
 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date || options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
 		else if (skip_prefix(option, "-C", &p)) {
diff --git a/sequencer.c b/sequencer.c
index 44e0b45e53..a21364c3be 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
 	BUG("GIT_AUTHOR_DATE missing from author script");
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, len) < 0) {
+		error(_("malformed ident line '%s'"), author);
+		return NULL;
+	}
+
+	len = ident.mail_end - ident.name_begin + 1;
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
 
 	if (opts->committer_date_is_author_date)
 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
 				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1387,7 +1410,8 @@ static int try_to_commit(struct repository *r,
 		strbuf_addf(&date, "@%.*s %.*s",
 			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
 			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
 		strbuf_release(&date);
 
 		if (res)
@@ -1453,6 +1477,16 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
+
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2582,6 +2616,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2674,6 +2713,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3596,7 +3637,11 @@ static int do_merge(struct repository *r,
 
 		if (opts->committer_date_is_author_date)
 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
 					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3876,7 +3921,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 4ab94119ae..3587878e3b 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -46,6 +46,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 7e68fb9753..a3f9d5b41a 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 	test_cmp expect actual
 '
 
+# Checking for +0000 in author time is enough since default
+# timezone is UTC, but the timezone used while committing
+# sets to +0530.
+test_expect_success '--ignore-date works with apply backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git log -1 --pretty=%ai >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works with merge backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -m HEAD^ &&
+	git log -1 --pretty=%ai >authortime &&
+	grep "+0000" authortime
+'
+
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -m \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -1 --pretty=%ai >authortime &&
+	grep +0000 authortime
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	git log --pretty=%ai >authortime &&
+	! grep -v "+0000" authortime
+'
+
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	git log -2 --pretty=%ai >authortime &&
+	git log -2 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	! grep -v "+0000" authortime
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		git rebase -i --strategy=resolve --ignore-date \
+		--committer-date-is-author-date side side &&
+	git log -1 --pretty=%ai >authortime &&
+	git log -1 --pretty=%ci >committertime &&
+	test_cmp authortime committertime &&
+	grep "+0000" authortime
+ '
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v4 5/5] rebase: add --reset-author-date
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
                     ` (3 preceding siblings ...)
  2020-05-27 17:33   ` [PATCH v4 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-05-27 17:33   ` Phillip Wood
  2020-05-27 17:57     ` [PATCH v4 6/5] fixup! " Phillip Wood
  2020-05-27 21:10   ` [PATCH v4 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-27 17:33 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The previous commit introduced --ignore-date flag to rebase -i, but the
name is rather vague as it does not say whether the author date or the
committer date is ignored. Add an alias to convey the precise purpose.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt   |  1 +
 builtin/rebase.c               |  6 ++++--
 t/t3436-rebase-more-options.sh | 34 ++++++++++++++++++++++------------
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e2717e20e6..a5f82913fb 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the author date of the original commit, use
 	the current time as the	author date of the rebased commit.  This
 	option implies `--force-rebase`.
diff --git a/builtin/rebase.c b/builtin/rebase.c
index cf86240bc8..911587690b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1519,8 +1519,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
-			 "ignore author date and use current date"),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index a3f9d5b41a..5ee193f333 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -137,22 +137,22 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 # Checking for +0000 in author time is enough since default
 # timezone is UTC, but the timezone used while committing
 # sets to +0530.
-test_expect_success '--ignore-date works with apply backend' '
+test_expect_success '--reset-author-date works with apply backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --apply --ignore-date HEAD^ &&
+	git rebase --apply --reset-author-date HEAD^ &&
 	git log -1 --pretty=%ai >authortime &&
 	grep "+0000" authortime
 '
 
-test_expect_success '--ignore-date works with merge backend' '
+test_expect_success '--reset-author-date works with merge backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --ignore-date -m HEAD^ &&
+	git rebase --reset-author-date -m HEAD^ &&
 	git log -1 --pretty=%ai >authortime &&
 	grep "+0000" authortime
 '
 
-test_expect_success '--ignore-date works after conflict resolution' '
-	test_must_fail git rebase --ignore-date -m \
+test_expect_success '--reset-author-date works after conflict resolution' '
+	test_must_fail git rebase --reset-author-date -m \
 		--onto commit2^^ commit2^ commit2 &&
 	echo resolved >foo &&
 	git add foo &&
@@ -161,17 +161,17 @@ test_expect_success '--ignore-date works after conflict resolution' '
 	grep +0000 authortime
 '
 
-test_expect_success '--ignore-date works with rebase -r' '
+test_expect_success '--reset-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
-	git rebase -r --root --ignore-date &&
+	git rebase -r --root --reset-author-date &&
 	git log --pretty=%ai >authortime &&
 	! grep -v "+0000" authortime
 '
 
-test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
 	test_must_fail git rebase -m --committer-date-is-author-date \
-		--ignore-date --onto commit2^^ commit2^ commit3 &&
+		--reset-author-date --onto commit2^^ commit2^ commit3 &&
 	git checkout --theirs foo &&
 	git add foo &&
 	git rebase --continue &&
@@ -181,16 +181,26 @@ test_expect_success '--ignore-date with --committer-date-is-author-date works' '
 	! grep -v "+0000" authortime
 '
 
-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
 	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
-		git rebase -i --strategy=resolve --ignore-date \
+		git rebase -i --strategy=resolve --reset-author-date \
 		--committer-date-is-author-date side side &&
 	git log -1 --pretty=%ai >authortime &&
 	git log -1 --pretty=%ci >committertime &&
 	test_cmp authortime committertime &&
 	grep "+0000" authortime
  '
 
+test_expect_success '--ignore-date is an alias for --reset-author-date' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
+	git rebase -m --ignore-date HEAD^ &&
+	git log -2 --pretty="format:%ai" >authortime &&
+	grep "+0000" authortime >output &&
+	test_line_count = 2 output
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v4 6/5] fixup! rebase: add --reset-author-date
  2020-05-27 17:33   ` [PATCH v4 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-05-27 17:57     ` Phillip Wood
  2020-05-28 13:17       ` Đoàn Trần Công Danh
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-05-27 17:57 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Sorry I somehow forgot to commit this before sending the v4 patches,
it fixes up the final patch

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 t/t3436-rebase-more-options.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 5ee193f333..ecfd68397f 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
 	git rebase --apply --ignore-date HEAD^ &&
 	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
 	git rebase -m --ignore-date HEAD^ &&
-	git log -2 --pretty="format:%ai" >authortime &&
+	git log -2 --pretty=%ai >authortime &&
 	grep "+0000" authortime >output &&
 	test_line_count = 2 output
 '
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 0/5] cleanup ra/rebase-i-more-options
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
                     ` (4 preceding siblings ...)
  2020-05-27 17:33   ` [PATCH v4 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-05-27 21:10   ` Junio C Hamano
  5 siblings, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-05-27 21:10 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

>     -+	git log -1 --pretty="format:%ai" >authortime &&
>     ++	git log -1 --pretty=%ai >authortime &&

It probably wouldn't make too much of a difference in real life, but
I think "--format=%ai" is how the above is customary written.

Some history.

The --pretty="format:<string with per-cent placeholder>" came first,
with an explicit goal of giving us enough flexibility to mimick
canned "pretty print" formats like --pretty=medium, --pretty=short,
etc. (note: it was *not* part of the goal to actually replace the
implementation of canned formats with hardcoded set of placeholder
strings).

If you run "git log --pretty=medium -2", you'd observe that the
topmost commit is shown immediately without any preceding blank
line, then an extra blank line is shown, and then the second commit
is shown, and after that, the output ends without any extra blank
line.  With respect to the "extra blank line", we call this
"separator semantics"---an extra blank is given _between_ two items
that are shown.

Like "git log --pretty=medium", the "format:<custom>" pretty print
format uses the "separator semantics".  There is no "extra LF" after
showing the last item.

Of course, the "separator" behaviour was later found to be
cumbersome if we wanted to mimick "--pretty=oneline".  The payload
of each item in the oneline output format lacks the terminating LF,
so instead of an extra LF between two items, we want an extra LF
after every item.  This, in contrast to "separator" semantics, is
called "terminator" semantics and --pretty="tformat:<custom>" was
introduced to allow.

Later, when we introduced --format=<format>, we made it so that 

 (1) when <format> is equal to one of the canned format names,
     "--format=<format>" is equivalent to "--<format>".

 (2) otherwise, when <format> has placeholders, "--format=<format>"
     acts the same way as "--pretty=tformat:<format>".

as we found out that people are often using custom format that
consists of only one line of payload, quite often as a way to
extract a handful of "fields" from each commit object.

So given all of the above, the "let's grab the author-time in iso
format and nothing else from each commit object" in the above
excerpt from your test is the use case for which --format=%ai was
designed.


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 6/5] fixup! rebase: add --reset-author-date
  2020-05-27 17:57     ` [PATCH v4 6/5] fixup! " Phillip Wood
@ 2020-05-28 13:17       ` Đoàn Trần Công Danh
  2020-05-29  2:59         ` Johannes Schindelin
  0 siblings, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-05-28 13:17 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

On 2020-05-27 18:57:48+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
> 
> Sorry I somehow forgot to commit this before sending the v4 patches,
> it fixes up the final patch
> 
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  t/t3436-rebase-more-options.sh | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 5ee193f333..ecfd68397f 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
>  	git rebase --apply --ignore-date HEAD^ &&
>  	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
>  	git rebase -m --ignore-date HEAD^ &&
> -	git log -2 --pretty="format:%ai" >authortime &&
> +	git log -2 --pretty=%ai >authortime &&
>  	grep "+0000" authortime >output &&
>  	test_line_count = 2 output
>  '

This version addressed all of my concerns, LGTM.

Only the last

	test_line_count = 2 output

puzzled me at first.
Since it's the only usage of test_line_count in this version
Turn out, it's equivalence with:
-----------8<-----------
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index ecfd68397f..abe9af4d8c 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -197,8 +197,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
 	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
 	git rebase -m --ignore-date HEAD^ &&
 	git log -2 --pretty=%ai >authortime &&
-	grep "+0000" authortime >output &&
-	test_line_count = 2 output
+	! grep -v "+0000" authortime
 '
 
 # This must be the last test in this file
------>8------

This is the check used in t3436.15
Current version is good as is, anyway.

-- 
Danh

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag
  2020-05-27 17:33   ` [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-05-29  2:38     ` Johannes Schindelin
  2020-06-01  9:23       ` Kerry, Richard
  2020-06-01 10:26       ` Phillip Wood
  0 siblings, 2 replies; 130+ messages in thread
From: Johannes Schindelin @ 2020-05-29  2:38 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi Phillip,

sorry to be _so_ late in the game. (And sorry for sending this to you
twice, I managed to skip all the Cc:s due to the Reply-To: header the
first time round.)

On Wed, 27 May 2020, Phillip Wood wrote:

> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>
> Rebase is implemented with two different backends - 'apply' and 'merge'
> each of which support a different set of options. In particuar the apply
> backend supports a number of options implemented by 'git am' that are
> not available to the merge backend. As part of an on going effort to

As a non-native speaker, I am thrown off when reading "available to"
instead of the grammatically correct (I believe) "available in". Likewise,
"on going" instead of "ongoing" just disrupts my workflow.

Maybe these can be fixed?

> remove the apply backend this patch adds support for the
> --ignore-whitespace option to the merge backend. This option treats
> lines with only whitespace changes as unchanged and is implemented in
> the merge backend by translating it to -Xignore-space-change.
>
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt           | 19 +++++-
>  builtin/rebase.c                       | 19 ++++--
>  t/t3422-rebase-incompatible-options.sh |  1 -
>  t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++
>  4 files changed, 118 insertions(+), 7 deletions(-)
>  create mode 100755 t/t3436-rebase-more-options.sh
>
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index f7a6033607..b003784f01 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
>  with `--keep-base` in order to drop those commits from your branch.
>
>  --ignore-whitespace::
> +	Ignore whitespace differences when trying to reconcile
> +differences. Currently, each backend implements an approximation of
> +this behavior:
> ++
> +apply backend: When applying a patch, ignore changes in whitespace in
> +context lines. Unfortunately, this means that if the "old" lines being
> +replaced by the patch differ only in whitespace from the existing
> +file, you will get a merge conflict instead of a successful patch
> +application.
> ++
> +merge backend: Treat lines with only whitespace changes as unchanged
> +when merging. Unfortunately, this means that any patch hunks that were
> +intended to modify whitespace and nothing else will be dropped, even
> +if the other side had no changes that conflicted.
> +
>  --whitespace=<option>::
> -	These flags are passed to the 'git apply' program
> +	This flag is passed to the 'git apply' program
>  	(see linkgit:git-apply[1]) that applies the patch.
>  	Implies --apply.
>  +
> @@ -572,7 +587,6 @@ The following options:
>   * --apply
>   * --committer-date-is-author-date
>   * --ignore-date
> - * --ignore-whitespace
>   * --whitespace
>   * -C
>
> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --signoff
>   * --preserve-merges and --rebase-merges
>   * --preserve-merges and --empty=
> + * --preserve-merges and --ignore-whitespace
>   * --keep-base and --onto
>   * --keep-base and --root
>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 27a07d4e78..5d8e117276 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -86,6 +86,7 @@ struct rebase_options {
>  	int signoff;
>  	int allow_rerere_autoupdate;
>  	int autosquash;
> +	int ignore_whitespace;
>  	char *gpg_sign_opt;
>  	int autostash;
>  	char *cmd;
> @@ -108,6 +109,7 @@ struct rebase_options {
>
>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  {
> +	struct strbuf strategy_buf = STRBUF_INIT;
>  	struct replay_opts replay = REPLAY_OPTS_INIT;
>
>  	replay.action = REPLAY_INTERACTIVE_REBASE;
> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>  	replay.strategy = opts->strategy;
> +
>  	if (opts->strategy_opts)
> -		parse_strategy_opts(&replay, opts->strategy_opts);
> +		strbuf_addstr(&strategy_buf, opts->strategy_opts);
> +	if (opts->ignore_whitespace)
> +		strbuf_addstr(&strategy_buf, " --ignore-space-change");
> +	if (strategy_buf.len)
> +		parse_strategy_opts(&replay, strategy_buf.buf);

Quite honestly, this is very, very ugly.

I would have expected this at a way earlier layer, namely in
`cmd__rebase()`. Something along these lines:

-- snip --
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 37ba76ac3d26..748e08aee2f2 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1289,6 +1289,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct strbuf revisions = STRBUF_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id merge_base;
+	int ignore_whitespace = 0;
 	enum action action = ACTION_NONE;
 	const char *gpg_sign = NULL;
 	struct string_list exec = STRING_LIST_INIT_NODUP;
@@ -1318,9 +1319,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
+			 N_("passed to 'git am'")),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1682,6 +1682,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		imply_merge(&options, "--rebase-merges");
 	}

+	if (ignore_whitespace) {
+		if (options.type == REBASE_APPLY)
+			argv_array_push(&options.git_am_opts,
+					"--ignore-whitespace");
+		else
+			string_list_append(&stragey_options,
+					   "--ignore-space-change");
+	}
+
 	if (strategy_options.nr) {
 		int i;

-- snap --


>
>  	if (opts->squash_onto) {
>  		oidcpy(&replay.squash_onto, opts->squash_onto);
>  		replay.have_squash_onto = 1;
>  	}
>
> +	strbuf_release(&strategy_buf);
>  	return replay;
>  }
>
> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>  	argc = parse_options(argc, argv, prefix, options,
>  			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>
> +	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);

I am not sure what this is about: `opts.strategy_opts` is of type `char
*`, i.e. it is supposed to be already allocated.

Not that `cmd_rebase__interactive()` matters _all_ that much anymore, of
course: it is only used by the --preserve-merges backend, which will
hopefully be retired soon.

> +
>  	if (!is_null_oid(&squash_onto))
>  		opts.squash_onto = &squash_onto;
>
> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)
>  	am.git_cmd = 1;
>  	argv_array_push(&am.args, "am");
>
> +	if (opts->ignore_whitespace)
> +		argv_array_push(&am.args, "--ignore-whitespace");
>  	if (opts->action && !strcmp("continue", opts->action)) {
>  		argv_array_push(&am.args, "--resolved");
>  		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>  		OPT_BOOL(0, "signoff", &options.signoff,
>  			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -				  NULL, N_("passed to 'git am'"),
> -				  PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>  				  &options.git_am_opts, NULL,
>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>  				  N_("passed to 'git apply'"), 0),
> +		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
> +			 N_("ignore changes in whitespace")),
>  		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>  				  N_("action"), N_("passed to 'git apply'"), 0),
>  		OPT_BIT('f', "force-rebase", &options.flags,
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 50e7960702..55ca46786d 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
>  test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> new file mode 100755
> index 0000000000..fb5e747e86
> --- /dev/null
> +++ b/t/t3436-rebase-more-options.sh
> @@ -0,0 +1,86 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2019 Rohit Ashiwal
> +#
> +
> +test_description='tests to ensure compatibility between am and interactive backends'
> +
> +. ./test-lib.sh
> +
> +. "$TEST_DIRECTORY"/lib-rebase.sh
> +
> +# This is a special case in which both am and interactive backends
> +# provide the same output. It was done intentionally because
> +# both the backends fall short of optimal behaviour.
> +test_expect_success 'setup' '
> +	git checkout -b topic &&
> +	q_to_tab >file <<-\EOF &&
> +	line 1
> +	Qline 2
> +	line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	cat >file <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	git commit -am "update file" &&
> +	git tag side &&
> +
> +	git checkout --orphan master &&
> +	sed -e "s/^|//" >file <<-\EOF &&
> +	|line 1
> +	|        line 2
> +	|line 3
> +	EOF
> +	git add file &&
> +	git commit -m "add file" &&
> +	git tag main
> +'

The file contents are repeated in an awfully repetitive manner. That not
only makes things a bit hard to read, it also makes it all too easy to
slip in bugs by mistake. How about something like this instead?

	test_commit file &&

	test_write_lines line1 Qline2 line3 >templ &&

	q_to_tab <templ >file.t &&
	git commit -m tab file.t &&

	sed "s/Q/new /" <templ >file.t &&
	git commit -m new file.t &&
	git tag side &&

	git checkout file -- &&
	sed "s/Q/        /" <templ >file.t &&
	git commit -m spaces file.t

... and then...

> +
> +test_expect_success '--ignore-whitespace works with apply backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF

	sed "s/Q/new /" <templ >expect

> +	test_must_fail git rebase --apply main side &&
> +	git rebase --abort &&
> +	git rebase --apply --ignore-whitespace main side &&
> +	test_cmp expect file

Personally, I prefer to read the contents of `expect` directly before the
`test_cmp expect file.t`

> +'
> +
> +test_expect_success '--ignore-whitespace works with merge backend' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF

Isn't this totally identical to the `expect` constructed earlier? And in
any case, isn't this identical to `git show main:file.t`, which is what we
_actually_ expect: for the file contents to be identical to the tagged
`main`? I.e.

	git diff --exit-code main

> +	test_must_fail git rebase --merge main side &&
> +	git rebase --abort &&
> +	git rebase --merge --ignore-whitespace main side &&
> +	test_cmp expect file
> +'
> +
> +test_expect_success '--ignore-whitespace is remembered when continuing' '
> +	cat >expect <<-\EOF &&
> +	line 1
> +	new line 2
> +	line 3
> +	EOF
> +	(
> +		set_fake_editor &&
> +		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
> +	) &&
> +	git rebase --continue &&
> +	test_cmp expect file

It is a bit funny to see these two invocations _specifically_ pulled out
from the subshell, that's not how we do things in other test scripts:
instead, we run all the Git commands _inside_ the subshell, and all the
verifications after the subshell.

I believe that with my suggestions, this test script will be a ton easier
to read and to maintain. At least it will be a lot DRYer.

Ciao,
Dscho

> +'
> +
> +# This must be the last test in this file
> +test_expect_success '$EDITOR and friends are unchanged' '
> +	test_editor_unchanged
> +'
> +
> +test_done
> --
> 2.26.2
>
>

^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date
  2020-05-27 17:33   ` [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-05-29  2:52     ` Johannes Schindelin
  2020-06-01 10:33       ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Johannes Schindelin @ 2020-05-29  2:52 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi Phillip,

On Wed, 27 May 2020, Phillip Wood wrote:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> As part of the on-going effort to retire the apply rebase backend teach
> the merge backend how to handle --committer-date-is-author-date.

I forgot to mention this in my reply to the first patch in this series: it
strikes me as a mis-characterization that the `apply` backend is about to
be retired. What _is_ true is that the `merge` backend is the default
backend, and what is even more true is that it is cumbersome if certain
`rebase` options cannot be combined because they are only implemented by
one of both rebase backends.

>
> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt           | 10 +++--
>  builtin/rebase.c                       | 16 ++++---
>  sequencer.c                            | 59 +++++++++++++++++++++++++-
>  sequencer.h                            |  1 +
>  t/t3422-rebase-incompatible-options.sh |  1 -
>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++
>  6 files changed, 133 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index b003784f01..dfa70263e6 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -445,9 +445,13 @@ if the other side had no changes that conflicted.
>  See also INCOMPATIBLE OPTIONS below.
>
>  --committer-date-is-author-date::
> +	Instead of using the current time as the committer date, use
> +	the author date of the commit being rebased as the committer
> +	date. This option implies --force-rebase.
> +
>  --ignore-date::
> -	These flags are passed to 'git am' to easily change the dates
> -	of the rebased commits (see linkgit:git-am[1]).
> +	This flag is passed to 'git am' to change the author date
> +	of each rebased commit (see linkgit:git-am[1]).
>  +
>  See also INCOMPATIBLE OPTIONS below.
>
> @@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS
>  The following options:
>
>   * --apply
> - * --committer-date-is-author-date
>   * --ignore-date
>   * --whitespace
>   * -C
> @@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --rebase-merges
>   * --preserve-merges and --empty=
>   * --preserve-merges and --ignore-whitespace
> + * --preserve-merges and --committer-date-is-author-date
>   * --keep-base and --onto
>   * --keep-base and --root
>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 5d8e117276..357cd6acf3 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -89,6 +89,7 @@ struct rebase_options {
>  	int ignore_whitespace;
>  	char *gpg_sign_opt;
>  	int autostash;
> +	int committer_date_is_author_date;
>  	char *cmd;
>  	int allow_empty_message;
>  	int rebase_merges, rebase_cousins;
> @@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
>  	replay.verbose = opts->flags & REBASE_VERBOSE;
>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +	replay.committer_date_is_author_date =
> +					opts->committer_date_is_author_date;
>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>  	replay.strategy = opts->strategy;
>
> @@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)
>
>  	if (opts->ignore_whitespace)
>  		argv_array_push(&am.args, "--ignore-whitespace");
> +	if (opts->committer_date_is_author_date)
> +		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");

As before, I would rather see this in `cmd__rebase()` rahn in `run_am()`.

>  	if (opts->action && !strcmp("continue", opts->action)) {
>  		argv_array_push(&am.args, "--resolved");
>  		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
> @@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>  		OPT_BOOL(0, "signoff", &options.signoff,
>  			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -				  &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "committer-date-is-author-date",
> +			 &options.committer_date_is_author_date,
> +			 N_("make committer date match author date")),
>  		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> @@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  	    options.autosquash) {
>  		allow_preemptive_ff = 0;
>  	}
> +	if (options.committer_date_is_author_date)
> +		options.flags |= REBASE_FORCE;
>
>  	for (i = 0; i < options.git_am_opts.argc; i++) {
>  		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--committer-date-is-author-date") ||
> -		    !strcmp(option, "--ignore-date") ||
> +		if (!strcmp(option, "--ignore-date") ||
>  		    !strcmp(option, "--whitespace=fix") ||
>  		    !strcmp(option, "--whitespace=strip"))
>  			allow_preemptive_ff = 0;
> diff --git a/sequencer.c b/sequencer.c
> index 6fd2674632..8826c6325b 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   * command-line.
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -872,6 +873,22 @@ static char *get_author(const char *message)
>  	return NULL;
>  }
>
> +static const char *author_date_from_env_array(const struct argv_array *env)
> +{
> +	int i;
> +	const char *date;
> +
> +	for (i = 0; i < env->argc; i++)
> +		if (skip_prefix(env->argv[i],
> +				"GIT_AUTHOR_DATE=", &date))
> +			return date;
> +	/*
> +	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
> +	 * reading the script
> +	 */
> +	BUG("GIT_AUTHOR_DATE missing from author script");
> +}
> +
>  static const char staged_changes_advice[] =
>  N_("you have staged changes in your working tree\n"
>  "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
>  			     gpg_opt, gpg_opt);
>  	}
>
> +	if (opts->committer_date_is_author_date)
> +		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +				 author_date_from_env_array(&cmd.env_array));
> +
>  	argv_array_push(&cmd.args, "commit");
>
>  	if (!(flags & VERIFY_MSG))
> @@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,
>  		commit_list_insert(current_head, &parents);
>  	}
>
> +	if (opts->committer_date_is_author_date) {
> +		int len = strlen(author);

Given that `len` is used only once, is this local variable really
necessary? You could just as well pass `(int)strlen(author)` in the
`split_ident_line()` call below.

> +		struct ident_split ident;
> +		struct strbuf date = STRBUF_INIT;
> +
> +		if (split_ident_line(&ident, author, len) < 0) {
> +			res = error(_("malformed ident line '%s'"), author);
> +			goto out;
> +		}
> +		if (!ident.date_begin) {
> +			res = error(_("corrupted author without date information"));
> +			goto out;
> +		}
> +
> +		strbuf_addf(&date, "@%.*s %.*s",
> +			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
> +			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
> +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		strbuf_release(&date);

It might be easier to read if it was written this way:

		if (split_ident_line(...) < 0)
			res = ...
		else if (!ident.date_begin)
			res = ...
		else {
			strbuf_addf(...)
			res = ...
			strbuf_release(&date);
		}

		if (res)
			goto out;

> +
> +		if (res)
> +			goto out;
> +	}
> +
>  	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>  		res = error(_("git write-tree failed to write a tree"));
>  		goto out;
> @@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)
>  			opts->signoff = 1;
>  		}
>
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>  		if (file_exists(rebase_path_reschedule_failed_exec()))
>  			opts->reschedule_failed_exec = 1;
>
> @@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>  		write_file(rebase_path_drop_redundant_commits(), "%s", "");
>  	if (opts->keep_redundant_commits)
>  		write_file(rebase_path_keep_redundant_commits(), "%s", "");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>  	if (opts->reschedule_failed_exec)
>  		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>
> @@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,
>  			goto leave_merge;
>  		}
>
> +		if (opts->committer_date_is_author_date)
> +			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +					 author_date_from_env_array(&cmd.env_array));
> +
>  		cmd.git_cmd = 1;
>  		argv_array_push(&cmd.args, "merge");
>  		argv_array_push(&cmd.args, "-s");
> @@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,
>  	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>  	if (opts->allow_ff)
>  		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>  	if (read_and_refresh_cache(r, opts))
>  		return -1;
>
> diff --git a/sequencer.h b/sequencer.h
> index 0bee85093e..4ab94119ae 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -45,6 +45,7 @@ struct replay_opts {
>  	int verbose;
>  	int quiet;
>  	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>
>  	int mainline;
>
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 55ca46786d..c8234062c6 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>
>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index fb5e747e86..7e68fb9753 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>
>  . "$TEST_DIRECTORY"/lib-rebase.sh
>
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>  # This is a special case in which both am and interactive backends
>  # provide the same output. It was done intentionally because
>  # both the backends fall short of optimal behaviour.
> @@ -28,8 +31,13 @@ test_expect_success 'setup' '
>  	EOF
>  	git commit -am "update file" &&
>  	git tag side &&
> +	test_commit commit1 foo foo1 &&
> +	test_commit commit2 foo foo2 &&
> +	test_commit commit3 foo foo3 &&
>
>  	git checkout --orphan master &&
> +	git rm --cached foo &&
> +	rm foo &&
>  	sed -e "s/^|//" >file <<-\EOF &&
>  	|line 1
>  	|        line 2
> @@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
>  	test_cmp expect file
>  '
>
> +test_expect_success '--committer-date-is-author-date works with apply backend' '
> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +	git rebase --apply --committer-date-is-author-date HEAD^ &&
> +	git log -1 --pretty=%ai >authortime &&
> +	git log -1 --pretty=%ci >committertime &&
> +	test_cmp authortime committertime

This seems to be a repeated pattern. To dry it up, it would make sense to
do this:

	test_ctime_is_atime () {
		git log -1 --pretty=%ai >authortime &&
		git log -1 --pretty=%ci >committertime &&
		test_cmp authortime committertime
	}

Ciao,
Dscho

> +'
> +
> +test_expect_success '--committer-date-is-author-date works with merge backend' '
> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +	git rebase -m --committer-date-is-author-date HEAD^ &&
> +	git log -1 --pretty=%ai >authortime &&
> +	git log -1 --pretty=%ci >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
> +	git checkout side &&
> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +	git rebase -r --root --committer-date-is-author-date &&
> +	git log --pretty=%ai >authortime &&
> +	git log --pretty=%ci >committertime &&
> +	test_cmp authortime committertime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when forking merge' '
> +	git checkout side &&
> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
> +	git log --pretty=%ai >authortime &&
> +	git log --pretty=%ci >committertime &&
> +	test_cmp authortime committertime
> +
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
> +	git checkout commit2 &&
> +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
> +	git log -1 --format=%at HEAD >expect &&
> +	test_must_fail git rebase -m --committer-date-is-author-date \
> +		--onto HEAD^^ HEAD^ &&
> +	echo resolved > foo &&
> +	git add foo &&
> +	git rebase --continue &&
> +	git log -1 --format=%ct HEAD >actual &&
> +	test_cmp expect actual
> +'
> +
>  # This must be the last test in this file
>  test_expect_success '$EDITOR and friends are unchanged' '
>  	test_editor_unchanged
> --
> 2.26.2
>
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 6/5] fixup! rebase: add --reset-author-date
  2020-05-28 13:17       ` Đoàn Trần Công Danh
@ 2020-05-29  2:59         ` Johannes Schindelin
  2020-06-01 10:36           ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Johannes Schindelin @ 2020-05-29  2:59 UTC (permalink / raw)
  To: Đoàn Trần Công Danh
  Cc: Phillip Wood, Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Alban Gruin, Git Mailing List

[-- Attachment #1: Type: text/plain, Size: 2450 bytes --]

Hi,

On Thu, 28 May 2020, Đoàn Trần Công Danh wrote:

> On 2020-05-27 18:57:48+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> > From: Phillip Wood <phillip.wood@dunelm.org.uk>
> >
> > Sorry I somehow forgot to commit this before sending the v4 patches,
> > it fixes up the final patch
> >
> > Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> > ---
> >  t/t3436-rebase-more-options.sh | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> > index 5ee193f333..ecfd68397f 100755
> > --- a/t/t3436-rebase-more-options.sh
> > +++ b/t/t3436-rebase-more-options.sh
> > @@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
> >  	git rebase --apply --ignore-date HEAD^ &&
> >  	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
> >  	git rebase -m --ignore-date HEAD^ &&
> > -	git log -2 --pretty="format:%ai" >authortime &&
> > +	git log -2 --pretty=%ai >authortime &&
> >  	grep "+0000" authortime >output &&
> >  	test_line_count = 2 output
> >  '
>
> This version addressed all of my concerns, LGTM.
>
> Only the last
>
> 	test_line_count = 2 output
>
> puzzled me at first.
> Since it's the only usage of test_line_count in this version
> Turn out, it's equivalence with:
> -----------8<-----------
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index ecfd68397f..abe9af4d8c 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -197,8 +197,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
>  	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
>  	git rebase -m --ignore-date HEAD^ &&
>  	git log -2 --pretty=%ai >authortime &&
> -	grep "+0000" authortime >output &&
> -	test_line_count = 2 output
> +	! grep -v "+0000" authortime
>  '
>
>  # This must be the last test in this file
> ------>8------

Good suggestion!

I've read through all 5 patches, and rather than repeating much of what I
said about 1/5 and 2/5 in 4/5, I'll just say it here that it applies
there, too: less repetitions in the test script, and I'd prefer the layer
where the `apply` vs `merge` options are set to be `cmd__rebase()` rather
than `run_am()` (and `get_replay_opts()`).

All in all, it was a pleasant read.

Thanks,
Dscho

^ permalink raw reply	[flat|nested] 130+ messages in thread

* RE: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag
  2020-05-29  2:38     ` Johannes Schindelin
@ 2020-06-01  9:23       ` Kerry, Richard
  2020-06-01 10:26       ` Phillip Wood
  1 sibling, 0 replies; 130+ messages in thread
From: Kerry, Richard @ 2020-06-01  9:23 UTC (permalink / raw)
  To: Git Mailing List


As a non-native speaker, I am thrown off when reading "available to"
instead of the grammatically correct (I believe) "available in". Likewise, "on going" instead of "ongoing" just disrupts my workflow.

Maybe these can be fixed?

[RK] There is a distinct difference between "available to" and "available in".
[RK] "service A is available to entity B" does not mean the same as "service A is available in entity B".  The former indicates that service A is implemented within entity B, the latter indicates merely that entity B uses service A.
[RK] As a real world example consider "The internet banking service of Bank X is available to me", which makes complete sense.  But "The internet banking service of Bank X is available in me" would be nonsense.  I don't know what the OP intended but the difference between these is not purely grammatical, there is a difference in meaning which I must leave the OP to clarify.

[RK] As for the other issue, I too would suggest "ongoing".

[RK] Regards,
[RK] Richard.


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag
  2020-05-29  2:38     ` Johannes Schindelin
  2020-06-01  9:23       ` Kerry, Richard
@ 2020-06-01 10:26       ` Phillip Wood
  2020-06-01 21:03         ` Johannes Schindelin
  1 sibling, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-06-01 10:26 UTC (permalink / raw)
  To: Johannes Schindelin, Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi dscho

Thanks for taking a look at this

On 29/05/2020 03:38, Johannes Schindelin wrote:
> Hi Phillip,
> 
> sorry to be _so_ late in the game. (And sorry for sending this to you
> twice, I managed to skip all the Cc:s due to the Reply-To: header the
> first time round.)
> 
> On Wed, 27 May 2020, Phillip Wood wrote:
> 
>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>>
>> Rebase is implemented with two different backends - 'apply' and 'merge'
>> each of which support a different set of options. In particuar the apply
>> backend supports a number of options implemented by 'git am' that are
>> not available to the merge backend. As part of an on going effort to
> 
> As a non-native speaker, I am thrown off when reading "available to"
> instead of the grammatically correct (I believe) "available in". Likewise,
> "on going" instead of "ongoing" just disrupts my workflow.
> 
> Maybe these can be fixed?

Sure

>> diff --git a/builtin/rebase.c b/builtin/rebase.c
>> index 27a07d4e78..5d8e117276 100644
>> --- a/builtin/rebase.c
>> +++ b/builtin/rebase.c
>> @@ -86,6 +86,7 @@ struct rebase_options {
>>  	int signoff;
>>  	int allow_rerere_autoupdate;
>>  	int autosquash;
>> +	int ignore_whitespace;
>>  	char *gpg_sign_opt;
>>  	int autostash;
>>  	char *cmd;
>> @@ -108,6 +109,7 @@ struct rebase_options {
>>
>>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>  {
>> +	struct strbuf strategy_buf = STRBUF_INIT;
>>  	struct replay_opts replay = REPLAY_OPTS_INIT;
>>
>>  	replay.action = REPLAY_INTERACTIVE_REBASE;
>> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>>  	replay.strategy = opts->strategy;
>> +
>>  	if (opts->strategy_opts)
>> -		parse_strategy_opts(&replay, opts->strategy_opts);
>> +		strbuf_addstr(&strategy_buf, opts->strategy_opts);
>> +	if (opts->ignore_whitespace)
>> +		strbuf_addstr(&strategy_buf, " --ignore-space-change");
>> +	if (strategy_buf.len)
>> +		parse_strategy_opts(&replay, strategy_buf.buf);
> 
> Quite honestly, this is very, very ugly.
> 
> I would have expected this at a way earlier layer, namely in
> `cmd__rebase()`. Something along these lines:

Yes your version is definitely better, I'll update with that (I had left
this patch mostly alone as unlike the later ones the original actually
worked)

> 
> -- snip --
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 37ba76ac3d26..748e08aee2f2 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -1289,6 +1289,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  	struct strbuf revisions = STRBUF_INIT;
>  	struct strbuf buf = STRBUF_INIT;
>  	struct object_id merge_base;
> +	int ignore_whitespace = 0;
>  	enum action action = ACTION_NONE;
>  	const char *gpg_sign = NULL;
>  	struct string_list exec = STRING_LIST_INIT_NODUP;
> @@ -1318,9 +1319,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>  		OPT_BOOL(0, "signoff", &options.signoff,
>  			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -				  NULL, N_("passed to 'git am'"),
> -				  PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
> +			 N_("passed to 'git am'")),
>  		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>  				  &options.git_am_opts, NULL,
>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> @@ -1682,6 +1682,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		imply_merge(&options, "--rebase-merges");
>  	}
> 
> +	if (ignore_whitespace) {
> +		if (options.type == REBASE_APPLY)
> +			argv_array_push(&options.git_am_opts,
> +					"--ignore-whitespace");
> +		else
> +			string_list_append(&stragey_options,
> +					   "--ignore-space-change");
> +	}
> +
>  	if (strategy_options.nr) {
>  		int i;
> 
> -- snap --
> 
> 
>>
>>  	if (opts->squash_onto) {
>>  		oidcpy(&replay.squash_onto, opts->squash_onto);
>>  		replay.have_squash_onto = 1;
>>  	}
>>
>> +	strbuf_release(&strategy_buf);
>>  	return replay;
>>  }
>>
>> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
>>  	argc = parse_options(argc, argv, prefix, options,
>>  			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
>>
>> +	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
> 
> I am not sure what this is about: `opts.strategy_opts` is of type `char
> *`, i.e. it is supposed to be already allocated.
> 
> Not that `cmd_rebase__interactive()` matters _all_ that much anymore, of
> course: it is only used by the --preserve-merges backend, which will
> hopefully be retired soon.
> 
>> +
>>  	if (!is_null_oid(&squash_onto))
>>  		opts.squash_onto = &squash_onto;
>>
>> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)
>>  	am.git_cmd = 1;
>>  	argv_array_push(&am.args, "am");
>>
>> +	if (opts->ignore_whitespace)
>> +		argv_array_push(&am.args, "--ignore-whitespace");
>>  	if (opts->action && !strcmp("continue", opts->action)) {
>>  		argv_array_push(&am.args, "--resolved");
>>  		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
>> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>  			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>>  		OPT_BOOL(0, "signoff", &options.signoff,
>>  			 N_("add a Signed-off-by: line to each commit")),
>> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
>> -				  NULL, N_("passed to 'git am'"),
>> -				  PARSE_OPT_NOARG),
>>  		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>>  				  &options.git_am_opts, NULL,
>>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>>  		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>>  				  N_("passed to 'git apply'"), 0),
>> +		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
>> +			 N_("ignore changes in whitespace")),
>>  		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>>  				  N_("action"), N_("passed to 'git apply'"), 0),
>>  		OPT_BIT('f', "force-rebase", &options.flags,
>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>> index 50e7960702..55ca46786d 100755
>> --- a/t/t3422-rebase-incompatible-options.sh
>> +++ b/t/t3422-rebase-incompatible-options.sh
>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>  }
>>
>>  test_rebase_am_only --whitespace=fix
>> -test_rebase_am_only --ignore-whitespace
>>  test_rebase_am_only --committer-date-is-author-date
>>  test_rebase_am_only -C4
>>
>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>> new file mode 100755
>> index 0000000000..fb5e747e86
>> --- /dev/null
>> +++ b/t/t3436-rebase-more-options.sh
>> @@ -0,0 +1,86 @@
>> +#!/bin/sh
>> +#
>> +# Copyright (c) 2019 Rohit Ashiwal
>> +#
>> +
>> +test_description='tests to ensure compatibility between am and interactive backends'
>> +
>> +. ./test-lib.sh
>> +
>> +. "$TEST_DIRECTORY"/lib-rebase.sh
>> +
>> +# This is a special case in which both am and interactive backends
>> +# provide the same output. It was done intentionally because
>> +# both the backends fall short of optimal behaviour.
>> +test_expect_success 'setup' '
>> +	git checkout -b topic &&
>> +	q_to_tab >file <<-\EOF &&
>> +	line 1
>> +	Qline 2
>> +	line 3
>> +	EOF
>> +	git add file &&
>> +	git commit -m "add file" &&
>> +	cat >file <<-\EOF &&
>> +	line 1
>> +	new line 2
>> +	line 3
>> +	EOF
>> +	git commit -am "update file" &&
>> +	git tag side &&
>> +
>> +	git checkout --orphan master &&
>> +	sed -e "s/^|//" >file <<-\EOF &&
>> +	|line 1
>> +	|        line 2
>> +	|line 3
>> +	EOF
>> +	git add file &&
>> +	git commit -m "add file" &&
>> +	git tag main
>> +'
> 
> The file contents are repeated in an awfully repetitive manner. That not
> only makes things a bit hard to read, it also makes it all too easy to
> slip in bugs by mistake. How about something like this instead?
> 
> 	test_commit file &&
> 
> 	test_write_lines line1 Qline2 line3 >templ &&
> 
> 	q_to_tab <templ >file.t &&
> 	git commit -m tab file.t &&
> 
> 	sed "s/Q/new /" <templ >file.t &&
> 	git commit -m new file.t &&
> 	git tag side &&
> 
> 	git checkout file -- &&
> 	sed "s/Q/        /" <templ >file.t &&
> 	git commit -m spaces file.t

I'm not totally convinced by this, I'd prefer to be able to read the
contents rather than having to work out what sed is doing. What about

test_write_lines "line 1" "	line 2" "line 3" >file &&
add and commit
test_write_lines "line 1" "new line 2" "line 3" >file &&
commit and tag
test_write_lines "line 1" "  line 2" "line 3" >file &&
commit and tag

It does not get rid of the repetition but it does dispense with having
the work out what sed and q_to_tab are doing

> ... and then...
> 
>> +
>> +test_expect_success '--ignore-whitespace works with apply backend' '
>> +	cat >expect <<-\EOF &&
>> +	line 1
>> +	new line 2
>> +	line 3
>> +	EOF
> 
> 	sed "s/Q/new /" <templ >expect
> 
>> +	test_must_fail git rebase --apply main side &&
>> +	git rebase --abort &&
>> +	git rebase --apply --ignore-whitespace main side &&
>> +	test_cmp expect file
> 
> Personally, I prefer to read the contents of `expect` directly before the
> `test_cmp expect file.t`

I can move it but if we use sed you cannot see the contents

>> +'
>> +
>> +test_expect_success '--ignore-whitespace works with merge backend' '
>> +	cat >expect <<-\EOF &&
>> +	line 1
>> +	new line 2
>> +	line 3
>> +	EOF
> 
> Isn't this totally identical to the `expect` constructed earlier? And in
> any case, isn't this identical to `git show main:file.t`, which is what we
> _actually_ expect: for the file contents to be identical to the tagged
> `main`? I.e.

Well spotted I'll update (I think it's actually the same as side)

> 	git diff --exit-code main
> 
>> +	test_must_fail git rebase --merge main side &&
>> +	git rebase --abort &&
>> +	git rebase --merge --ignore-whitespace main side &&
>> +	test_cmp expect file
>> +'
>> +
>> +test_expect_success '--ignore-whitespace is remembered when continuing' '
>> +	cat >expect <<-\EOF &&
>> +	line 1
>> +	new line 2
>> +	line 3
>> +	EOF
>> +	(
>> +		set_fake_editor &&
>> +		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
>> +	) &&
>> +	git rebase --continue &&
>> +	test_cmp expect file
> 
> It is a bit funny to see these two invocations _specifically_ pulled out
> from the subshell, that's not how we do things in other test scripts:
> instead, we run all the Git commands _inside_ the subshell, and all the
> verifications after the subshell.

The idea was to only set the variable where it is used.

Best Wishes

Phillip

> I believe that with my suggestions, this test script will be a ton easier
> to read and to maintain. At least it will be a lot DRYer.
> 
> Ciao,
> Dscho
> 
>> +'
>> +
>> +# This must be the last test in this file
>> +test_expect_success '$EDITOR and friends are unchanged' '
>> +	test_editor_unchanged
>> +'
>> +
>> +test_done
>> --
>> 2.26.2
>>
>>


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date
  2020-05-29  2:52     ` Johannes Schindelin
@ 2020-06-01 10:33       ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-01 10:33 UTC (permalink / raw)
  To: Johannes Schindelin, Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi dscho

On 29/05/2020 03:52, Johannes Schindelin wrote:
> Hi Phillip,
> 
> On Wed, 27 May 2020, Phillip Wood wrote:
> 
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> As part of the on-going effort to retire the apply rebase backend teach
>> the merge backend how to handle --committer-date-is-author-date.
> 
> I forgot to mention this in my reply to the first patch in this series: it
> strikes me as a mis-characterization that the `apply` backend is about to
> be retired. What _is_ true is that the `merge` backend is the default
> backend, and what is even more true is that it is cumbersome if certain
> `rebase` options cannot be combined because they are only implemented by
> one of both rebase backends.

I'm not trying to imply that the apply backend is about to be retired
but it is the long term plan to get rid of it isn't it?

> 
>>
>> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>  Documentation/git-rebase.txt           | 10 +++--
>>  builtin/rebase.c                       | 16 ++++---
>>  sequencer.c                            | 59 +++++++++++++++++++++++++-
>>  sequencer.h                            |  1 +
>>  t/t3422-rebase-incompatible-options.sh |  1 -
>>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++
>>  6 files changed, 133 insertions(+), 10 deletions(-)
>>
>> diff --git a/builtin/rebase.c b/builtin/rebase.c
>> index 5d8e117276..357cd6acf3 100644
>> --- a/builtin/rebase.c
>> +++ b/builtin/rebase.c
>> @@ -89,6 +89,7 @@ struct rebase_options {
>>  	int ignore_whitespace;
>>  	char *gpg_sign_opt;
>>  	int autostash;
>> +	int committer_date_is_author_date;
>>  	char *cmd;
>>  	int allow_empty_message;
>>  	int rebase_merges, rebase_cousins;
>> @@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>  	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
>>  	replay.verbose = opts->flags & REBASE_VERBOSE;
>>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>> +	replay.committer_date_is_author_date =
>> +					opts->committer_date_is_author_date;
>>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>>  	replay.strategy = opts->strategy;
>>
>> @@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)
>>
>>  	if (opts->ignore_whitespace)
>>  		argv_array_push(&am.args, "--ignore-whitespace");
>> +	if (opts->committer_date_is_author_date)
>> +		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
> 
> As before, I would rather see this in `cmd__rebase()` rahn in `run_am()`.

Right I'll take a look at that

>>  	if (opts->action && !strcmp("continue", opts->action)) {
>>  		argv_array_push(&am.args, "--resolved");
>>  		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
>> @@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>  			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>>  		OPT_BOOL(0, "signoff", &options.signoff,
>>  			 N_("add a Signed-off-by: line to each commit")),
>> -		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>> -				  &options.git_am_opts, NULL,
>> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>> +		OPT_BOOL(0, "committer-date-is-author-date",
>> +			 &options.committer_date_is_author_date,
>> +			 N_("make committer date match author date")),
>>  		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>> @@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>  	    options.autosquash) {
>>  		allow_preemptive_ff = 0;
>>  	}
>> +	if (options.committer_date_is_author_date)
>> +		options.flags |= REBASE_FORCE;
>>
>>  	for (i = 0; i < options.git_am_opts.argc; i++) {
>>  		const char *option = options.git_am_opts.argv[i], *p;
>> -		if (!strcmp(option, "--committer-date-is-author-date") ||
>> -		    !strcmp(option, "--ignore-date") ||
>> +		if (!strcmp(option, "--ignore-date") ||
>>  		    !strcmp(option, "--whitespace=fix") ||
>>  		    !strcmp(option, "--whitespace=strip"))
>>  			allow_preemptive_ff = 0;
>> diff --git a/sequencer.c b/sequencer.c
>> index 6fd2674632..8826c6325b 100644
>> --- a/sequencer.c
>> +++ b/sequencer.c
>> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>>   * command-line.
>>   */
>>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
>> @@ -872,6 +873,22 @@ static char *get_author(const char *message)
>>  	return NULL;
>>  }
>>
>> +static const char *author_date_from_env_array(const struct argv_array *env)
>> +{
>> +	int i;
>> +	const char *date;
>> +
>> +	for (i = 0; i < env->argc; i++)
>> +		if (skip_prefix(env->argv[i],
>> +				"GIT_AUTHOR_DATE=", &date))
>> +			return date;
>> +	/*
>> +	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
>> +	 * reading the script
>> +	 */
>> +	BUG("GIT_AUTHOR_DATE missing from author script");
>> +}
>> +
>>  static const char staged_changes_advice[] =
>>  N_("you have staged changes in your working tree\n"
>>  "If these changes are meant to be squashed into the previous commit, run:\n"
>> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
>>  			     gpg_opt, gpg_opt);
>>  	}
>>
>> +	if (opts->committer_date_is_author_date)
>> +		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>> +				 author_date_from_env_array(&cmd.env_array));
>> +
>>  	argv_array_push(&cmd.args, "commit");
>>
>>  	if (!(flags & VERIFY_MSG))
>> @@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,
>>  		commit_list_insert(current_head, &parents);
>>  	}
>>
>> +	if (opts->committer_date_is_author_date) {
>> +		int len = strlen(author);
> 
> Given that `len` is used only once, is this local variable really
> necessary? You could just as well pass `(int)strlen(author)` in the
> `split_ident_line()` call below.

I wonder if it makes the `split_ident_line()` line too long, I'll take a
look.

>> +		struct ident_split ident;
>> +		struct strbuf date = STRBUF_INIT;
>> +
>> +		if (split_ident_line(&ident, author, len) < 0) {
>> +			res = error(_("malformed ident line '%s'"), author);
>> +			goto out;
>> +		}
>> +		if (!ident.date_begin) {
>> +			res = error(_("corrupted author without date information"));
>> +			goto out;
>> +		}
>> +
>> +		strbuf_addf(&date, "@%.*s %.*s",
>> +			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
>> +			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
>> +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
>> +		strbuf_release(&date);
> 
> It might be easier to read if it was written this way:
> 
> 		if (split_ident_line(...) < 0)
> 			res = ...
> 		else if (!ident.date_begin)
> 			res = ...
> 		else {
> 			strbuf_addf(...)
> 			res = ...
> 			strbuf_release(&date);
> 		}
> 
> 		if (res)
> 			goto out;

I'm not sure. The current style of "if there's an error goto out" makes
the control flow clear without having to reason ones way through a
series of else ifs

>> +
>> +		if (res)
>> +			goto out;
>> +	}
>> +
>>  	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>>  		res = error(_("git write-tree failed to write a tree"));
>>  		goto out;
>> @@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)
>>  			opts->signoff = 1;
>>  		}
>>
>> +		if (file_exists(rebase_path_cdate_is_adate())) {
>> +			opts->allow_ff = 0;
>> +			opts->committer_date_is_author_date = 1;
>> +		}
>> +
>>  		if (file_exists(rebase_path_reschedule_failed_exec()))
>>  			opts->reschedule_failed_exec = 1;
>>
>> @@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>>  		write_file(rebase_path_drop_redundant_commits(), "%s", "");
>>  	if (opts->keep_redundant_commits)
>>  		write_file(rebase_path_keep_redundant_commits(), "%s", "");
>> +	if (opts->committer_date_is_author_date)
>> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>>  	if (opts->reschedule_failed_exec)
>>  		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>>
>> @@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,
>>  			goto leave_merge;
>>  		}
>>
>> +		if (opts->committer_date_is_author_date)
>> +			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>> +					 author_date_from_env_array(&cmd.env_array));
>> +
>>  		cmd.git_cmd = 1;
>>  		argv_array_push(&cmd.args, "merge");
>>  		argv_array_push(&cmd.args, "-s");
>> @@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,
>>  	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>>  	if (opts->allow_ff)
>>  		assert(!(opts->signoff || opts->no_commit ||
>> -				opts->record_origin || opts->edit));
>> +				opts->record_origin || opts->edit ||
>> +				opts->committer_date_is_author_date));
>>  	if (read_and_refresh_cache(r, opts))
>>  		return -1;
>>
>> diff --git a/sequencer.h b/sequencer.h
>> index 0bee85093e..4ab94119ae 100644
>> --- a/sequencer.h
>> +++ b/sequencer.h
>> @@ -45,6 +45,7 @@ struct replay_opts {
>>  	int verbose;
>>  	int quiet;
>>  	int reschedule_failed_exec;
>> +	int committer_date_is_author_date;
>>
>>  	int mainline;
>>
>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>> index 55ca46786d..c8234062c6 100755
>> --- a/t/t3422-rebase-incompatible-options.sh
>> +++ b/t/t3422-rebase-incompatible-options.sh
>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>  }
>>
>>  test_rebase_am_only --whitespace=fix
>> -test_rebase_am_only --committer-date-is-author-date
>>  test_rebase_am_only -C4
>>
>>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>> index fb5e747e86..7e68fb9753 100755
>> --- a/t/t3436-rebase-more-options.sh
>> +++ b/t/t3436-rebase-more-options.sh
>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>>
>>  . "$TEST_DIRECTORY"/lib-rebase.sh
>>
>> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>> +export GIT_AUTHOR_DATE
>> +
>>  # This is a special case in which both am and interactive backends
>>  # provide the same output. It was done intentionally because
>>  # both the backends fall short of optimal behaviour.
>> @@ -28,8 +31,13 @@ test_expect_success 'setup' '
>>  	EOF
>>  	git commit -am "update file" &&
>>  	git tag side &&
>> +	test_commit commit1 foo foo1 &&
>> +	test_commit commit2 foo foo2 &&
>> +	test_commit commit3 foo foo3 &&
>>
>>  	git checkout --orphan master &&
>> +	git rm --cached foo &&
>> +	rm foo &&
>>  	sed -e "s/^|//" >file <<-\EOF &&
>>  	|line 1
>>  	|        line 2
>> @@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
>>  	test_cmp expect file
>>  '
>>
>> +test_expect_success '--committer-date-is-author-date works with apply backend' '
>> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>> +	git rebase --apply --committer-date-is-author-date HEAD^ &&
>> +	git log -1 --pretty=%ai >authortime &&
>> +	git log -1 --pretty=%ci >committertime &&
>> +	test_cmp authortime committertime
> 
> This seems to be a repeated pattern. To dry it up, it would make sense to
> do this:
> 
> 	test_ctime_is_atime () {
> 		git log -1 --pretty=%ai >authortime &&
> 		git log -1 --pretty=%ci >committertime &&
> 		test_cmp authortime committertime
> 	}

Good suggestion (though we need to parametrize the -1 so we can use it
with the rebase --root cases)

Thanks

Phillip

> 
> Ciao,
> Dscho
> 
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with merge backend' '
>> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>> +	git rebase -m --committer-date-is-author-date HEAD^ &&
>> +	git log -1 --pretty=%ai >authortime &&
>> +	git log -1 --pretty=%ci >committertime &&
>> +	test_cmp authortime committertime
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
>> +	git checkout side &&
>> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>> +	git rebase -r --root --committer-date-is-author-date &&
>> +	git log --pretty=%ai >authortime &&
>> +	git log --pretty=%ci >committertime &&
>> +	test_cmp authortime committertime
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works when forking merge' '
>> +	git checkout side &&
>> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>> +	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
>> +	git log --pretty=%ai >authortime &&
>> +	git log --pretty=%ci >committertime &&
>> +	test_cmp authortime committertime
>> +
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
>> +	git checkout commit2 &&
>> +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
>> +	git log -1 --format=%at HEAD >expect &&
>> +	test_must_fail git rebase -m --committer-date-is-author-date \
>> +		--onto HEAD^^ HEAD^ &&
>> +	echo resolved > foo &&
>> +	git add foo &&
>> +	git rebase --continue &&
>> +	git log -1 --format=%ct HEAD >actual &&
>> +	test_cmp expect actual
>> +'
>> +
>>  # This must be the last test in this file
>>  test_expect_success '$EDITOR and friends are unchanged' '
>>  	test_editor_unchanged
>> --
>> 2.26.2
>>
>>


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 6/5] fixup! rebase: add --reset-author-date
  2020-05-29  2:59         ` Johannes Schindelin
@ 2020-06-01 10:36           ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-01 10:36 UTC (permalink / raw)
  To: Johannes Schindelin, Đoàn Trần Công Danh
  Cc: Phillip Wood, Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Alban Gruin, Git Mailing List

Hi dscho and Danh

On 29/05/2020 03:59, Johannes Schindelin wrote:
> Hi,
> 
> On Thu, 28 May 2020, Đoàn Trần Công Danh wrote:
> 
>> On 2020-05-27 18:57:48+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>>
>>> Sorry I somehow forgot to commit this before sending the v4 patches,
>>> it fixes up the final patch
>>>
>>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>>> ---
>>>  t/t3436-rebase-more-options.sh | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>>> index 5ee193f333..ecfd68397f 100755
>>> --- a/t/t3436-rebase-more-options.sh
>>> +++ b/t/t3436-rebase-more-options.sh
>>> @@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
>>>  	git rebase --apply --ignore-date HEAD^ &&
>>>  	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
>>>  	git rebase -m --ignore-date HEAD^ &&
>>> -	git log -2 --pretty="format:%ai" >authortime &&
>>> +	git log -2 --pretty=%ai >authortime &&
>>>  	grep "+0000" authortime >output &&
>>>  	test_line_count = 2 output
>>>  '
>>
>> This version addressed all of my concerns, LGTM.
>>
>> Only the last
>>
>> 	test_line_count = 2 output
>>
>> puzzled me at first.
>> Since it's the only usage of test_line_count in this version
>> Turn out, it's equivalence with:
>> -----------8<-----------
>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>> index ecfd68397f..abe9af4d8c 100755
>> --- a/t/t3436-rebase-more-options.sh
>> +++ b/t/t3436-rebase-more-options.sh
>> @@ -197,8 +197,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
>>  	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
>>  	git rebase -m --ignore-date HEAD^ &&
>>  	git log -2 --pretty=%ai >authortime &&
>> -	grep "+0000" authortime >output &&
>> -	test_line_count = 2 output
>> +	! grep -v "+0000" authortime
>>  '
>>
>>  # This must be the last test in this file
>> ------>8------
> 
> Good suggestion!

Yes thanks Danh I'll update with that

> I've read through all 5 patches, and rather than repeating much of what I
> said about 1/5 and 2/5 in 4/5, I'll just say it here that it applies
> there, too: less repetitions in the test script,

I'll look at adding a helper for to do the checks

> and I'd prefer the layer
> where the `apply` vs `merge` options are set to be `cmd__rebase()` rather
> than `run_am()` (and `get_replay_opts()`).

Yeah that would make it nicer.

> All in all, it was a pleasant read.

Thanks for your comments on this series

Phillip

> Thanks,
> Dscho
> 


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-01 10:26       ` Phillip Wood
@ 2020-06-01 21:03         ` Johannes Schindelin
  0 siblings, 0 replies; 130+ messages in thread
From: Johannes Schindelin @ 2020-06-01 21:03 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Phillip Wood, Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi Phillip,

On Mon, 1 Jun 2020, Phillip Wood wrote:

> On 29/05/2020 03:38, Johannes Schindelin wrote:
> >
> > On Wed, 27 May 2020, Phillip Wood wrote:
> >
> >> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> >>
> >> [...]
> >> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> >> new file mode 100755
> >> index 0000000000..fb5e747e86
> >> --- /dev/null
> >> +++ b/t/t3436-rebase-more-options.sh
> >> @@ -0,0 +1,86 @@
> >> +#!/bin/sh
> >> +#
> >> +# Copyright (c) 2019 Rohit Ashiwal
> >> +#
> >> +
> >> +test_description='tests to ensure compatibility between am and interactive backends'
> >> +
> >> +. ./test-lib.sh
> >> +
> >> +. "$TEST_DIRECTORY"/lib-rebase.sh
> >> +
> >> +# This is a special case in which both am and interactive backends
> >> +# provide the same output. It was done intentionally because
> >> +# both the backends fall short of optimal behaviour.
> >> +test_expect_success 'setup' '
> >> +	git checkout -b topic &&
> >> +	q_to_tab >file <<-\EOF &&
> >> +	line 1
> >> +	Qline 2
> >> +	line 3
> >> +	EOF
> >> +	git add file &&
> >> +	git commit -m "add file" &&
> >> +	cat >file <<-\EOF &&
> >> +	line 1
> >> +	new line 2
> >> +	line 3
> >> +	EOF
> >> +	git commit -am "update file" &&
> >> +	git tag side &&
> >> +
> >> +	git checkout --orphan master &&
> >> +	sed -e "s/^|//" >file <<-\EOF &&
> >> +	|line 1
> >> +	|        line 2
> >> +	|line 3
> >> +	EOF
> >> +	git add file &&
> >> +	git commit -m "add file" &&
> >> +	git tag main
> >> +'
> >
> > The file contents are repeated in an awfully repetitive manner. That not
> > only makes things a bit hard to read, it also makes it all too easy to
> > slip in bugs by mistake. How about something like this instead?
> >
> > 	test_commit file &&
> >
> > 	test_write_lines line1 Qline2 line3 >templ &&
> >
> > 	q_to_tab <templ >file.t &&
> > 	git commit -m tab file.t &&
> >
> > 	sed "s/Q/new /" <templ >file.t &&
> > 	git commit -m new file.t &&
> > 	git tag side &&
> >
> > 	git checkout file -- &&
> > 	sed "s/Q/        /" <templ >file.t &&
> > 	git commit -m spaces file.t
>
> I'm not totally convinced by this, I'd prefer to be able to read the
> contents rather than having to work out what sed is doing. What about
>
> test_write_lines "line 1" "	line 2" "line 3" >file &&
> add and commit
> test_write_lines "line 1" "new line 2" "line 3" >file &&
> commit and tag
> test_write_lines "line 1" "  line 2" "line 3" >file &&
> commit and tag
>
> It does not get rid of the repetition but it does dispense with having
> the work out what sed and q_to_tab are doing

Sure. Your version is still tons easier to parse for a human being.

> > 	git diff --exit-code main
> >
> >> +	test_must_fail git rebase --merge main side &&
> >> +	git rebase --abort &&
> >> +	git rebase --merge --ignore-whitespace main side &&
> >> +	test_cmp expect file
> >> +'
> >> +
> >> +test_expect_success '--ignore-whitespace is remembered when continuing' '
> >> +	cat >expect <<-\EOF &&
> >> +	line 1
> >> +	new line 2
> >> +	line 3
> >> +	EOF
> >> +	(
> >> +		set_fake_editor &&
> >> +		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
> >> +	) &&
> >> +	git rebase --continue &&
> >> +	test_cmp expect file
> >
> > It is a bit funny to see these two invocations _specifically_ pulled out
> > from the subshell, that's not how we do things in other test scripts:
> > instead, we run all the Git commands _inside_ the subshell, and all the
> > verifications after the subshell.
>
> The idea was to only set the variable where it is used.

I understand that, but I think that it would be better to follow the
existing pattern rather than introducing an inconsistent second one.

Thanks,
Dscho

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v5 0/5] cleanup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (10 preceding siblings ...)
  2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
@ 2020-06-26  9:55 ` Phillip Wood
  2020-06-26  9:55   ` [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
                     ` (5 more replies)
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
                   ` (2 subsequent siblings)
  14 siblings, 6 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26  9:55 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

I've updated the commit messages, option handling and tests as
suggested by dscho. I've also changed the tests that used
'--strategy=resolve' to use a real external merge strategy so they
continue to test the same code path once Alban's patches to handle the
resolve strategy without forking are merged

Thanks for the review

Phillip

Phillip Wood (2):
  rebase -i: support --committer-date-is-author-date
  rebase -i: support --ignore-date

Rohit Ashiwal (3):
  rebase -i: add --ignore-whitespace flag
  sequencer: rename amend_author to author_to_free
  rebase: add --reset-author-date

 Documentation/git-rebase.txt           |  33 ++++-
 builtin/rebase.c                       |  44 ++++--
 sequencer.c                            | 112 ++++++++++++++-
 sequencer.h                            |   2 +
 t/t3422-rebase-incompatible-options.sh |   2 -
 t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++
 6 files changed, 350 insertions(+), 23 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

Range-diff against v4:
1:  df8c4ed2e9 ! 1:  43ee10d4d5 rebase -i: add --ignore-whitespace flag
    @@ Metadata
      ## Commit message ##
         rebase -i: add --ignore-whitespace flag
     
    -    Rebase is implemented with two different backends - 'apply' and 'merge'
    -    each of which support a different set of options. In particuar the apply
    -    backend supports a number of options implemented by 'git am' that are
    -    not available to the merge backend. As part of an on going effort to
    -    remove the apply backend this patch adds support for the
    +    Rebase is implemented with two different backends - 'apply' and
    +    'merge' each of which support a different set of options. In
    +    particular the apply backend supports a number of options implemented
    +    by 'git am' that are not implemented in the merge backend. This means
    +    that the available options are different depending on which backend is
    +    used which is confusing. This patch adds support for the
         --ignore-whitespace option to the merge backend. This option treats
         lines with only whitespace changes as unchanged and is implemented in
         the merge backend by translating it to -Xignore-space-change.
    @@ Documentation/git-rebase.txt: In addition, the following pairs of options are in
      
     
      ## builtin/rebase.c ##
    -@@ builtin/rebase.c: struct rebase_options {
    - 	int signoff;
    - 	int allow_rerere_autoupdate;
    - 	int autosquash;
    -+	int ignore_whitespace;
    - 	char *gpg_sign_opt;
    - 	int autostash;
    - 	char *cmd;
    -@@ builtin/rebase.c: struct rebase_options {
    - 
    - static struct replay_opts get_replay_opts(const struct rebase_options *opts)
    - {
    -+	struct strbuf strategy_buf = STRBUF_INIT;
    - 	struct replay_opts replay = REPLAY_OPTS_INIT;
    - 
    - 	replay.action = REPLAY_INTERACTIVE_REBASE;
     @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_options *opts)
      	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
      	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
      	replay.strategy = opts->strategy;
     +
      	if (opts->strategy_opts)
    --		parse_strategy_opts(&replay, opts->strategy_opts);
    -+		strbuf_addstr(&strategy_buf, opts->strategy_opts);
    -+	if (opts->ignore_whitespace)
    -+		strbuf_addstr(&strategy_buf, " --ignore-space-change");
    -+	if (strategy_buf.len)
    -+		parse_strategy_opts(&replay, strategy_buf.buf);
    - 
    - 	if (opts->squash_onto) {
    - 		oidcpy(&replay.squash_onto, opts->squash_onto);
    - 		replay.have_squash_onto = 1;
    - 	}
    - 
    -+	strbuf_release(&strategy_buf);
    - 	return replay;
    - }
    - 
    -@@ builtin/rebase.c: int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
    - 	argc = parse_options(argc, argv, prefix, options,
    - 			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
    - 
    -+	opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
    -+
    - 	if (!is_null_oid(&squash_onto))
    - 		opts.squash_onto = &squash_onto;
    - 
    -@@ builtin/rebase.c: static int run_am(struct rebase_options *opts)
    - 	am.git_cmd = 1;
    - 	argv_array_push(&am.args, "am");
    - 
    -+	if (opts->ignore_whitespace)
    -+		argv_array_push(&am.args, "--ignore-whitespace");
    - 	if (opts->action && !strcmp("continue", opts->action)) {
    - 		argv_array_push(&am.args, "--resolved");
    - 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
    + 		parse_strategy_opts(&replay, opts->strategy_opts);
    + 
    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
    + 	struct strbuf revisions = STRBUF_INIT;
    + 	struct strbuf buf = STRBUF_INIT;
    + 	struct object_id merge_base;
    ++	int ignore_whitespace = 0;
    + 	enum action action = ACTION_NONE;
    + 	const char *gpg_sign = NULL;
    + 	struct string_list exec = STRING_LIST_INIT_NODUP;
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
      			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
      		OPT_BOOL(0, "signoff", &options.signoff,
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
      		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
      				  N_("passed to 'git apply'"), 0),
    -+		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
    ++		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
     +			 N_("ignore changes in whitespace")),
      		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
      				  N_("action"), N_("passed to 'git apply'"), 0),
      		OPT_BIT('f', "force-rebase", &options.flags,
    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
    + 		imply_merge(&options, "--rebase-merges");
    + 	}
    + 
    ++	if (options.type == REBASE_APPLY) {
    ++		if (ignore_whitespace)
    ++			argv_array_push (&options.git_am_opts,
    ++					 "--ignore-whitespace");
    ++	} else if (ignore_whitespace) {
    ++			string_list_append (&strategy_options,
    ++					    "ignore-space-change");
    ++	}
    ++
    + 	if (strategy_options.nr) {
    + 		int i;
    + 
     
      ## t/t3422-rebase-incompatible-options.sh ##
     @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {
    @@ t/t3436-rebase-more-options.sh (new)
     +# both the backends fall short of optimal behaviour.
     +test_expect_success 'setup' '
     +	git checkout -b topic &&
    -+	q_to_tab >file <<-\EOF &&
    -+	line 1
    -+	Qline 2
    -+	line 3
    -+	EOF
    ++	test_write_lines "line 1" "	line 2" "line 3" >file &&
     +	git add file &&
     +	git commit -m "add file" &&
    -+	cat >file <<-\EOF &&
    -+	line 1
    -+	new line 2
    -+	line 3
    -+	EOF
    ++
    ++	test_write_lines "line 1" "new line 2" "line 3" >file &&
     +	git commit -am "update file" &&
     +	git tag side &&
     +
     +	git checkout --orphan master &&
    -+	sed -e "s/^|//" >file <<-\EOF &&
    -+	|line 1
    -+	|        line 2
    -+	|line 3
    -+	EOF
    -+	git add file &&
    -+	git commit -m "add file" &&
    ++	test_write_lines "line 1" "        line 2" "line 3" >file &&
    ++	git commit -am "add file" &&
     +	git tag main
     +'
     +
     +test_expect_success '--ignore-whitespace works with apply backend' '
    -+	cat >expect <<-\EOF &&
    -+	line 1
    -+	new line 2
    -+	line 3
    -+	EOF
     +	test_must_fail git rebase --apply main side &&
     +	git rebase --abort &&
     +	git rebase --apply --ignore-whitespace main side &&
    -+	test_cmp expect file
    ++	git diff --exit-code side
     +'
     +
     +test_expect_success '--ignore-whitespace works with merge backend' '
    -+	cat >expect <<-\EOF &&
    -+	line 1
    -+	new line 2
    -+	line 3
    -+	EOF
     +	test_must_fail git rebase --merge main side &&
     +	git rebase --abort &&
     +	git rebase --merge --ignore-whitespace main side &&
    -+	test_cmp expect file
    ++	git diff --exit-code side
     +'
     +
     +test_expect_success '--ignore-whitespace is remembered when continuing' '
    -+	cat >expect <<-\EOF &&
    -+	line 1
    -+	new line 2
    -+	line 3
    -+	EOF
     +	(
     +		set_fake_editor &&
    -+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace main side
    ++		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
    ++			main side &&
    ++		git rebase --continue
     +	) &&
    -+	git rebase --continue &&
    -+	test_cmp expect file
    ++	git diff --exit-code side
     +'
     +
     +# This must be the last test in this file
2:  ad21e5d8fb ! 2:  a2b57df19c rebase -i: support --committer-date-is-author-date
    @@ Metadata
      ## Commit message ##
         rebase -i: support --committer-date-is-author-date
     
    -    As part of the on-going effort to retire the apply rebase backend teach
    -    the merge backend how to handle --committer-date-is-author-date.
    +    Rebase is implemented with two different backends - 'apply' and
    +    'merge' each of which support a different set of options. In
    +    particular the apply backend supports a number of options implemented
    +    by 'git am' that are not implemented in the merge backend. This means
    +    that the available options are different depending on which backend is
    +    used which is confusing. This patch adds support for the
    +    --committer-date-is-author-date option to the merge backend. This
    +    option uses the author date of the commit that is being rewritten as
    +    the committer date when the new commit is created.
     
         Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
         Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
    @@ Documentation/git-rebase.txt: In addition, the following pairs of options are in
     
      ## builtin/rebase.c ##
     @@ builtin/rebase.c: struct rebase_options {
    - 	int ignore_whitespace;
    + 	int autosquash;
      	char *gpg_sign_opt;
      	int autostash;
     +	int committer_date_is_author_date;
    @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_
      	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
      	replay.strategy = opts->strategy;
      
    -@@ builtin/rebase.c: static int run_am(struct rebase_options *opts)
    - 
    - 	if (opts->ignore_whitespace)
    - 		argv_array_push(&am.args, "--ignore-whitespace");
    -+	if (opts->committer_date_is_author_date)
    -+		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
    - 	if (opts->action && !strcmp("continue", opts->action)) {
    - 		argv_array_push(&am.args, "--resolved");
    - 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
      			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
      		OPT_BOOL(0, "signoff", &options.signoff,
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      		    !strcmp(option, "--whitespace=fix") ||
      		    !strcmp(option, "--whitespace=strip"))
      			allow_preemptive_ff = 0;
    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
    + 		if (ignore_whitespace)
    + 			argv_array_push (&options.git_am_opts,
    + 					 "--ignore-whitespace");
    ++		if (options.committer_date_is_author_date)
    ++			argv_array_push(&options.git_am_opts,
    ++					"--committer-date-is-author-date");
    + 	} else if (ignore_whitespace) {
    + 			string_list_append (&strategy_options,
    + 					    "ignore-space-change");
     
      ## sequencer.c ##
     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
    @@ sequencer.c: static int try_to_commit(struct repository *r,
      	}
      
     +	if (opts->committer_date_is_author_date) {
    -+		int len = strlen(author);
     +		struct ident_split ident;
     +		struct strbuf date = STRBUF_INIT;
     +
    -+		if (split_ident_line(&ident, author, len) < 0) {
    ++		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
     +			res = error(_("malformed ident line '%s'"), author);
     +			goto out;
     +		}
    @@ sequencer.c: static int try_to_commit(struct repository *r,
     +		}
     +
     +		strbuf_addf(&date, "@%.*s %.*s",
    -+			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
    -+			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
    ++			    (int)(ident.date_end - ident.date_begin),
    ++			    ident.date_begin,
    ++			    (int)(ident.tz_end - ident.tz_begin),
    ++			    ident.tz_begin);
     +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
     +		strbuf_release(&date);
     +
    @@ t/t3436-rebase-more-options.sh: test_description='tests to ensure compatibility
      # provide the same output. It was done intentionally because
      # both the backends fall short of optimal behaviour.
     @@ t/t3436-rebase-more-options.sh: test_expect_success 'setup' '
    - 	EOF
    + 	test_write_lines "line 1" "new line 2" "line 3" >file &&
      	git commit -am "update file" &&
      	git tag side &&
     +	test_commit commit1 foo foo1 &&
     +	test_commit commit2 foo foo2 &&
     +	test_commit commit3 foo foo3 &&
      
      	git checkout --orphan master &&
    -+	git rm --cached foo &&
     +	rm foo &&
    - 	sed -e "s/^|//" >file <<-\EOF &&
    - 	|line 1
    - 	|        line 2
    + 	test_write_lines "line 1" "        line 2" "line 3" >file &&
    + 	git commit -am "add file" &&
    +-	git tag main
    ++	git tag main &&
    ++
    ++	mkdir test-bin &&
    ++	write_script test-bin/git-merge-test <<-\EOF
    ++	exec git-merge-recursive "$@"
    ++	EOF
    + '
    + 
    + test_expect_success '--ignore-whitespace works with apply backend' '
     @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-whitespace is remembered when continuing' '
    - 	test_cmp expect file
    + 	git diff --exit-code side
      '
      
    ++test_ctime_is_atime () {
    ++	git log $1 --format=%ai >authortime &&
    ++	git log $1 --format=%ci >committertime &&
    ++	test_cmp authortime committertime
    ++}
    ++
     +test_expect_success '--committer-date-is-author-date works with apply backend' '
     +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
     +	git rebase --apply --committer-date-is-author-date HEAD^ &&
    -+	git log -1 --pretty=%ai >authortime &&
    -+	git log -1 --pretty=%ci >committertime &&
    -+	test_cmp authortime committertime
    ++	test_ctime_is_atime -1
     +'
     +
     +test_expect_success '--committer-date-is-author-date works with merge backend' '
     +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
     +	git rebase -m --committer-date-is-author-date HEAD^ &&
    -+	git log -1 --pretty=%ai >authortime &&
    -+	git log -1 --pretty=%ci >committertime &&
    -+	test_cmp authortime committertime
    ++	test_ctime_is_atime -1
     +'
     +
     +test_expect_success '--committer-date-is-author-date works with rebase -r' '
     +	git checkout side &&
     +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
     +	git rebase -r --root --committer-date-is-author-date &&
    -+	git log --pretty=%ai >authortime &&
    -+	git log --pretty=%ci >committertime &&
    -+	test_cmp authortime committertime
    ++	test_ctime_is_atime
     +'
     +
     +test_expect_success '--committer-date-is-author-date works when forking merge' '
     +	git checkout side &&
     +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
    -+	git rebase -r --root --strategy=resolve --committer-date-is-author-date &&
    -+	git log --pretty=%ai >authortime &&
    -+	git log --pretty=%ci >committertime &&
    -+	test_cmp authortime committertime
    -+
    ++	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
    ++					--committer-date-is-author-date &&
    ++	test_ctime_is_atime
     +'
     +
     +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
     +	git checkout commit2 &&
     +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
    -+	git log -1 --format=%at HEAD >expect &&
     +	test_must_fail git rebase -m --committer-date-is-author-date \
     +		--onto HEAD^^ HEAD^ &&
     +	echo resolved > foo &&
     +	git add foo &&
     +	git rebase --continue &&
    -+	git log -1 --format=%ct HEAD >actual &&
    -+	test_cmp expect actual
    ++	test_ctime_is_atime -1
     +'
     +
      # This must be the last test in this file
3:  af92e29cf9 = 3:  363a0140ad sequencer: rename amend_author to author_to_free
4:  4399dc19b6 ! 4:  46d9e108be rebase -i: support --ignore-date
    @@ Metadata
      ## Commit message ##
         rebase -i: support --ignore-date
     
    -    As part of the on-going effort to retire the apply rebase backend
    -    teach the merge backend how to handle --ignore-date. We take care to
    -    handle the combination of --ignore-date and
    -    --committer-date-is-author-date in the same way as the apply backend.
    +    Rebase is implemented with two different backends - 'apply' and
    +    'merge' each of which support a different set of options. In
    +    particular the apply backend supports a number of options implemented
    +    by 'git am' that are not implemented in the merge backend. This means
    +    that the available options are different depending on which backend is
    +    used which is confusing. This patch adds support for the --ignore-date
    +    option to the merge backend. This option uses the current time as the
    +    author date rather than reusing the original author date when
    +    rewriting commits. We take care to handle the combination of
    +    --ignore-date and --committer-date-is-author-date in the same way as
    +    the apply backend.
     
         Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
         Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
    @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_
      	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
      	replay.strategy = opts->strategy;
      
    -@@ builtin/rebase.c: static int run_am(struct rebase_options *opts)
    - 		argv_array_push(&am.args, "--ignore-whitespace");
    - 	if (opts->committer_date_is_author_date)
    - 		argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
    -+	if (opts->ignore_date)
    -+		argv_array_push(&opts->git_am_opts, "--ignore-date");
    - 	if (opts->action && !strcmp("continue", opts->action)) {
    - 		argv_array_push(&am.args, "--resolved");
    - 		argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
      		OPT_BOOL(0, "committer-date-is-author-date",
      			 &options.committer_date_is_author_date,
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
     +			 "ignore author date and use current date"),
      		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
      				  N_("passed to 'git apply'"), 0),
    - 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
    + 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
      	    options.autosquash) {
      		allow_preemptive_ff = 0;
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      		    !strcmp(option, "--whitespace=strip"))
      			allow_preemptive_ff = 0;
      		else if (skip_prefix(option, "-C", &p)) {
    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
    + 		if (options.committer_date_is_author_date)
    + 			argv_array_push(&options.git_am_opts,
    + 					"--committer-date-is-author-date");
    ++		if (options.ignore_date)
    ++			argv_array_push(&options.git_am_opts, "--ignore-date");
    + 	} else if (ignore_whitespace) {
    + 			string_list_append (&strategy_options,
    + 					    "ignore-space-change");
     
      ## sequencer.c ##
     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
    @@ sequencer.c: static int run_git_commit(struct repository *r,
      	argv_array_push(&cmd.args, "commit");
      
     @@ sequencer.c: static int try_to_commit(struct repository *r,
    - 		strbuf_addf(&date, "@%.*s %.*s",
    - 			    (int)(ident.date_end - ident.date_begin), ident.date_begin,
    - 			    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
    + 			    ident.date_begin,
    + 			    (int)(ident.tz_end - ident.tz_begin),
    + 			    ident.tz_begin);
     -		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
     +		res = setenv("GIT_COMMITTER_DATE",
     +			     opts->ignore_date ? "" : date.buf, 1);
    @@ sequencer.h: struct replay_opts {
     
      ## t/t3436-rebase-more-options.sh ##
     @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-date works when committing confl
    - 	test_cmp expect actual
    + 	test_ctime_is_atime -1
      '
      
    -+# Checking for +0000 in author time is enough since default
    -+# timezone is UTC, but the timezone used while committing
    -+# sets to +0530.
    ++# Checking for +0000 in the author date is sufficient since the
    ++# default timezone is UTC but the timezone used while committing is
    ++# +0530. The inverted logic in the grep is necessary to check all the
    ++# author dates in the file.
    ++test_ctime_is_ignored () {
    ++	git log $1 --format=%ai >authortime &&
    ++	! grep -v +0000 authortime
    ++}
    ++
     +test_expect_success '--ignore-date works with apply backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --apply --ignore-date HEAD^ &&
    -+	git log -1 --pretty=%ai >authortime &&
    -+	grep "+0000" authortime
    ++	test_ctime_is_ignored -1
     +'
     +
     +test_expect_success '--ignore-date works with merge backend' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --ignore-date -m HEAD^ &&
    -+	git log -1 --pretty=%ai >authortime &&
    -+	grep "+0000" authortime
    ++	test_ctime_is_ignored -1
     +'
     +
     +test_expect_success '--ignore-date works after conflict resolution' '
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-
     +	echo resolved >foo &&
     +	git add foo &&
     +	git rebase --continue &&
    -+	git log -1 --pretty=%ai >authortime &&
    -+	grep +0000 authortime
    ++	test_ctime_is_ignored -1
     +'
     +
     +test_expect_success '--ignore-date works with rebase -r' '
     +	git checkout side &&
     +	git merge --no-ff commit3 &&
     +	git rebase -r --root --ignore-date &&
    -+	git log --pretty=%ai >authortime &&
    -+	! grep -v "+0000" authortime
    ++	test_ctime_is_ignored
     +'
     +
     +test_expect_success '--ignore-date with --committer-date-is-author-date works' '
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-
     +	git checkout --theirs foo &&
     +	git add foo &&
     +	git rebase --continue &&
    -+	git log -2 --pretty=%ai >authortime &&
    -+	git log -2 --pretty=%ci >committertime &&
    -+	test_cmp authortime committertime &&
    -+	! grep -v "+0000" authortime
    ++	test_ctime_is_atime -2 &&
    ++	test_ctime_is_ignored -2
     +'
     +
     +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
     +	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
    -+		git rebase -i --strategy=resolve --ignore-date \
    -+		--committer-date-is-author-date side side &&
    -+	git log -1 --pretty=%ai >authortime &&
    -+	git log -1 --pretty=%ci >committertime &&
    -+	test_cmp authortime committertime &&
    -+	grep "+0000" authortime
    ++		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
    ++				--ignore-date --committer-date-is-author-date \
    ++				side side &&
    ++	test_ctime_is_atime -1 &&
    ++	test_ctime_is_ignored -1
     + '
     +
      # This must be the last test in this file
5:  a11db78eb4 ! 5:  26d5eefdcb rebase: add --reset-author-date
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
     +				N_("synonym of --reset-author-date")),
      		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
      				  N_("passed to 'git apply'"), 0),
    - 		OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
    + 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
     
      ## t/t3436-rebase-more-options.sh ##
    -@@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-date works when committing confl
    - # Checking for +0000 in author time is enough since default
    - # timezone is UTC, but the timezone used while committing
    - # sets to +0530.
    +@@ t/t3436-rebase-more-options.sh: test_ctime_is_ignored () {
    + 	! grep -v +0000 authortime
    + }
    + 
     -test_expect_success '--ignore-date works with apply backend' '
     +test_expect_success '--reset-author-date works with apply backend' '
      	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     -	git rebase --apply --ignore-date HEAD^ &&
     +	git rebase --apply --reset-author-date HEAD^ &&
    - 	git log -1 --pretty=%ai >authortime &&
    - 	grep "+0000" authortime
    + 	test_ctime_is_ignored -1
      '
      
     -test_expect_success '--ignore-date works with merge backend' '
     +test_expect_success '--reset-author-date works with merge backend' '
      	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     -	git rebase --ignore-date -m HEAD^ &&
     +	git rebase --reset-author-date -m HEAD^ &&
    - 	git log -1 --pretty=%ai >authortime &&
    - 	grep "+0000" authortime
    + 	test_ctime_is_ignored -1
      '
      
     -test_expect_success '--ignore-date works after conflict resolution' '
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-
      		--onto commit2^^ commit2^ commit2 &&
      	echo resolved >foo &&
      	git add foo &&
    -@@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date works after conflict resolution' '
    - 	grep +0000 authortime
    + 	git rebase --continue &&
    + 	test_ctime_is_ignored -1
      '
      
     -test_expect_success '--ignore-date works with rebase -r' '
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date works after c
      	git merge --no-ff commit3 &&
     -	git rebase -r --root --ignore-date &&
     +	git rebase -r --root --reset-author-date &&
    - 	git log --pretty=%ai >authortime &&
    - 	! grep -v "+0000" authortime
    + 	test_ctime_is_ignored
      '
      
     -test_expect_success '--ignore-date with --committer-date-is-author-date works' '
    @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date works after c
      	git checkout --theirs foo &&
      	git add foo &&
      	git rebase --continue &&
    -@@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date with --committer-date-is-author-date works' '
    - 	! grep -v "+0000" authortime
    + 	test_ctime_is_atime -2 &&
    + 	test_ctime_is_ignored -2
      '
      
     -test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
     +test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
      	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
    --		git rebase -i --strategy=resolve --ignore-date \
    -+		git rebase -i --strategy=resolve --reset-author-date \
    - 		--committer-date-is-author-date side side &&
    - 	git log -1 --pretty=%ai >authortime &&
    - 	git log -1 --pretty=%ci >committertime &&
    - 	test_cmp authortime committertime &&
    - 	grep "+0000" authortime
    + 		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
    +-				--ignore-date --committer-date-is-author-date \
    +-				side side &&
    ++				--reset-author-date \
    ++				--committer-date-is-author-date side side &&
    + 	test_ctime_is_atime -1 &&
    + 	test_ctime_is_ignored -1
       '
      
     +test_expect_success '--ignore-date is an alias for --reset-author-date' '
     +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
     +	git rebase --apply --ignore-date HEAD^ &&
     +	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
     +	git rebase -m --ignore-date HEAD^ &&
    -+	git log -2 --pretty="format:%ai" >authortime &&
    -+	grep "+0000" authortime >output &&
    -+	test_line_count = 2 output
    ++	test_ctime_is_ignored -2
     +'
     +
      # This must be the last test in this file
-- 
2.27.0


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
@ 2020-06-26  9:55   ` Phillip Wood
  2020-06-26 13:37     ` Đoàn Trần Công Danh
  2020-06-26 15:43     ` Junio C Hamano
  2020-06-26  9:55   ` [PATCH v5 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
                     ` (4 subsequent siblings)
  5 siblings, 2 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26  9:55 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--ignore-whitespace option to the merge backend. This option treats
lines with only whitespace changes as unchanged and is implemented in
the merge backend by translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 19 +++++++-
 builtin/rebase.c                       | 16 +++++--
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++
 4 files changed, 90 insertions(+), 6 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f7a6033607..b003784f01 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Ignore whitespace differences when trying to reconcile
+differences. Currently, each backend implements an approximation of
+this behavior:
++
+apply backend: When applying a patch, ignore changes in whitespace in
+context lines. Unfortunately, this means that if the "old" lines being
+replaced by the patch differ only in whitespace from the existing
+file, you will get a merge conflict instead of a successful patch
+application.
++
+merge backend: Treat lines with only whitespace changes as unchanged
+when merging. Unfortunately, this means that any patch hunks that were
+intended to modify whitespace and nothing else will be dropped, even
+if the other side had no changes that conflicted.
+
 --whitespace=<option>::
-	These flags are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 	Implies --apply.
 +
@@ -572,7 +587,6 @@ The following options:
  * --apply
  * --committer-date-is-author-date
  * --ignore-date
- * --ignore-whitespace
  * --whitespace
  * -C
 
@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 27a07d4e78..810c9b7779 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
 		parse_strategy_opts(&replay, opts->strategy_opts);
 
@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct strbuf revisions = STRBUF_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id merge_base;
+	int ignore_whitespace = 0;
 	enum action action = ACTION_NONE;
 	const char *gpg_sign = NULL;
 	struct string_list exec = STRING_LIST_INIT_NODUP;
@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		imply_merge(&options, "--rebase-merges");
 	}
 
+	if (options.type == REBASE_APPLY) {
+		if (ignore_whitespace)
+			argv_array_push (&options.git_am_opts,
+					 "--ignore-whitespace");
+	} else if (ignore_whitespace) {
+			string_list_append (&strategy_options,
+					    "ignore-space-change");
+	}
+
 	if (strategy_options.nr) {
 		int i;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
new file mode 100755
index 0000000000..4f8a6e51c9
--- /dev/null
+++ b/t/t3436-rebase-more-options.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	test_write_lines "line 1" "	line 2" "line 3" >file &&
+	git add file &&
+	git commit -m "add file" &&
+
+	test_write_lines "line 1" "new line 2" "line 3" >file &&
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	test_write_lines "line 1" "        line 2" "line 3" >file &&
+	git commit -am "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with apply backend' '
+	test_must_fail git rebase --apply main side &&
+	git rebase --abort &&
+	git rebase --apply --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace works with merge backend' '
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
+			main side &&
+		git rebase --continue
+	) &&
+	git diff --exit-code side
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
+test_done
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v5 2/5] rebase -i: support --committer-date-is-author-date
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
  2020-06-26  9:55   ` [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-06-26  9:55   ` Phillip Wood
  2020-06-26  9:55   ` [PATCH v5 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26  9:55 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--committer-date-is-author-date option to the merge backend. This
option uses the author date of the commit that is being rewritten as
the committer date when the new commit is created.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 10 +++--
 builtin/rebase.c                       | 17 +++++---
 sequencer.c                            | 60 +++++++++++++++++++++++++-
 sequencer.h                            |  1 +
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++++++++++-
 6 files changed, 136 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b003784f01..dfa70263e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of using the current time as the committer date, use
+	the author date of the commit being rebased as the committer
+	date. This option implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 810c9b7779..a7c3d5c92b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -88,6 +88,7 @@ struct rebase_options {
 	int autosquash;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (ignore_whitespace)
 			argv_array_push (&options.git_am_opts,
 					 "--ignore-whitespace");
+		if (options.committer_date_is_author_date)
+			argv_array_push(&options.git_am_opts,
+					"--committer-date-is-author-date");
 	} else if (ignore_whitespace) {
 			string_list_append (&strategy_options,
 					    "ignore-space-change");
diff --git a/sequencer.c b/sequencer.c
index 6fd2674632..368d397970 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -872,6 +873,22 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+static const char *author_date_from_env_array(const struct argv_array *env)
+{
+	int i;
+	const char *date;
+
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
 			     gpg_opt, gpg_opt);
 	}
 
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 author_date_from_env_array(&cmd.env_array));
+
 	argv_array_push(&cmd.args, "commit");
 
 	if (!(flags & VERIFY_MSG))
@@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
+			res = error(_("malformed ident line '%s'"), author);
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin),
+			    ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin),
+			    ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
 	if (opts->keep_redundant_commits)
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
 			goto leave_merge;
 		}
 
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 author_date_from_env_array(&cmd.env_array));
+
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
 		argv_array_push(&cmd.args, "-s");
@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 0bee85093e..4ab94119ae 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -45,6 +45,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 4f8a6e51c9..50a63d8ebe 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -21,11 +24,20 @@ test_expect_success 'setup' '
 	test_write_lines "line 1" "new line 2" "line 3" >file &&
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	rm foo &&
 	test_write_lines "line 1" "        line 2" "line 3" >file &&
 	git commit -am "add file" &&
-	git tag main
+	git tag main &&
+
+	mkdir test-bin &&
+	write_script test-bin/git-merge-test <<-\EOF
+	exec git-merge-recursive "$@"
+	EOF
 '
 
 test_expect_success '--ignore-whitespace works with apply backend' '
@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
 	git diff --exit-code side
 '
 
+test_ctime_is_atime () {
+	git log $1 --format=%ai >authortime &&
+	git log $1 --format=%ci >committertime &&
+	test_cmp authortime committertime
+}
+
+test_expect_success '--committer-date-is-author-date works with apply backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase --apply --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with merge backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase -m --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
+					--committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -1
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v5 3/5] sequencer: rename amend_author to author_to_free
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
  2020-06-26  9:55   ` [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-06-26  9:55   ` [PATCH v5 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-06-26  9:55   ` Phillip Wood
  2020-06-26  9:55   ` [PATCH v5 4/5] rebase -i: support --ignore-date Phillip Wood
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26  9:55 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() when amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 368d397970..29f6d1bc39 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1474,7 +1474,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v5 4/5] rebase -i: support --ignore-date
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
                     ` (2 preceding siblings ...)
  2020-06-26  9:55   ` [PATCH v5 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
@ 2020-06-26  9:55   ` Phillip Wood
  2020-06-26 14:09     ` Đoàn Trần Công Danh
  2020-06-26 16:29     ` Junio C Hamano
  2020-06-26  9:55   ` [PATCH v5 5/5] rebase: add --reset-author-date Phillip Wood
  2020-06-26 15:04   ` [PATCH v5 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 2 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26  9:55 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the --ignore-date
option to the merge backend. This option uses the current time as the
author date rather than reusing the original author date when
rewriting commits. We take care to handle the combination of
--ignore-date and --committer-date-is-author-date in the same way as
the apply backend.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt   |  7 +++--
 builtin/rebase.c               | 13 +++++---
 sequencer.c                    | 50 ++++++++++++++++++++++++++++--
 sequencer.h                    |  1 +
 t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index dfa70263e6..e2717e20e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the author date of the original commit, use
+	the current time as the	author date of the rebased commit.  This
+	option implies `--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --ignore-date
  * --whitespace
  * -C
 
@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index a7c3d5c92b..890dd4c588 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -89,6 +89,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 "ignore author date and use current date"),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date || options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
 		else if (skip_prefix(option, "-C", &p)) {
@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (options.committer_date_is_author_date)
 			argv_array_push(&options.git_am_opts,
 					"--committer-date-is-author-date");
+		if (options.ignore_date)
+			argv_array_push(&options.git_am_opts, "--ignore-date");
 	} else if (ignore_whitespace) {
 			string_list_append (&strategy_options,
 					    "ignore-space-change");
diff --git a/sequencer.c b/sequencer.c
index 29f6d1bc39..f8e1e38623 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
 	BUG("GIT_AUTHOR_DATE missing from author script");
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len = strlen(author);
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, len) < 0) {
+		error(_("malformed ident line '%s'"), author);
+		return NULL;
+	}
+
+	len = ident.mail_end - ident.name_begin + 1;
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
 
 	if (opts->committer_date_is_author_date)
 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
 				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,
 			    ident.date_begin,
 			    (int)(ident.tz_end - ident.tz_begin),
 			    ident.tz_begin);
-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
 		strbuf_release(&date);
 
 		if (res)
@@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
+
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,
 
 		if (opts->committer_date_is_author_date)
 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
 					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 4ab94119ae..3587878e3b 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -46,6 +46,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 50a63d8ebe..0ede2b8900 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 	test_ctime_is_atime -1
 '
 
+# Checking for +0000 in the author date is sufficient since the
+# default timezone is UTC but the timezone used while committing is
+# +0530. The inverted logic in the grep is necessary to check all the
+# author dates in the file.
+test_ctime_is_ignored () {
+	git log $1 --format=%ai >authortime &&
+	! grep -v +0000 authortime
+}
+
+test_expect_success '--ignore-date works with apply backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with merge backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -m HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -m \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	test_ctime_is_ignored
+'
+
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -2 &&
+	test_ctime_is_ignored -2
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
+				--ignore-date --committer-date-is-author-date \
+				side side &&
+	test_ctime_is_atime -1 &&
+	test_ctime_is_ignored -1
+ '
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v5 5/5] rebase: add --reset-author-date
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
                     ` (3 preceding siblings ...)
  2020-06-26  9:55   ` [PATCH v5 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-06-26  9:55   ` Phillip Wood
  2020-06-26 16:35     ` Junio C Hamano
  2020-06-26 15:04   ` [PATCH v5 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-06-26  9:55 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The previous commit introduced --ignore-date flag to rebase -i, but the
name is rather vague as it does not say whether the author date or the
committer date is ignored. Add an alias to convey the precise purpose.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt   |  1 +
 builtin/rebase.c               |  6 ++++--
 t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e2717e20e6..a5f82913fb 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the author date of the original commit, use
 	the current time as the	author date of the rebased commit.  This
 	option implies `--force-rebase`.
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 890dd4c588..3fe33beef4 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
-			 "ignore author date and use current date"),
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 0ede2b8900..5b8963272a 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -117,53 +117,61 @@ test_ctime_is_ignored () {
 	! grep -v +0000 authortime
 }
 
-test_expect_success '--ignore-date works with apply backend' '
+test_expect_success '--reset-author-date works with apply backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --apply --ignore-date HEAD^ &&
+	git rebase --apply --reset-author-date HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with merge backend' '
+test_expect_success '--reset-author-date works with merge backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --ignore-date -m HEAD^ &&
+	git rebase --reset-author-date -m HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works after conflict resolution' '
-	test_must_fail git rebase --ignore-date -m \
+test_expect_success '--reset-author-date works after conflict resolution' '
+	test_must_fail git rebase --reset-author-date -m \
 		--onto commit2^^ commit2^ commit2 &&
 	echo resolved >foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with rebase -r' '
+test_expect_success '--reset-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
-	git rebase -r --root --ignore-date &&
+	git rebase -r --root --reset-author-date &&
 	test_ctime_is_ignored
 '
 
-test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
 	test_must_fail git rebase -m --committer-date-is-author-date \
-		--ignore-date --onto commit2^^ commit2^ commit3 &&
+		--reset-author-date --onto commit2^^ commit2^ commit3 &&
 	git checkout --theirs foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_atime -2 &&
 	test_ctime_is_ignored -2
 '
 
-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
 	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
 		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
-				--ignore-date --committer-date-is-author-date \
-				side side &&
+				--reset-author-date \
+				--committer-date-is-author-date side side &&
 	test_ctime_is_atime -1 &&
 	test_ctime_is_ignored -1
  '
 
+test_expect_success '--ignore-date is an alias for --reset-author-date' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
+	git rebase -m --ignore-date HEAD^ &&
+	test_ctime_is_ignored -2
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-26  9:55   ` [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-06-26 13:37     ` Đoàn Trần Công Danh
  2020-06-26 14:43       ` Phillip Wood
  2020-06-26 15:43     ` Junio C Hamano
  1 sibling, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-06-26 13:37 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

On 2020-06-26 10:55:24+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> 
> Rebase is implemented with two different backends - 'apply' and
> 'merge' each of which support a different set of options. In
> particular the apply backend supports a number of options implemented
> by 'git am' that are not implemented in the merge backend. This means
> that the available options are different depending on which backend is
> used which is confusing. This patch adds support for the
> --ignore-whitespace option to the merge backend. This option treats
> lines with only whitespace changes as unchanged and is implemented in
> the merge backend by translating it to -Xignore-space-change.
> 
> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt           | 19 +++++++-
>  builtin/rebase.c                       | 16 +++++--
>  t/t3422-rebase-incompatible-options.sh |  1 -
>  t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++
>  4 files changed, 90 insertions(+), 6 deletions(-)
>  create mode 100755 t/t3436-rebase-more-options.sh
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index f7a6033607..b003784f01 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
>  with `--keep-base` in order to drop those commits from your branch.
>  
>  --ignore-whitespace::
> +	Ignore whitespace differences when trying to reconcile
> +differences. Currently, each backend implements an approximation of
> +this behavior:
> ++
> +apply backend: When applying a patch, ignore changes in whitespace in
> +context lines. Unfortunately, this means that if the "old" lines being
> +replaced by the patch differ only in whitespace from the existing
> +file, you will get a merge conflict instead of a successful patch
> +application.
> ++
> +merge backend: Treat lines with only whitespace changes as unchanged
> +when merging. Unfortunately, this means that any patch hunks that were
> +intended to modify whitespace and nothing else will be dropped, even
> +if the other side had no changes that conflicted.
> +
>  --whitespace=<option>::
> -	These flags are passed to the 'git apply' program
> +	This flag is passed to the 'git apply' program
>  	(see linkgit:git-apply[1]) that applies the patch.
>  	Implies --apply.
>  +
> @@ -572,7 +587,6 @@ The following options:
>   * --apply
>   * --committer-date-is-author-date
>   * --ignore-date
> - * --ignore-whitespace
>   * --whitespace
>   * -C
>  
> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --signoff
>   * --preserve-merges and --rebase-merges
>   * --preserve-merges and --empty=
> + * --preserve-merges and --ignore-whitespace
>   * --keep-base and --onto
>   * --keep-base and --root
>  
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 27a07d4e78..810c9b7779 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>  	replay.strategy = opts->strategy;
> +
>  	if (opts->strategy_opts)
>  		parse_strategy_opts(&replay, opts->strategy_opts);
>  
> @@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  	struct strbuf revisions = STRBUF_INIT;
>  	struct strbuf buf = STRBUF_INIT;
>  	struct object_id merge_base;
> +	int ignore_whitespace = 0;
>  	enum action action = ACTION_NONE;
>  	const char *gpg_sign = NULL;
>  	struct string_list exec = STRING_LIST_INIT_NODUP;
> @@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>  		OPT_BOOL(0, "signoff", &options.signoff,
>  			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
> -				  NULL, N_("passed to 'git am'"),
> -				  PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>  				  &options.git_am_opts, NULL,
>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>  				  N_("passed to 'git apply'"), 0),
> +		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
> +			 N_("ignore changes in whitespace")),
>  		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>  				  N_("action"), N_("passed to 'git apply'"), 0),
>  		OPT_BIT('f', "force-rebase", &options.flags,
> @@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		imply_merge(&options, "--rebase-merges");
>  	}
>  
> +	if (options.type == REBASE_APPLY) {
> +		if (ignore_whitespace)
> +			argv_array_push (&options.git_am_opts,
> +					 "--ignore-whitespace");
> +	} else if (ignore_whitespace) {
> +			string_list_append (&strategy_options,
> +					    "ignore-space-change");
> +	}
> +

Hm, I've just noticed this by now.
Would it's better if we rewrite it as:

	if (ignore_whitespace) {
		if (options.type == REBASE_APPLY)
			argv_array_push(&options.git_am_opts,
					"--ignore-whitespace");
		else
			string_list_append(&strategy_options,
					   "ignore-space-change");
	}

Ah, the incoming patches will add more conditions into the:

	if (options.type == REBASE_APPLY)

I'm still not convinced, though.

Anyway, IIRC, --ignore-whitespace and --ignore-space-change has the
same meaning, I think it's better to use the same option for both
legs, no?

I can understand the decision to use --ignore-whitespace as keeping
the pass-through behavior of old code, but I think future maintenance
is more important than that.

I've tried changing ignore-whitespace to ignore-space-change and run
make test

It looks good to me (aka nothing failed _in my machine_),
4/5 and 5/5 is not applied, though.

>  	if (strategy_options.nr) {
>  		int i;
>  
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 50e7960702..55ca46786d 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>  
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
>  test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>  
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> new file mode 100755
> index 0000000000..4f8a6e51c9
> --- /dev/null
> +++ b/t/t3436-rebase-more-options.sh
> @@ -0,0 +1,60 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2019 Rohit Ashiwal
> +#
> +
> +test_description='tests to ensure compatibility between am and interactive backends'
> +
> +. ./test-lib.sh
> +
> +. "$TEST_DIRECTORY"/lib-rebase.sh
> +
> +# This is a special case in which both am and interactive backends
> +# provide the same output. It was done intentionally because
> +# both the backends fall short of optimal behaviour.
> +test_expect_success 'setup' '
> +	git checkout -b topic &&
> +	test_write_lines "line 1" "	line 2" "line 3" >file &&
> +	git add file &&
> +	git commit -m "add file" &&
> +
> +	test_write_lines "line 1" "new line 2" "line 3" >file &&
> +	git commit -am "update file" &&
> +	git tag side &&
> +
> +	git checkout --orphan master &&
> +	test_write_lines "line 1" "        line 2" "line 3" >file &&
> +	git commit -am "add file" &&
> +	git tag main
> +'
> +
> +test_expect_success '--ignore-whitespace works with apply backend' '
> +	test_must_fail git rebase --apply main side &&
> +	git rebase --abort &&
> +	git rebase --apply --ignore-whitespace main side &&
> +	git diff --exit-code side
> +'
> +
> +test_expect_success '--ignore-whitespace works with merge backend' '
> +	test_must_fail git rebase --merge main side &&
> +	git rebase --abort &&
> +	git rebase --merge --ignore-whitespace main side &&
> +	git diff --exit-code side
> +'
> +
> +test_expect_success '--ignore-whitespace is remembered when continuing' '
> +	(
> +		set_fake_editor &&
> +		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
> +			main side &&
> +		git rebase --continue
> +	) &&
> +	git diff --exit-code side
> +'
> +
> +# This must be the last test in this file
> +test_expect_success '$EDITOR and friends are unchanged' '
> +	test_editor_unchanged
> +'
> +
> +test_done
> -- 
> 2.27.0
> 

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 4/5] rebase -i: support --ignore-date
  2020-06-26  9:55   ` [PATCH v5 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-06-26 14:09     ` Đoàn Trần Công Danh
  2020-06-26 14:38       ` Phillip Wood
  2020-06-26 16:29     ` Junio C Hamano
  1 sibling, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-06-26 14:09 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

On 2020-06-26 10:55:27+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
> 
> Rebase is implemented with two different backends - 'apply' and
> 'merge' each of which support a different set of options. In
> particular the apply backend supports a number of options implemented
> by 'git am' that are not implemented in the merge backend. This means
> that the available options are different depending on which backend is
> used which is confusing. This patch adds support for the --ignore-date
> option to the merge backend. This option uses the current time as the
> author date rather than reusing the original author date when
> rewriting commits. We take care to handle the combination of
> --ignore-date and --committer-date-is-author-date in the same way as
> the apply backend.
> 
> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt   |  7 +++--
>  builtin/rebase.c               | 13 +++++---
>  sequencer.c                    | 50 ++++++++++++++++++++++++++++--
>  sequencer.h                    |  1 +
>  t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++
>  5 files changed, 117 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index dfa70263e6..e2717e20e6 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
>  	date. This option implies --force-rebase.
>  
>  --ignore-date::
> -	This flag is passed to 'git am' to change the author date
> -	of each rebased commit (see linkgit:git-am[1]).
> +	Instead of using the author date of the original commit, use
> +	the current time as the	author date of the rebased commit.  This
> +	option implies `--force-rebase`.
>  +
>  See also INCOMPATIBLE OPTIONS below.
>  
> @@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
>  The following options:
>  
>   * --apply
> - * --ignore-date
>   * --whitespace
>   * -C
>  
> @@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --empty=
>   * --preserve-merges and --ignore-whitespace
>   * --preserve-merges and --committer-date-is-author-date
> + * --preserve-merges and --ignore-date
>   * --keep-base and --onto
>   * --keep-base and --root
>  
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index a7c3d5c92b..890dd4c588 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -89,6 +89,7 @@ struct rebase_options {
>  	char *gpg_sign_opt;
>  	int autostash;
>  	int committer_date_is_author_date;
> +	int ignore_date;
>  	char *cmd;
>  	int allow_empty_message;
>  	int rebase_merges, rebase_cousins;
> @@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>  	replay.committer_date_is_author_date =
>  					opts->committer_date_is_author_date;
> +	replay.ignore_date = opts->ignore_date;
>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>  	replay.strategy = opts->strategy;
>  
> @@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		OPT_BOOL(0, "committer-date-is-author-date",
>  			 &options.committer_date_is_author_date,
>  			 N_("make committer date match author date")),
> -		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "ignore-date", &options.ignore_date,
> +			 "ignore author date and use current date"),

Nit: The options' description is subjected to l10n.

s/".*"/N_(&)/

>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>  				  N_("passed to 'git apply'"), 0),
>  		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
> @@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  	    options.autosquash) {
>  		allow_preemptive_ff = 0;
>  	}
> -	if (options.committer_date_is_author_date)
> +	if (options.committer_date_is_author_date || options.ignore_date)
>  		options.flags |= REBASE_FORCE;
>  
>  	for (i = 0; i < options.git_am_opts.argc; i++) {
>  		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--ignore-date") ||
> -		    !strcmp(option, "--whitespace=fix") ||
> +		if (!strcmp(option, "--whitespace=fix") ||
>  		    !strcmp(option, "--whitespace=strip"))
>  			allow_preemptive_ff = 0;
>  		else if (skip_prefix(option, "-C", &p)) {
> @@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		if (options.committer_date_is_author_date)
>  			argv_array_push(&options.git_am_opts,
>  					"--committer-date-is-author-date");
> +		if (options.ignore_date)
> +			argv_array_push(&options.git_am_opts, "--ignore-date");
>  	} else if (ignore_whitespace) {
>  			string_list_append (&strategy_options,
>  					    "ignore-space-change");
> diff --git a/sequencer.c b/sequencer.c
> index 29f6d1bc39..f8e1e38623 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>  static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
>  	BUG("GIT_AUTHOR_DATE missing from author script");
>  }
>  
> +/* Construct a free()able author string with current time as the author date */
> +static char *ignore_author_date(const char *author)
> +{
> +	int len = strlen(author);
> +	struct ident_split ident;
> +	struct strbuf new_author = STRBUF_INIT;
> +
> +	if (split_ident_line(&ident, author, len) < 0) {
> +		error(_("malformed ident line '%s'"), author);
> +		return NULL;
> +	}
> +
> +	len = ident.mail_end - ident.name_begin + 1;
> +	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);

I wonder if we can do this instead:

	strbuf_add(&new_author, ident.name_begin, len);

Quick skim through the code and nothing crashes when make test with:

	CFLAGS="-fstack-clash-protection -D_FORTIFY_SOURCE=2"

I think it's OK to be changed.

> +	datestamp(&new_author);
> +	return strbuf_detach(&new_author, NULL);
> +}
> +

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 4/5] rebase -i: support --ignore-date
  2020-06-26 14:09     ` Đoàn Trần Công Danh
@ 2020-06-26 14:38       ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26 14:38 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 26/06/2020 15:09, Đoàn Trần Công Danh wrote:
> On 2020-06-26 10:55:27+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> Rebase is implemented with two different backends - 'apply' and
>> 'merge' each of which support a different set of options. In
>> particular the apply backend supports a number of options implemented
>> by 'git am' that are not implemented in the merge backend. This means
>> that the available options are different depending on which backend is
>> used which is confusing. This patch adds support for the --ignore-date
>> option to the merge backend. This option uses the current time as the
>> author date rather than reusing the original author date when
>> rewriting commits. We take care to handle the combination of
>> --ignore-date and --committer-date-is-author-date in the same way as
>> the apply backend.
>>
>> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>   Documentation/git-rebase.txt   |  7 +++--
>>   builtin/rebase.c               | 13 +++++---
>>   sequencer.c                    | 50 ++++++++++++++++++++++++++++--
>>   sequencer.h                    |  1 +
>>   t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++
>>   5 files changed, 117 insertions(+), 10 deletions(-)
>>
>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
>> index dfa70263e6..e2717e20e6 100644
>> --- a/Documentation/git-rebase.txt
>> +++ b/Documentation/git-rebase.txt
>> @@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
>>   	date. This option implies --force-rebase.
>>   
>>   --ignore-date::
>> -	This flag is passed to 'git am' to change the author date
>> -	of each rebased commit (see linkgit:git-am[1]).
>> +	Instead of using the author date of the original commit, use
>> +	the current time as the	author date of the rebased commit.  This
>> +	option implies `--force-rebase`.
>>   +
>>   See also INCOMPATIBLE OPTIONS below.
>>   
>> @@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
>>   The following options:
>>   
>>    * --apply
>> - * --ignore-date
>>    * --whitespace
>>    * -C
>>   
>> @@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
>>    * --preserve-merges and --empty=
>>    * --preserve-merges and --ignore-whitespace
>>    * --preserve-merges and --committer-date-is-author-date
>> + * --preserve-merges and --ignore-date
>>    * --keep-base and --onto
>>    * --keep-base and --root
>>   
>> diff --git a/builtin/rebase.c b/builtin/rebase.c
>> index a7c3d5c92b..890dd4c588 100644
>> --- a/builtin/rebase.c
>> +++ b/builtin/rebase.c
>> @@ -89,6 +89,7 @@ struct rebase_options {
>>   	char *gpg_sign_opt;
>>   	int autostash;
>>   	int committer_date_is_author_date;
>> +	int ignore_date;
>>   	char *cmd;
>>   	int allow_empty_message;
>>   	int rebase_merges, rebase_cousins;
>> @@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>>   	replay.committer_date_is_author_date =
>>   					opts->committer_date_is_author_date;
>> +	replay.ignore_date = opts->ignore_date;
>>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>>   	replay.strategy = opts->strategy;
>>   
>> @@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>   		OPT_BOOL(0, "committer-date-is-author-date",
>>   			 &options.committer_date_is_author_date,
>>   			 N_("make committer date match author date")),
>> -		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>> +		OPT_BOOL(0, "ignore-date", &options.ignore_date,
>> +			 "ignore author date and use current date"),
> 
> Nit: The options' description is subjected to l10n.
> 
> s/".*"/N_(&)/

Well spotted, thanks

>>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>>   				  N_("passed to 'git apply'"), 0),
>>   		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
>> @@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>   	    options.autosquash) {
>>   		allow_preemptive_ff = 0;
>>   	}
>> -	if (options.committer_date_is_author_date)
>> +	if (options.committer_date_is_author_date || options.ignore_date)
>>   		options.flags |= REBASE_FORCE;
>>   
>>   	for (i = 0; i < options.git_am_opts.argc; i++) {
>>   		const char *option = options.git_am_opts.argv[i], *p;
>> -		if (!strcmp(option, "--ignore-date") ||
>> -		    !strcmp(option, "--whitespace=fix") ||
>> +		if (!strcmp(option, "--whitespace=fix") ||
>>   		    !strcmp(option, "--whitespace=strip"))
>>   			allow_preemptive_ff = 0;
>>   		else if (skip_prefix(option, "-C", &p)) {
>> @@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>   		if (options.committer_date_is_author_date)
>>   			argv_array_push(&options.git_am_opts,
>>   					"--committer-date-is-author-date");
>> +		if (options.ignore_date)
>> +			argv_array_push(&options.git_am_opts, "--ignore-date");
>>   	} else if (ignore_whitespace) {
>>   			string_list_append (&strategy_options,
>>   					    "ignore-space-change");
>> diff --git a/sequencer.c b/sequencer.c
>> index 29f6d1bc39..f8e1e38623 100644
>> --- a/sequencer.c
>> +++ b/sequencer.c
>> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>>    */
>>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
>>   static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>> +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
>>   static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>>   static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>>   static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
>> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
>>   	BUG("GIT_AUTHOR_DATE missing from author script");
>>   }
>>   
>> +/* Construct a free()able author string with current time as the author date */
>> +static char *ignore_author_date(const char *author)
>> +{
>> +	int len = strlen(author);
>> +	struct ident_split ident;
>> +	struct strbuf new_author = STRBUF_INIT;
>> +
>> +	if (split_ident_line(&ident, author, len) < 0) {
>> +		error(_("malformed ident line '%s'"), author);
>> +		return NULL;
>> +	}
>> +
>> +	len = ident.mail_end - ident.name_begin + 1;
>> +	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
> 
> I wonder if we can do this instead:
> 
> 	strbuf_add(&new_author, ident.name_begin, len);

There is a space at the end of the format string, which I think is 
needed to separate the name and email from the date we add with 
datestamp() below

Best Wishes

Phillip

> Quick skim through the code and nothing crashes when make test with:
>
> 	CFLAGS="-fstack-clash-protection -D_FORTIFY_SOURCE=2"
> 
> I think it's OK to be changed.
> 
>> +	datestamp(&new_author);
>> +	return strbuf_detach(&new_author, NULL);
>> +}
>> +
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-26 13:37     ` Đoàn Trần Công Danh
@ 2020-06-26 14:43       ` Phillip Wood
  2020-06-26 16:03         ` Junio C Hamano
  2020-06-29 14:14         ` Đoàn Trần Công Danh
  0 siblings, 2 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26 14:43 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 26/06/2020 14:37, Đoàn Trần Công Danh wrote:
> On 2020-06-26 10:55:24+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>>
>> Rebase is implemented with two different backends - 'apply' and
>> 'merge' each of which support a different set of options. In
>> particular the apply backend supports a number of options implemented
>> by 'git am' that are not implemented in the merge backend. This means
>> that the available options are different depending on which backend is
>> used which is confusing. This patch adds support for the
>> --ignore-whitespace option to the merge backend. This option treats
>> lines with only whitespace changes as unchanged and is implemented in
>> the merge backend by translating it to -Xignore-space-change.
>>
>> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>   Documentation/git-rebase.txt           | 19 +++++++-
>>   builtin/rebase.c                       | 16 +++++--
>>   t/t3422-rebase-incompatible-options.sh |  1 -
>>   t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++
>>   4 files changed, 90 insertions(+), 6 deletions(-)
>>   create mode 100755 t/t3436-rebase-more-options.sh
>>
>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
>> index f7a6033607..b003784f01 100644
>> --- a/Documentation/git-rebase.txt
>> +++ b/Documentation/git-rebase.txt
>> @@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
>>   with `--keep-base` in order to drop those commits from your branch.
>>   
>>   --ignore-whitespace::
>> +	Ignore whitespace differences when trying to reconcile
>> +differences. Currently, each backend implements an approximation of
>> +this behavior:
>> ++
>> +apply backend: When applying a patch, ignore changes in whitespace in
>> +context lines. Unfortunately, this means that if the "old" lines being
>> +replaced by the patch differ only in whitespace from the existing
>> +file, you will get a merge conflict instead of a successful patch
>> +application.
>> ++
>> +merge backend: Treat lines with only whitespace changes as unchanged
>> +when merging. Unfortunately, this means that any patch hunks that were
>> +intended to modify whitespace and nothing else will be dropped, even
>> +if the other side had no changes that conflicted.
>> +
>>   --whitespace=<option>::
>> -	These flags are passed to the 'git apply' program
>> +	This flag is passed to the 'git apply' program
>>   	(see linkgit:git-apply[1]) that applies the patch.
>>   	Implies --apply.
>>   +
>> @@ -572,7 +587,6 @@ The following options:
>>    * --apply
>>    * --committer-date-is-author-date
>>    * --ignore-date
>> - * --ignore-whitespace
>>    * --whitespace
>>    * -C
>>   
>> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
>>    * --preserve-merges and --signoff
>>    * --preserve-merges and --rebase-merges
>>    * --preserve-merges and --empty=
>> + * --preserve-merges and --ignore-whitespace
>>    * --keep-base and --onto
>>    * --keep-base and --root
>>   
>> diff --git a/builtin/rebase.c b/builtin/rebase.c
>> index 27a07d4e78..810c9b7779 100644
>> --- a/builtin/rebase.c
>> +++ b/builtin/rebase.c
>> @@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>>   	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>>   	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>>   	replay.strategy = opts->strategy;
>> +
>>   	if (opts->strategy_opts)
>>   		parse_strategy_opts(&replay, opts->strategy_opts);
>>   
>> @@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>   	struct strbuf revisions = STRBUF_INIT;
>>   	struct strbuf buf = STRBUF_INIT;
>>   	struct object_id merge_base;
>> +	int ignore_whitespace = 0;
>>   	enum action action = ACTION_NONE;
>>   	const char *gpg_sign = NULL;
>>   	struct string_list exec = STRING_LIST_INIT_NODUP;
>> @@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>   			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>>   		OPT_BOOL(0, "signoff", &options.signoff,
>>   			 N_("add a Signed-off-by: line to each commit")),
>> -		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
>> -				  NULL, N_("passed to 'git am'"),
>> -				  PARSE_OPT_NOARG),
>>   		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
>>   				  &options.git_am_opts, NULL,
>>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>>   		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>>   				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>>   		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
>>   				  N_("passed to 'git apply'"), 0),
>> +		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
>> +			 N_("ignore changes in whitespace")),
>>   		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
>>   				  N_("action"), N_("passed to 'git apply'"), 0),
>>   		OPT_BIT('f', "force-rebase", &options.flags,
>> @@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>>   		imply_merge(&options, "--rebase-merges");
>>   	}
>>   
>> +	if (options.type == REBASE_APPLY) {
>> +		if (ignore_whitespace)
>> +			argv_array_push (&options.git_am_opts,
>> +					 "--ignore-whitespace");
>> +	} else if (ignore_whitespace) {
>> +			string_list_append (&strategy_options,
>> +					    "ignore-space-change");
>> +	}
>> +
> 
> Hm, I've just noticed this by now.
> Would it's better if we rewrite it as:
> 
> 	if (ignore_whitespace) {
> 		if (options.type == REBASE_APPLY)
> 			argv_array_push(&options.git_am_opts,
> 					"--ignore-whitespace");
> 		else
> 			string_list_append(&strategy_options,
> 					   "ignore-space-change");
> 	}
> 
> Ah, the incoming patches will add more conditions into the:
> 
> 	if (options.type == REBASE_APPLY)
> 
> I'm still not convinced, though.

I wanted to keep the subsequent patches as simple as possible. Having to 
rewrite the if statement in the next patch just clutters it up and makes 
the real changes introduced by that patch less obvious

> Anyway, IIRC, --ignore-whitespace and --ignore-space-change has the
> same meaning, I think it's better to use the same option for both
> legs, no?
> 
> I can understand the decision to use --ignore-whitespace as keeping
> the pass-through behavior of old code, but I think future maintenance
> is more important than that.

I'm not sure how it affects future maintenance. The two different 
options are for two different commands so I'm not sure it is worth the 
effort

Best Wishes

Phillip

> I've tried changing ignore-whitespace to ignore-space-change and run
> make test
> 
> It looks good to me (aka nothing failed _in my machine_),
> 4/5 and 5/5 is not applied, though.
> 
>>   	if (strategy_options.nr) {
>>   		int i;
>>   
>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>> index 50e7960702..55ca46786d 100755
>> --- a/t/t3422-rebase-incompatible-options.sh
>> +++ b/t/t3422-rebase-incompatible-options.sh
>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>   }
>>   
>>   test_rebase_am_only --whitespace=fix
>> -test_rebase_am_only --ignore-whitespace
>>   test_rebase_am_only --committer-date-is-author-date
>>   test_rebase_am_only -C4
>>   
>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>> new file mode 100755
>> index 0000000000..4f8a6e51c9
>> --- /dev/null
>> +++ b/t/t3436-rebase-more-options.sh
>> @@ -0,0 +1,60 @@
>> +#!/bin/sh
>> +#
>> +# Copyright (c) 2019 Rohit Ashiwal
>> +#
>> +
>> +test_description='tests to ensure compatibility between am and interactive backends'
>> +
>> +. ./test-lib.sh
>> +
>> +. "$TEST_DIRECTORY"/lib-rebase.sh
>> +
>> +# This is a special case in which both am and interactive backends
>> +# provide the same output. It was done intentionally because
>> +# both the backends fall short of optimal behaviour.
>> +test_expect_success 'setup' '
>> +	git checkout -b topic &&
>> +	test_write_lines "line 1" "	line 2" "line 3" >file &&
>> +	git add file &&
>> +	git commit -m "add file" &&
>> +
>> +	test_write_lines "line 1" "new line 2" "line 3" >file &&
>> +	git commit -am "update file" &&
>> +	git tag side &&
>> +
>> +	git checkout --orphan master &&
>> +	test_write_lines "line 1" "        line 2" "line 3" >file &&
>> +	git commit -am "add file" &&
>> +	git tag main
>> +'
>> +
>> +test_expect_success '--ignore-whitespace works with apply backend' '
>> +	test_must_fail git rebase --apply main side &&
>> +	git rebase --abort &&
>> +	git rebase --apply --ignore-whitespace main side &&
>> +	git diff --exit-code side
>> +'
>> +
>> +test_expect_success '--ignore-whitespace works with merge backend' '
>> +	test_must_fail git rebase --merge main side &&
>> +	git rebase --abort &&
>> +	git rebase --merge --ignore-whitespace main side &&
>> +	git diff --exit-code side
>> +'
>> +
>> +test_expect_success '--ignore-whitespace is remembered when continuing' '
>> +	(
>> +		set_fake_editor &&
>> +		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
>> +			main side &&
>> +		git rebase --continue
>> +	) &&
>> +	git diff --exit-code side
>> +'
>> +
>> +# This must be the last test in this file
>> +test_expect_success '$EDITOR and friends are unchanged' '
>> +	test_editor_unchanged
>> +'
>> +
>> +test_done
>> -- 
>> 2.27.0
>>
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 0/5] cleanup ra/rebase-i-more-options
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
                     ` (4 preceding siblings ...)
  2020-06-26  9:55   ` [PATCH v5 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-06-26 15:04   ` Junio C Hamano
  5 siblings, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-06-26 15:04 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> I've updated the commit messages, option handling and tests as
> suggested by dscho. I've also changed the tests that used
> '--strategy=resolve' to use a real external merge strategy so they
> continue to test the same code path once Alban's patches to handle the
> resolve strategy without forking are merged

Thanks, will take a look and replace.


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-26  9:55   ` [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-06-26 13:37     ` Đoàn Trần Công Danh
@ 2020-06-26 15:43     ` Junio C Hamano
  1 sibling, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-06-26 15:43 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> ... This option treats
> lines with only whitespace changes as unchanged and is implemented in
> the merge backend by translating it to -Xignore-space-change.

OK.  Hiding the subtle difference is good.

> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
>   * --preserve-merges and --signoff
>   * --preserve-merges and --rebase-merges
>   * --preserve-merges and --empty=
> + * --preserve-merges and --ignore-whitespace
>   * --keep-base and --onto
>   * --keep-base and --root

Hmph...

> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 27a07d4e78..810c9b7779 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>  	replay.strategy = opts->strategy;
> +
>  	if (opts->strategy_opts)
>  		parse_strategy_opts(&replay, opts->strategy_opts);

Usually I would complain about whitespace-only changes to places
where there is no real change, but I am OK with this one.  It does
make sense to have a blank here.

> @@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		imply_merge(&options, "--rebase-merges");
>  	}
>  
> +	if (options.type == REBASE_APPLY) {
> +		if (ignore_whitespace)
> +			argv_array_push (&options.git_am_opts,
> +					 "--ignore-whitespace");
> +	} else if (ignore_whitespace) {
> +			string_list_append (&strategy_options,
> +					    "ignore-space-change");
> +	}

I agree with the other reviewer that "when --ignore-whitespace is
given, do these different things depending on the .type" is easier
to follow.  Also pay attention to the style.  There is no SP between
the name of the function and the opening '(' for its parameter list.

	if (ignore_whitespace) {
        	if (options.type == REBASE_APPLY)
			argv_array_push(&options.git_am_opts, "--ignore-whitespace");
		else
			string_list_append(&strategy_options, "ignore-space-change");
	}


> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 50e7960702..55ca46786d 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>  
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --ignore-whitespace
>  test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4

OK.

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-26 14:43       ` Phillip Wood
@ 2020-06-26 16:03         ` Junio C Hamano
  2020-06-29 14:14         ` Đoàn Trần Công Danh
  1 sibling, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-06-26 16:03 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Đoàn Trần Công Danh, Phillip Wood,
	Johannes Schindelin, Elijah Newren, Rohit Ashiwal, Alban Gruin,
	Git Mailing List

Phillip Wood <phillip.wood123@gmail.com> writes:

>>>   +	if (options.type == REBASE_APPLY) {
>>> +		if (ignore_whitespace)
>>> +			argv_array_push (&options.git_am_opts,
>>> +					 "--ignore-whitespace");
>>> +	} else if (ignore_whitespace) {
>>> +			string_list_append (&strategy_options,
>>> +					    "ignore-space-change");
>>> +	}
>>> +
>> ...
> I wanted to keep the subsequent patches as simple as possible. Having
> to rewrite the if statement in the next patch just clutters it up and
> makes the real changes introduced by that patch less obvious

A set of different behaviour depending on .type is OK, but then at
least the above should be more like this:

	if (options.type == REBASE_APPLY) {
		if (ignore_whitespace)
			argv_array_push(...);
	} else {
		/* REBASE_MERGE and PRESERVE_MERGES */
		if (ignore_whitespace)
			string_list_append(...);
	}

or even

	switch (options.type) {
	case REBASE_APPLY:
		...
		break;
	case REBASE_MERGE:
	case REBASE_PRESERVE_MERGES:
		...
		break;
	default:
		BUG("unhandled rebase type %d", options.type);
	}

That would clarify the flow of the logic better.

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 4/5] rebase -i: support --ignore-date
  2020-06-26  9:55   ` [PATCH v5 4/5] rebase -i: support --ignore-date Phillip Wood
  2020-06-26 14:09     ` Đoàn Trần Công Danh
@ 2020-06-26 16:29     ` Junio C Hamano
  1 sibling, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-06-26 16:29 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> +/* Construct a free()able author string with current time as the author date */
> +static char *ignore_author_date(const char *author)
> +{
> +	int len = strlen(author);

I'd rather not to see this initialization, because ...

> +	struct ident_split ident;
> +	struct strbuf new_author = STRBUF_INIT;
> +
> +	if (split_ident_line(&ident, author, len) < 0) {

... it is away from this line.  This line is better written

	if (split_ident_line(&ident, author, strlen(author)) < 0) {

to show what the third parameter is about.  It is not just "len",
but is the length of the second parameter, author.

> +		error(_("malformed ident line '%s'"), author);
> +		return NULL;
> +	}
> +
> +	len = ident.mail_end - ident.name_begin + 1;
> +	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
> +	datestamp(&new_author);
> +	return strbuf_detach(&new_author, NULL);
> +}

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 5/5] rebase: add --reset-author-date
  2020-06-26  9:55   ` [PATCH v5 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-06-26 16:35     ` Junio C Hamano
  2020-06-26 18:07       ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-06-26 16:35 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Phillip Wood <phillip.wood123@gmail.com> writes:

> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>
> The previous commit introduced --ignore-date flag to rebase -i, but the
> name is rather vague as it does not say whether the author date or the
> committer date is ignored. Add an alias to convey the precise purpose.
>
> Helped-by: Junio C Hamano <gitster@pobox.com>

Hmph, did I?

> +		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
> +			 N_("ignore author date and use current date")),
> +		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
> +				N_("synonym of --reset-author-date")),

It is merely hidden but still supported.

> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 0ede2b8900..5b8963272a 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -117,53 +117,61 @@ test_ctime_is_ignored () {
>  	! grep -v +0000 authortime
>  }
>  
> -test_expect_success '--ignore-date works with apply backend' '
> +test_expect_success '--reset-author-date works with apply backend' '
>  	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> -	git rebase --apply --ignore-date HEAD^ &&
> +	git rebase --apply --reset-author-date HEAD^ &&
>  	test_ctime_is_ignored -1
>  '

Are there still some tests that check "--ignore-date"?  We probably
should have them, if we are not removing the support.

Thanks.  The entire series looked reasonable to me.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 5/5] rebase: add --reset-author-date
  2020-06-26 16:35     ` Junio C Hamano
@ 2020-06-26 18:07       ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-06-26 18:07 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi Junio

On 26/06/2020 17:35, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
>>
>> The previous commit introduced --ignore-date flag to rebase -i, but the
>> name is rather vague as it does not say whether the author date or the
>> committer date is ignored. Add an alias to convey the precise purpose.
>>
>> Helped-by: Junio C Hamano <gitster@pobox.com>
> 
> Hmph, did I?

Yes, you added a fixup d82dfa7f5b ("rebase -i: finishing touches to
--reset-author-date", 2019-11-21) which I squashed into this patch

> 
>> +		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
>> +			 N_("ignore author date and use current date")),
>> +		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
>> +				N_("synonym of --reset-author-date")),
> 
> It is merely hidden but still supported.
> 
>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>> index 0ede2b8900..5b8963272a 100755
>> --- a/t/t3436-rebase-more-options.sh
>> +++ b/t/t3436-rebase-more-options.sh
>> @@ -117,53 +117,61 @@ test_ctime_is_ignored () {
>>  	! grep -v +0000 authortime
>>  }
>>  
>> -test_expect_success '--ignore-date works with apply backend' '
>> +test_expect_success '--reset-author-date works with apply backend' '
>>  	git commit --amend --date="$GIT_AUTHOR_DATE" &&
>> -	git rebase --apply --ignore-date HEAD^ &&
>> +	git rebase --apply --reset-author-date HEAD^ &&
>>  	test_ctime_is_ignored -1
>>  '
> 
> Are there still some tests that check "--ignore-date"?  We probably
> should have them, if we are not removing the support.

This patch converts the existing --ignore-date tests to use
--reset-author-date and adds a single new test at the end to check
--ignore-date

Best Wishes

Phillip

> 
> Thanks.  The entire series looked reasonable to me.
> 


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-26 14:43       ` Phillip Wood
  2020-06-26 16:03         ` Junio C Hamano
@ 2020-06-29 14:14         ` Đoàn Trần Công Danh
  2020-07-13 10:02           ` Phillip Wood
  1 sibling, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-06-29 14:14 UTC (permalink / raw)
  To: phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Phillip,

On 2020-06-26 15:43:00+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> > > +	if (options.type == REBASE_APPLY) {
> > > +		if (ignore_whitespace)
> > > +			argv_array_push (&options.git_am_opts,
> > > +					 "--ignore-whitespace");
> > > +	} else if (ignore_whitespace) {
> > > +			string_list_append (&strategy_options,
> > > +					    "ignore-space-change");
> > > +	}
> > > +
> > 
> > Hm, I've just noticed this by now.
> > Would it's better if we rewrite it as:
> > 
> > 	if (ignore_whitespace) {
> > 		if (options.type == REBASE_APPLY)
> > 			argv_array_push(&options.git_am_opts,
> > 					"--ignore-whitespace");
> > 		else
> > 			string_list_append(&strategy_options,
> > 					   "ignore-space-change");
> > 	}
> > 
> > Ah, the incoming patches will add more conditions into the:
> > 
> > 	if (options.type == REBASE_APPLY)
> > 
> > I'm still not convinced, though.
> 
> I wanted to keep the subsequent patches as simple as possible. Having to
> rewrite the if statement in the next patch just clutters it up and makes the
> real changes introduced by that patch less obvious

I think the code suggested by Junio may be cleaner ;)
I may write as:

	if (ignore_whitespace) {
		if (options.type == REBASE_APPLY)
			argv_array_push(...)
		else
			string_list_append(...)
	}

	if (other_condition)
		do_something_else(...)

I don't know if it's cleaner or not.
I haven't tried applied it into real code.

> > Anyway, IIRC, --ignore-whitespace and --ignore-space-change has the
> > same meaning, I think it's better to use the same option for both
> > legs, no?
> > 
> > I can understand the decision to use --ignore-whitespace as keeping
> > the pass-through behavior of old code, but I think future maintenance
> > is more important than that.
> 
> I'm not sure how it affects future maintenance. The two different options
> are for two different commands so I'm not sure it is worth the effort

I vaguely remember I was thinking about same option text in both leg
would make the code easier for reasoning. And we can unify the
recommendation for both backend. We will never strip
--ignore-whitespace from git-apply, but it would be easier to always
answer: "--ignore-space-change should be used to ignore space" when
someone asks about it.

Typing this now makes me wonder if we should teach --ignore-space-change to
git-rebase?

Thanks,

-- Danh

> 
> Best Wishes
> 
> Phillip
> 
> > I've tried changing ignore-whitespace to ignore-space-change and run
> > make test
> > 
> > It looks good to me (aka nothing failed _in my machine_),
> > 4/5 and 5/5 is not applied, though.
> > 
> > >   	if (strategy_options.nr) {
> > >   		int i;
> > > diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> > > index 50e7960702..55ca46786d 100755
> > > --- a/t/t3422-rebase-incompatible-options.sh
> > > +++ b/t/t3422-rebase-incompatible-options.sh
> > > @@ -61,7 +61,6 @@ test_rebase_am_only () {
> > >   }
> > >   test_rebase_am_only --whitespace=fix
> > > -test_rebase_am_only --ignore-whitespace
> > >   test_rebase_am_only --committer-date-is-author-date
> > >   test_rebase_am_only -C4
> > > diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> > > new file mode 100755
> > > index 0000000000..4f8a6e51c9
> > > --- /dev/null
> > > +++ b/t/t3436-rebase-more-options.sh
> > > @@ -0,0 +1,60 @@
> > > +#!/bin/sh
> > > +#
> > > +# Copyright (c) 2019 Rohit Ashiwal
> > > +#
> > > +
> > > +test_description='tests to ensure compatibility between am and interactive backends'
> > > +
> > > +. ./test-lib.sh
> > > +
> > > +. "$TEST_DIRECTORY"/lib-rebase.sh
> > > +
> > > +# This is a special case in which both am and interactive backends
> > > +# provide the same output. It was done intentionally because
> > > +# both the backends fall short of optimal behaviour.
> > > +test_expect_success 'setup' '
> > > +	git checkout -b topic &&
> > > +	test_write_lines "line 1" "	line 2" "line 3" >file &&
> > > +	git add file &&
> > > +	git commit -m "add file" &&
> > > +
> > > +	test_write_lines "line 1" "new line 2" "line 3" >file &&
> > > +	git commit -am "update file" &&
> > > +	git tag side &&
> > > +
> > > +	git checkout --orphan master &&
> > > +	test_write_lines "line 1" "        line 2" "line 3" >file &&
> > > +	git commit -am "add file" &&
> > > +	git tag main
> > > +'
> > > +
> > > +test_expect_success '--ignore-whitespace works with apply backend' '
> > > +	test_must_fail git rebase --apply main side &&
> > > +	git rebase --abort &&
> > > +	git rebase --apply --ignore-whitespace main side &&
> > > +	git diff --exit-code side
> > > +'
> > > +
> > > +test_expect_success '--ignore-whitespace works with merge backend' '
> > > +	test_must_fail git rebase --merge main side &&
> > > +	git rebase --abort &&
> > > +	git rebase --merge --ignore-whitespace main side &&
> > > +	git diff --exit-code side
> > > +'
> > > +
> > > +test_expect_success '--ignore-whitespace is remembered when continuing' '
> > > +	(
> > > +		set_fake_editor &&
> > > +		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
> > > +			main side &&
> > > +		git rebase --continue
> > > +	) &&
> > > +	git diff --exit-code side
> > > +'
> > > +
> > > +# This must be the last test in this file
> > > +test_expect_success '$EDITOR and friends are unchanged' '
> > > +	test_editor_unchanged
> > > +'
> > > +
> > > +test_done
> > > -- 
> > > 2.27.0
> > > 
> > 

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag
  2020-06-29 14:14         ` Đoàn Trần Công Danh
@ 2020-07-13 10:02           ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-13 10:02 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 29/06/2020 15:14, Đoàn Trần Công Danh wrote:
> Hi Phillip,
> 
> On 2020-06-26 15:43:00+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>>>> +	if (options.type == REBASE_APPLY) {
>>>> +		if (ignore_whitespace)
>>>> +			argv_array_push (&options.git_am_opts,
>>>> +					 "--ignore-whitespace");
>>>> +	} else if (ignore_whitespace) {
>>>> +			string_list_append (&strategy_options,
>>>> +					    "ignore-space-change");
>>>> +	}
>>>> +
>>>
>>> Hm, I've just noticed this by now.
>>> Would it's better if we rewrite it as:
>>>
>>> 	if (ignore_whitespace) {
>>> 		if (options.type == REBASE_APPLY)
>>> 			argv_array_push(&options.git_am_opts,
>>> 					"--ignore-whitespace");
>>> 		else
>>> 			string_list_append(&strategy_options,
>>> 					   "ignore-space-change");
>>> 	}
>>>
>>> Ah, the incoming patches will add more conditions into the:
>>>
>>> 	if (options.type == REBASE_APPLY)
>>>
>>> I'm still not convinced, though.
>>
>> I wanted to keep the subsequent patches as simple as possible. Having to
>> rewrite the if statement in the next patch just clutters it up and makes the
>> real changes introduced by that patch less obvious
> 
> I think the code suggested by Junio may be cleaner ;)

Yes, I'll reroll with Junio's suggestion

> I may write as:
> 
> 	if (ignore_whitespace) {
> 		if (options.type == REBASE_APPLY)
> 			argv_array_push(...)
> 		else
> 			string_list_append(...)
> 	}
> 
> 	if (other_condition)
> 		do_something_else(...)
> 
> I don't know if it's cleaner or not.

It leads to a lot of repetition of ' && options.type == REBASE_APPLY' as
all the other conditions apart from --ignore-whitespace only need
handling for the apply backend here.

> I haven't tried applied it into real code.
> 
>>> Anyway, IIRC, --ignore-whitespace and --ignore-space-change has the
>>> same meaning, I think it's better to use the same option for both
>>> legs, no?
>>>
>>> I can understand the decision to use --ignore-whitespace as keeping
>>> the pass-through behavior of old code, but I think future maintenance
>>> is more important than that.
>>
>> I'm not sure how it affects future maintenance. The two different options
>> are for two different commands so I'm not sure it is worth the effort
> 
> I vaguely remember I was thinking about same option text in both leg
> would make the code easier for reasoning. And we can unify the
> recommendation for both backend. We will never strip
> --ignore-whitespace from git-apply, but it would be easier to always
> answer: "--ignore-space-change should be used to ignore space" when
> someone asks about it.
> 
> Typing this now makes me wonder if we should teach --ignore-space-change to
> git-rebase?

Possibly but not as part of this series which is about improving the
merge backend rather than adding new options to rebase itself

Best Wishes

Phillip

> 
> Thanks,
> 
> -- Danh
> 
>>
>> Best Wishes
>>
>> Phillip
>>
>>> I've tried changing ignore-whitespace to ignore-space-change and run
>>> make test
>>>
>>> It looks good to me (aka nothing failed _in my machine_),
>>> 4/5 and 5/5 is not applied, though.
>>>
>>>>   	if (strategy_options.nr) {
>>>>   		int i;
>>>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>>>> index 50e7960702..55ca46786d 100755
>>>> --- a/t/t3422-rebase-incompatible-options.sh
>>>> +++ b/t/t3422-rebase-incompatible-options.sh
>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>>>   }
>>>>   test_rebase_am_only --whitespace=fix
>>>> -test_rebase_am_only --ignore-whitespace
>>>>   test_rebase_am_only --committer-date-is-author-date
>>>>   test_rebase_am_only -C4
>>>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>>>> new file mode 100755
>>>> index 0000000000..4f8a6e51c9
>>>> --- /dev/null
>>>> +++ b/t/t3436-rebase-more-options.sh
>>>> @@ -0,0 +1,60 @@
>>>> +#!/bin/sh
>>>> +#
>>>> +# Copyright (c) 2019 Rohit Ashiwal
>>>> +#
>>>> +
>>>> +test_description='tests to ensure compatibility between am and interactive backends'
>>>> +
>>>> +. ./test-lib.sh
>>>> +
>>>> +. "$TEST_DIRECTORY"/lib-rebase.sh
>>>> +
>>>> +# This is a special case in which both am and interactive backends
>>>> +# provide the same output. It was done intentionally because
>>>> +# both the backends fall short of optimal behaviour.
>>>> +test_expect_success 'setup' '
>>>> +	git checkout -b topic &&
>>>> +	test_write_lines "line 1" "	line 2" "line 3" >file &&
>>>> +	git add file &&
>>>> +	git commit -m "add file" &&
>>>> +
>>>> +	test_write_lines "line 1" "new line 2" "line 3" >file &&
>>>> +	git commit -am "update file" &&
>>>> +	git tag side &&
>>>> +
>>>> +	git checkout --orphan master &&
>>>> +	test_write_lines "line 1" "        line 2" "line 3" >file &&
>>>> +	git commit -am "add file" &&
>>>> +	git tag main
>>>> +'
>>>> +
>>>> +test_expect_success '--ignore-whitespace works with apply backend' '
>>>> +	test_must_fail git rebase --apply main side &&
>>>> +	git rebase --abort &&
>>>> +	git rebase --apply --ignore-whitespace main side &&
>>>> +	git diff --exit-code side
>>>> +'
>>>> +
>>>> +test_expect_success '--ignore-whitespace works with merge backend' '
>>>> +	test_must_fail git rebase --merge main side &&
>>>> +	git rebase --abort &&
>>>> +	git rebase --merge --ignore-whitespace main side &&
>>>> +	git diff --exit-code side
>>>> +'
>>>> +
>>>> +test_expect_success '--ignore-whitespace is remembered when continuing' '
>>>> +	(
>>>> +		set_fake_editor &&
>>>> +		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
>>>> +			main side &&
>>>> +		git rebase --continue
>>>> +	) &&
>>>> +	git diff --exit-code side
>>>> +'
>>>> +
>>>> +# This must be the last test in this file
>>>> +test_expect_success '$EDITOR and friends are unchanged' '
>>>> +	test_editor_unchanged
>>>> +'
>>>> +
>>>> +test_done
>>>> -- 
>>>> 2.27.0
>>>>
>>>
> 


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v6 0/5] fixup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (11 preceding siblings ...)
  2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
@ 2020-07-13 10:10 ` Phillip Wood
  2020-07-13 10:10   ` [PATCH v6 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
                     ` (5 more replies)
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
  2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
  14 siblings, 6 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-13 10:10 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Thanks for the comments on the last round, I've modified the
controversial conditional in the first patch as suggested by Junio and
updated patch 4 as suggested as well

Best Wishes

Phillip

Phillip Wood (2):
  rebase -i: support --committer-date-is-author-date
  rebase -i: support --ignore-date

Rohit Ashiwal (3):
  rebase -i: add --ignore-whitespace flag
  sequencer: rename amend_author to author_to_free
  rebase: add --reset-author-date

 Documentation/git-rebase.txt           |  33 ++++-
 builtin/rebase.c                       |  47 +++++--
 sequencer.c                            | 112 ++++++++++++++-
 sequencer.h                            |   2 +
 t/t3422-rebase-incompatible-options.sh |   2 -
 t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++
 6 files changed, 353 insertions(+), 23 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

Range-diff against v5:
1:  43ee10d4d5 ! 1:  5bb4226007 rebase -i: add --ignore-whitespace flag
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      
     +	if (options.type == REBASE_APPLY) {
     +		if (ignore_whitespace)
    -+			argv_array_push (&options.git_am_opts,
    -+					 "--ignore-whitespace");
    -+	} else if (ignore_whitespace) {
    -+			string_list_append (&strategy_options,
    -+					    "ignore-space-change");
    ++			argv_array_push(&options.git_am_opts,
    ++					"--ignore-whitespace");
    ++	} else {
    ++		/* REBASE_MERGE and PRESERVE_MERGES */
    ++		if (ignore_whitespace) {
    ++			string_list_append(&strategy_options,
    ++					   "ignore-space-change");
    ++		}
     +	}
     +
      	if (strategy_options.nr) {
2:  a2b57df19c ! 2:  e5fdb574ed rebase -i: support --committer-date-is-author-date
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      			allow_preemptive_ff = 0;
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
      		if (ignore_whitespace)
    - 			argv_array_push (&options.git_am_opts,
    - 					 "--ignore-whitespace");
    + 			argv_array_push(&options.git_am_opts,
    + 					"--ignore-whitespace");
     +		if (options.committer_date_is_author_date)
     +			argv_array_push(&options.git_am_opts,
     +					"--committer-date-is-author-date");
    - 	} else if (ignore_whitespace) {
    - 			string_list_append (&strategy_options,
    - 					    "ignore-space-change");
    + 	} else {
    + 		/* REBASE_MERGE and PRESERVE_MERGES */
    + 		if (ignore_whitespace) {
     
      ## sequencer.c ##
     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
3:  363a0140ad = 3:  cf5c9a2456 sequencer: rename amend_author to author_to_free
4:  46d9e108be ! 4:  0fc90eaff1 rebase -i: support --ignore-date
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
     -		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
     -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
     +		OPT_BOOL(0, "ignore-date", &options.ignore_date,
    -+			 "ignore author date and use current date"),
    ++			 N_("ignore author date and use current date")),
      		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
      				  N_("passed to 'git apply'"), 0),
      		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      					"--committer-date-is-author-date");
     +		if (options.ignore_date)
     +			argv_array_push(&options.git_am_opts, "--ignore-date");
    - 	} else if (ignore_whitespace) {
    - 			string_list_append (&strategy_options,
    - 					    "ignore-space-change");
    + 	} else {
    + 		/* REBASE_MERGE and PRESERVE_MERGES */
    + 		if (ignore_whitespace) {
     
      ## sequencer.c ##
     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
    @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr
     +/* Construct a free()able author string with current time as the author date */
     +static char *ignore_author_date(const char *author)
     +{
    -+	int len = strlen(author);
    ++	int len;
     +	struct ident_split ident;
     +	struct strbuf new_author = STRBUF_INIT;
     +
    -+	if (split_ident_line(&ident, author, len) < 0) {
    ++	if (split_ident_line(&ident, author, strlen(author)) < 0) {
     +		error(_("malformed ident line '%s'"), author);
     +		return NULL;
     +	}
5:  26d5eefdcb ! 5:  21cf5e5512 rebase: add --reset-author-date
    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
      			 &options.committer_date_is_author_date,
      			 N_("make committer date match author date")),
     -		OPT_BOOL(0, "ignore-date", &options.ignore_date,
    --			 "ignore author date and use current date"),
     +		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
    -+			 N_("ignore author date and use current date")),
    + 			 N_("ignore author date and use current date")),
     +		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
     +				N_("synonym of --reset-author-date")),
      		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
-- 
2.27.0


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v6 1/5] rebase -i: add --ignore-whitespace flag
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
@ 2020-07-13 10:10   ` Phillip Wood
  2020-07-13 10:10   ` [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-13 10:10 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--ignore-whitespace option to the merge backend. This option treats
lines with only whitespace changes as unchanged and is implemented in
the merge backend by translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 19 +++++++-
 builtin/rebase.c                       | 19 ++++++--
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++
 4 files changed, 93 insertions(+), 6 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f7a6033607..b003784f01 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Ignore whitespace differences when trying to reconcile
+differences. Currently, each backend implements an approximation of
+this behavior:
++
+apply backend: When applying a patch, ignore changes in whitespace in
+context lines. Unfortunately, this means that if the "old" lines being
+replaced by the patch differ only in whitespace from the existing
+file, you will get a merge conflict instead of a successful patch
+application.
++
+merge backend: Treat lines with only whitespace changes as unchanged
+when merging. Unfortunately, this means that any patch hunks that were
+intended to modify whitespace and nothing else will be dropped, even
+if the other side had no changes that conflicted.
+
 --whitespace=<option>::
-	These flags are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 	Implies --apply.
 +
@@ -572,7 +587,6 @@ The following options:
  * --apply
  * --committer-date-is-author-date
  * --ignore-date
- * --ignore-whitespace
  * --whitespace
  * -C
 
@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 27a07d4e78..bd93e9742c 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
 		parse_strategy_opts(&replay, opts->strategy_opts);
 
@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct strbuf revisions = STRBUF_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id merge_base;
+	int ignore_whitespace = 0;
 	enum action action = ACTION_NONE;
 	const char *gpg_sign = NULL;
 	struct string_list exec = STRING_LIST_INIT_NODUP;
@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		imply_merge(&options, "--rebase-merges");
 	}
 
+	if (options.type == REBASE_APPLY) {
+		if (ignore_whitespace)
+			argv_array_push(&options.git_am_opts,
+					"--ignore-whitespace");
+	} else {
+		/* REBASE_MERGE and PRESERVE_MERGES */
+		if (ignore_whitespace) {
+			string_list_append(&strategy_options,
+					   "ignore-space-change");
+		}
+	}
+
 	if (strategy_options.nr) {
 		int i;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
new file mode 100755
index 0000000000..4f8a6e51c9
--- /dev/null
+++ b/t/t3436-rebase-more-options.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	test_write_lines "line 1" "	line 2" "line 3" >file &&
+	git add file &&
+	git commit -m "add file" &&
+
+	test_write_lines "line 1" "new line 2" "line 3" >file &&
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	test_write_lines "line 1" "        line 2" "line 3" >file &&
+	git commit -am "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with apply backend' '
+	test_must_fail git rebase --apply main side &&
+	git rebase --abort &&
+	git rebase --apply --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace works with merge backend' '
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
+			main side &&
+		git rebase --continue
+	) &&
+	git diff --exit-code side
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
+test_done
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
  2020-07-13 10:10   ` [PATCH v6 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-07-13 10:10   ` Phillip Wood
  2020-07-15 14:27     ` Đoàn Trần Công Danh
  2020-07-13 10:10   ` [PATCH v6 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-07-13 10:10 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--committer-date-is-author-date option to the merge backend. This
option uses the author date of the commit that is being rewritten as
the committer date when the new commit is created.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 10 +++--
 builtin/rebase.c                       | 17 +++++---
 sequencer.c                            | 60 +++++++++++++++++++++++++-
 sequencer.h                            |  1 +
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++++++++++-
 6 files changed, 136 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b003784f01..dfa70263e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of using the current time as the committer date, use
+	the author date of the commit being rebased as the committer
+	date. This option implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index bd93e9742c..2579380729 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -88,6 +88,7 @@ struct rebase_options {
 	int autosquash;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (ignore_whitespace)
 			argv_array_push(&options.git_am_opts,
 					"--ignore-whitespace");
+		if (options.committer_date_is_author_date)
+			argv_array_push(&options.git_am_opts,
+					"--committer-date-is-author-date");
 	} else {
 		/* REBASE_MERGE and PRESERVE_MERGES */
 		if (ignore_whitespace) {
diff --git a/sequencer.c b/sequencer.c
index 6fd2674632..368d397970 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -872,6 +873,22 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+static const char *author_date_from_env_array(const struct argv_array *env)
+{
+	int i;
+	const char *date;
+
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
 			     gpg_opt, gpg_opt);
 	}
 
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 author_date_from_env_array(&cmd.env_array));
+
 	argv_array_push(&cmd.args, "commit");
 
 	if (!(flags & VERIFY_MSG))
@@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
+			res = error(_("malformed ident line '%s'"), author);
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin),
+			    ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin),
+			    ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
 	if (opts->keep_redundant_commits)
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
 			goto leave_merge;
 		}
 
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 author_date_from_env_array(&cmd.env_array));
+
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
 		argv_array_push(&cmd.args, "-s");
@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 0bee85093e..4ab94119ae 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -45,6 +45,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 4f8a6e51c9..50a63d8ebe 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -21,11 +24,20 @@ test_expect_success 'setup' '
 	test_write_lines "line 1" "new line 2" "line 3" >file &&
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	rm foo &&
 	test_write_lines "line 1" "        line 2" "line 3" >file &&
 	git commit -am "add file" &&
-	git tag main
+	git tag main &&
+
+	mkdir test-bin &&
+	write_script test-bin/git-merge-test <<-\EOF
+	exec git-merge-recursive "$@"
+	EOF
 '
 
 test_expect_success '--ignore-whitespace works with apply backend' '
@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
 	git diff --exit-code side
 '
 
+test_ctime_is_atime () {
+	git log $1 --format=%ai >authortime &&
+	git log $1 --format=%ci >committertime &&
+	test_cmp authortime committertime
+}
+
+test_expect_success '--committer-date-is-author-date works with apply backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase --apply --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with merge backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase -m --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
+					--committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -1
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v6 3/5] sequencer: rename amend_author to author_to_free
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
  2020-07-13 10:10   ` [PATCH v6 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-07-13 10:10   ` [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-07-13 10:10   ` Phillip Wood
  2020-07-13 10:10   ` [PATCH v6 4/5] rebase -i: support --ignore-date Phillip Wood
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-13 10:10 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() when amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 368d397970..29f6d1bc39 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1474,7 +1474,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v6 4/5] rebase -i: support --ignore-date
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
                     ` (2 preceding siblings ...)
  2020-07-13 10:10   ` [PATCH v6 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
@ 2020-07-13 10:10   ` Phillip Wood
  2020-07-13 10:10   ` [PATCH v6 5/5] rebase: add --reset-author-date Phillip Wood
  2020-07-13 15:28   ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-13 10:10 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the --ignore-date
option to the merge backend. This option uses the current time as the
author date rather than reusing the original author date when
rewriting commits. We take care to handle the combination of
--ignore-date and --committer-date-is-author-date in the same way as
the apply backend.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt   |  7 +++--
 builtin/rebase.c               | 13 +++++---
 sequencer.c                    | 50 ++++++++++++++++++++++++++++--
 sequencer.h                    |  1 +
 t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index dfa70263e6..e2717e20e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the author date of the original commit, use
+	the current time as the	author date of the rebased commit.  This
+	option implies `--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --ignore-date
  * --whitespace
  * -C
 
@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 2579380729..583ac96fc7 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -89,6 +89,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date || options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
 		else if (skip_prefix(option, "-C", &p)) {
@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (options.committer_date_is_author_date)
 			argv_array_push(&options.git_am_opts,
 					"--committer-date-is-author-date");
+		if (options.ignore_date)
+			argv_array_push(&options.git_am_opts, "--ignore-date");
 	} else {
 		/* REBASE_MERGE and PRESERVE_MERGES */
 		if (ignore_whitespace) {
diff --git a/sequencer.c b/sequencer.c
index 29f6d1bc39..c140162cbd 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
 	BUG("GIT_AUTHOR_DATE missing from author script");
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len;
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, strlen(author)) < 0) {
+		error(_("malformed ident line '%s'"), author);
+		return NULL;
+	}
+
+	len = ident.mail_end - ident.name_begin + 1;
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
 
 	if (opts->committer_date_is_author_date)
 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
 				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,
 			    ident.date_begin,
 			    (int)(ident.tz_end - ident.tz_begin),
 			    ident.tz_begin);
-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
 		strbuf_release(&date);
 
 		if (res)
@@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
+
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,
 
 		if (opts->committer_date_is_author_date)
 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
 					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 4ab94119ae..3587878e3b 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -46,6 +46,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 50a63d8ebe..0ede2b8900 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 	test_ctime_is_atime -1
 '
 
+# Checking for +0000 in the author date is sufficient since the
+# default timezone is UTC but the timezone used while committing is
+# +0530. The inverted logic in the grep is necessary to check all the
+# author dates in the file.
+test_ctime_is_ignored () {
+	git log $1 --format=%ai >authortime &&
+	! grep -v +0000 authortime
+}
+
+test_expect_success '--ignore-date works with apply backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with merge backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -m HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -m \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	test_ctime_is_ignored
+'
+
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -2 &&
+	test_ctime_is_ignored -2
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
+				--ignore-date --committer-date-is-author-date \
+				side side &&
+	test_ctime_is_atime -1 &&
+	test_ctime_is_ignored -1
+ '
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v6 5/5] rebase: add --reset-author-date
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
                     ` (3 preceding siblings ...)
  2020-07-13 10:10   ` [PATCH v6 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-07-13 10:10   ` Phillip Wood
  2020-07-13 15:28   ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Junio C Hamano
  5 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-13 10:10 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The previous commit introduced --ignore-date flag to rebase -i, but the
name is rather vague as it does not say whether the author date or the
committer date is ignored. Add an alias to convey the precise purpose.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt   |  1 +
 builtin/rebase.c               |  4 +++-
 t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e2717e20e6..a5f82913fb 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the author date of the original commit, use
 	the current time as the	author date of the rebased commit.  This
 	option implies `--force-rebase`.
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 583ac96fc7..b126fbe940 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
 			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 0ede2b8900..5b8963272a 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -117,53 +117,61 @@ test_ctime_is_ignored () {
 	! grep -v +0000 authortime
 }
 
-test_expect_success '--ignore-date works with apply backend' '
+test_expect_success '--reset-author-date works with apply backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --apply --ignore-date HEAD^ &&
+	git rebase --apply --reset-author-date HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with merge backend' '
+test_expect_success '--reset-author-date works with merge backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --ignore-date -m HEAD^ &&
+	git rebase --reset-author-date -m HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works after conflict resolution' '
-	test_must_fail git rebase --ignore-date -m \
+test_expect_success '--reset-author-date works after conflict resolution' '
+	test_must_fail git rebase --reset-author-date -m \
 		--onto commit2^^ commit2^ commit2 &&
 	echo resolved >foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with rebase -r' '
+test_expect_success '--reset-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
-	git rebase -r --root --ignore-date &&
+	git rebase -r --root --reset-author-date &&
 	test_ctime_is_ignored
 '
 
-test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
 	test_must_fail git rebase -m --committer-date-is-author-date \
-		--ignore-date --onto commit2^^ commit2^ commit3 &&
+		--reset-author-date --onto commit2^^ commit2^ commit3 &&
 	git checkout --theirs foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_atime -2 &&
 	test_ctime_is_ignored -2
 '
 
-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
 	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
 		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
-				--ignore-date --committer-date-is-author-date \
-				side side &&
+				--reset-author-date \
+				--committer-date-is-author-date side side &&
 	test_ctime_is_atime -1 &&
 	test_ctime_is_ignored -1
  '
 
+test_expect_success '--ignore-date is an alias for --reset-author-date' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
+	git rebase -m --ignore-date HEAD^ &&
+	test_ctime_is_ignored -2
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 0/5] fixup ra/rebase-i-more-options
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
                     ` (4 preceding siblings ...)
  2020-07-13 10:10   ` [PATCH v6 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-07-13 15:28   ` Junio C Hamano
  2020-07-15  8:55     ` Phillip Wood
  5 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-07-13 15:28 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> Phillip Wood (2):
>   rebase -i: support --committer-date-is-author-date
>   rebase -i: support --ignore-date
>
> Rohit Ashiwal (3):
>   rebase -i: add --ignore-whitespace flag
>   sequencer: rename amend_author to author_to_free
>   rebase: add --reset-author-date

Thanks for polishing them further.

Will queue; with help from others, this can be one of the early
topics to be merged after 2.28 gets tagged, hopefully?

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 0/5] fixup ra/rebase-i-more-options
  2020-07-13 15:28   ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Junio C Hamano
@ 2020-07-15  8:55     ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-15  8:55 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

On 13/07/2020 16:28, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>> Phillip Wood (2):
>>    rebase -i: support --committer-date-is-author-date
>>    rebase -i: support --ignore-date
>>
>> Rohit Ashiwal (3):
>>    rebase -i: add --ignore-whitespace flag
>>    sequencer: rename amend_author to author_to_free
>>    rebase: add --reset-author-date
> 
> Thanks for polishing them further.
> 
> Will queue; with help from others, this can be one of the early
> topics to be merged after 2.28 gets tagged, hopefully?

Yes I hope so, I'm not aware of any outstanding issues (lets see if the 
reviewers agree)

Best Wishes

Phillip


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-13 10:10   ` [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-07-15 14:27     ` Đoàn Trần Công Danh
  2020-07-16  8:23       ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-07-15 14:27 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List


Hi Phillip,

On 2020-07-13 11:10:42+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index bd93e9742c..2579380729 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -88,6 +88,7 @@ struct rebase_options {
>  	int autosquash;
>  	char *gpg_sign_opt;
>  	int autostash;
> +	int committer_date_is_author_date;
>  	char *cmd;
>  	int allow_empty_message;
>  	int rebase_merges, rebase_cousins;
> @@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
>  	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
>  	replay.verbose = opts->flags & REBASE_VERBOSE;
>  	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
> +	replay.committer_date_is_author_date =
> +					opts->committer_date_is_author_date;
>  	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
>  	replay.strategy = opts->strategy;
>  
> @@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
>  		OPT_BOOL(0, "signoff", &options.signoff,
>  			 N_("add a Signed-off-by: line to each commit")),
> -		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
> -				  &options.git_am_opts, NULL,
> -				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
> +		OPT_BOOL(0, "committer-date-is-author-date",
> +			 &options.committer_date_is_author_date,
> +			 N_("make committer date match author date")),
>  		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
>  				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
>  		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
> @@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  	    options.autosquash) {
>  		allow_preemptive_ff = 0;
>  	}
> +	if (options.committer_date_is_author_date)
> +		options.flags |= REBASE_FORCE;
>  
>  	for (i = 0; i < options.git_am_opts.argc; i++) {
>  		const char *option = options.git_am_opts.argv[i], *p;
> -		if (!strcmp(option, "--committer-date-is-author-date") ||
> -		    !strcmp(option, "--ignore-date") ||
> +		if (!strcmp(option, "--ignore-date") ||
>  		    !strcmp(option, "--whitespace=fix") ||
>  		    !strcmp(option, "--whitespace=strip"))
>  			allow_preemptive_ff = 0;
> @@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		if (ignore_whitespace)
>  			argv_array_push(&options.git_am_opts,
>  					"--ignore-whitespace");
> +		if (options.committer_date_is_author_date)
> +			argv_array_push(&options.git_am_opts,
> +					"--committer-date-is-author-date");
>  	} else {
>  		/* REBASE_MERGE and PRESERVE_MERGES */
>  		if (ignore_whitespace) {
> diff --git a/sequencer.c b/sequencer.c
> index 6fd2674632..368d397970 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
>   * command-line.
>   */
>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
>  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
>  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
>  static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
> @@ -872,6 +873,22 @@ static char *get_author(const char *message)
>  	return NULL;
>  }
>  
> +static const char *author_date_from_env_array(const struct argv_array *env)
> +{
> +	int i;
> +	const char *date;
> +
> +	for (i = 0; i < env->argc; i++)
> +		if (skip_prefix(env->argv[i],
> +				"GIT_AUTHOR_DATE=", &date))
> +			return date;
> +	/*
> +	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
> +	 * reading the script
> +	 */
> +	BUG("GIT_AUTHOR_DATE missing from author script");
> +}
> +
>  static const char staged_changes_advice[] =
>  N_("you have staged changes in your working tree\n"
>  "If these changes are meant to be squashed into the previous commit, run:\n"
> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
>  			     gpg_opt, gpg_opt);
>  	}
>  
> +	if (opts->committer_date_is_author_date)
> +		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +				 author_date_from_env_array(&cmd.env_array));
> +
>  	argv_array_push(&cmd.args, "commit");
>  
>  	if (!(flags & VERIFY_MSG))
> @@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,
>  		commit_list_insert(current_head, &parents);
>  	}
>  
> +	if (opts->committer_date_is_author_date) {
> +		struct ident_split ident;
> +		struct strbuf date = STRBUF_INIT;
> +
> +		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
> +			res = error(_("malformed ident line '%s'"), author);

I've checked with the translation for my native language (vi).
The translators seem to misread ident (as in identity) as
indent (as in indentation).

The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:

	#~ msgid "malformed ident line"
	#~ msgstr "thụt đầu dòng dị hình"

Translating back to English, it reads: "malformed indentation".

Hence, I think it would read better if we write:

	res = error(_("malformed identity line '%s'"), author);

3 more characters is not that much :)

> +			goto out;
> +		}
> +		if (!ident.date_begin) {
> +			res = error(_("corrupted author without date information"));
> +			goto out;
> +		}
> +
> +		strbuf_addf(&date, "@%.*s %.*s",
> +			    (int)(ident.date_end - ident.date_begin),
> +			    ident.date_begin,
> +			    (int)(ident.tz_end - ident.tz_begin),
> +			    ident.tz_begin);
> +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		strbuf_release(&date);
> +
> +		if (res)
> +			goto out;
> +	}
> +
>  	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>  		res = error(_("git write-tree failed to write a tree"));
>  		goto out;
> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
>  			opts->signoff = 1;
>  		}
>  
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>  		if (file_exists(rebase_path_reschedule_failed_exec()))
>  			opts->reschedule_failed_exec = 1;
>  
> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>  		write_file(rebase_path_drop_redundant_commits(), "%s", "");
>  	if (opts->keep_redundant_commits)
>  		write_file(rebase_path_keep_redundant_commits(), "%s", "");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>  	if (opts->reschedule_failed_exec)
>  		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>  
> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
>  			goto leave_merge;
>  		}
>  
> +		if (opts->committer_date_is_author_date)
> +			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +					 author_date_from_env_array(&cmd.env_array));
> +
>  		cmd.git_cmd = 1;
>  		argv_array_push(&cmd.args, "merge");
>  		argv_array_push(&cmd.args, "-s");
> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
>  	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>  	if (opts->allow_ff)
>  		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>  	if (read_and_refresh_cache(r, opts))
>  		return -1;
>  
> diff --git a/sequencer.h b/sequencer.h
> index 0bee85093e..4ab94119ae 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -45,6 +45,7 @@ struct replay_opts {
>  	int verbose;
>  	int quiet;
>  	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>  
>  	int mainline;
>  
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 55ca46786d..c8234062c6 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>  
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>  
>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 4f8a6e51c9..50a63d8ebe 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>  
>  . "$TEST_DIRECTORY"/lib-rebase.sh
>  
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>  # This is a special case in which both am and interactive backends
>  # provide the same output. It was done intentionally because
>  # both the backends fall short of optimal behaviour.
> @@ -21,11 +24,20 @@ test_expect_success 'setup' '
>  	test_write_lines "line 1" "new line 2" "line 3" >file &&
>  	git commit -am "update file" &&
>  	git tag side &&
> +	test_commit commit1 foo foo1 &&
> +	test_commit commit2 foo foo2 &&
> +	test_commit commit3 foo foo3 &&
>  
>  	git checkout --orphan master &&
> +	rm foo &&
>  	test_write_lines "line 1" "        line 2" "line 3" >file &&
>  	git commit -am "add file" &&
> -	git tag main
> +	git tag main &&
> +
> +	mkdir test-bin &&
> +	write_script test-bin/git-merge-test <<-\EOF
> +	exec git-merge-recursive "$@"
> +	EOF
>  '
>  
>  test_expect_success '--ignore-whitespace works with apply backend' '
> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
>  	git diff --exit-code side
>  '
>  
> +test_ctime_is_atime () {
> +	git log $1 --format=%ai >authortime &&
> +	git log $1 --format=%ci >committertime &&
> +	test_cmp authortime committertime
> +}
> +
> +test_expect_success '--committer-date-is-author-date works with apply backend' '
> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +	git rebase --apply --committer-date-is-author-date HEAD^ &&
> +	test_ctime_is_atime -1
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with merge backend' '
> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +	git rebase -m --committer-date-is-author-date HEAD^ &&
> +	test_ctime_is_atime -1
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
> +	git checkout side &&
> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +	git rebase -r --root --committer-date-is-author-date &&
> +	test_ctime_is_atime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when forking merge' '
> +	git checkout side &&
> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
> +					--committer-date-is-author-date &&
> +	test_ctime_is_atime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
> +	git checkout commit2 &&
> +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
> +	test_must_fail git rebase -m --committer-date-is-author-date \
> +		--onto HEAD^^ HEAD^ &&
> +	echo resolved > foo &&

Nitpick: no space after ">" :D

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-15 14:27     ` Đoàn Trần Công Danh
@ 2020-07-16  8:23       ` Phillip Wood
  2020-07-16 13:06         ` Đoàn Trần Công Danh
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-07-16  8:23 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, Phillip Wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 15/07/2020 15:27, Đoàn Trần Công Danh wrote:
> 
> Hi Phillip,
> 
> On 2020-07-13 11:10:42+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
 >> [...]
>>   
>> +	if (opts->committer_date_is_author_date) {
>> +		struct ident_split ident;
>> +		struct strbuf date = STRBUF_INIT;
>> +
>> +		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
>> +			res = error(_("malformed ident line '%s'"), author);
> 
> I've checked with the translation for my native language (vi).
> The translators seem to misread ident (as in identity) as
> indent (as in indentation).
> 
> The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:
> 
> 	#~ msgid "malformed ident line"
> 	#~ msgstr "thụt đầu dòng dị hình"
> 
> Translating back to English, it reads: "malformed indentation".
> 
> Hence, I think it would read better if we write:
> 
> 	res = error(_("malformed identity line '%s'"), author);
> 
> 3 more characters is not that much :)

Looking through the existing strings "invalid ident line: %.*s" is 
already used by am so maybe we should reuse that (log.c also contains 
"invalid ident line: %s"). Is the translation correct?

#: builtin/am.c:1270
#, c-format
msgid "invalid ident line: %.*s"
msgstr "dòng thụt lề không hợp lệ: %.*s"

Best Wishes

Phillip

> 
>> +			goto out;
>> +		}
>> +		if (!ident.date_begin) {
>> +			res = error(_("corrupted author without date information"));
>> +			goto out;
>> +		}
>> +
>> +		strbuf_addf(&date, "@%.*s %.*s",
>> +			    (int)(ident.date_end - ident.date_begin),
>> +			    ident.date_begin,
>> +			    (int)(ident.tz_end - ident.tz_begin),
>> +			    ident.tz_begin);
>> +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
>> +		strbuf_release(&date);
>> +
>> +		if (res)
>> +			goto out;
>> +	}
>> +
>>   	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>>   		res = error(_("git write-tree failed to write a tree"));
>>   		goto out;
>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
>>   			opts->signoff = 1;
>>   		}
>>   
>> +		if (file_exists(rebase_path_cdate_is_adate())) {
>> +			opts->allow_ff = 0;
>> +			opts->committer_date_is_author_date = 1;
>> +		}
>> +
>>   		if (file_exists(rebase_path_reschedule_failed_exec()))
>>   			opts->reschedule_failed_exec = 1;
>>   
>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>>   		write_file(rebase_path_drop_redundant_commits(), "%s", "");
>>   	if (opts->keep_redundant_commits)
>>   		write_file(rebase_path_keep_redundant_commits(), "%s", "");
>> +	if (opts->committer_date_is_author_date)
>> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>>   	if (opts->reschedule_failed_exec)
>>   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>>   
>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
>>   			goto leave_merge;
>>   		}
>>   
>> +		if (opts->committer_date_is_author_date)
>> +			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>> +					 author_date_from_env_array(&cmd.env_array));
>> +
>>   		cmd.git_cmd = 1;
>>   		argv_array_push(&cmd.args, "merge");
>>   		argv_array_push(&cmd.args, "-s");
>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
>>   	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>>   	if (opts->allow_ff)
>>   		assert(!(opts->signoff || opts->no_commit ||
>> -				opts->record_origin || opts->edit));
>> +				opts->record_origin || opts->edit ||
>> +				opts->committer_date_is_author_date));
>>   	if (read_and_refresh_cache(r, opts))
>>   		return -1;
>>   
>> diff --git a/sequencer.h b/sequencer.h
>> index 0bee85093e..4ab94119ae 100644
>> --- a/sequencer.h
>> +++ b/sequencer.h
>> @@ -45,6 +45,7 @@ struct replay_opts {
>>   	int verbose;
>>   	int quiet;
>>   	int reschedule_failed_exec;
>> +	int committer_date_is_author_date;
>>   
>>   	int mainline;
>>   
>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>> index 55ca46786d..c8234062c6 100755
>> --- a/t/t3422-rebase-incompatible-options.sh
>> +++ b/t/t3422-rebase-incompatible-options.sh
>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>   }
>>   
>>   test_rebase_am_only --whitespace=fix
>> -test_rebase_am_only --committer-date-is-author-date
>>   test_rebase_am_only -C4
>>   
>>   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>> index 4f8a6e51c9..50a63d8ebe 100755
>> --- a/t/t3436-rebase-more-options.sh
>> +++ b/t/t3436-rebase-more-options.sh
>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>>   
>>   . "$TEST_DIRECTORY"/lib-rebase.sh
>>   
>> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>> +export GIT_AUTHOR_DATE
>> +
>>   # This is a special case in which both am and interactive backends
>>   # provide the same output. It was done intentionally because
>>   # both the backends fall short of optimal behaviour.
>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '
>>   	test_write_lines "line 1" "new line 2" "line 3" >file &&
>>   	git commit -am "update file" &&
>>   	git tag side &&
>> +	test_commit commit1 foo foo1 &&
>> +	test_commit commit2 foo foo2 &&
>> +	test_commit commit3 foo foo3 &&
>>   
>>   	git checkout --orphan master &&
>> +	rm foo &&
>>   	test_write_lines "line 1" "        line 2" "line 3" >file &&
>>   	git commit -am "add file" &&
>> -	git tag main
>> +	git tag main &&
>> +
>> +	mkdir test-bin &&
>> +	write_script test-bin/git-merge-test <<-\EOF
>> +	exec git-merge-recursive "$@"
>> +	EOF
>>   '
>>   
>>   test_expect_success '--ignore-whitespace works with apply backend' '
>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
>>   	git diff --exit-code side
>>   '
>>   
>> +test_ctime_is_atime () {
>> +	git log $1 --format=%ai >authortime &&
>> +	git log $1 --format=%ci >committertime &&
>> +	test_cmp authortime committertime
>> +}
>> +
>> +test_expect_success '--committer-date-is-author-date works with apply backend' '
>> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>> +	git rebase --apply --committer-date-is-author-date HEAD^ &&
>> +	test_ctime_is_atime -1
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with merge backend' '
>> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>> +	git rebase -m --committer-date-is-author-date HEAD^ &&
>> +	test_ctime_is_atime -1
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
>> +	git checkout side &&
>> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>> +	git rebase -r --root --committer-date-is-author-date &&
>> +	test_ctime_is_atime
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works when forking merge' '
>> +	git checkout side &&
>> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>> +	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
>> +					--committer-date-is-author-date &&
>> +	test_ctime_is_atime
>> +'
>> +
>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
>> +	git checkout commit2 &&
>> +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
>> +	test_must_fail git rebase -m --committer-date-is-author-date \
>> +		--onto HEAD^^ HEAD^ &&
>> +	echo resolved > foo &&
> 
> Nitpick: no space after ">" :D
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-16  8:23       ` Phillip Wood
@ 2020-07-16 13:06         ` Đoàn Trần Công Danh
  2020-07-16 15:17           ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-07-16 13:06 UTC (permalink / raw)
  To: phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Phillip,

On 2020-07-16 09:23:17+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> >> [...]
> > > +	if (opts->committer_date_is_author_date) {
> > > +		struct ident_split ident;
> > > +		struct strbuf date = STRBUF_INIT;
> > > +
> > > +		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
> > > +			res = error(_("malformed ident line '%s'"), author);
> > 
> > I've checked with the translation for my native language (vi).
> > The translators seem to misread ident (as in identity) as
> > indent (as in indentation).
> > 
> > The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:
> > 
> > 	#~ msgid "malformed ident line"
> > 	#~ msgstr "thụt đầu dòng dị hình"
> > 
> > Translating back to English, it reads: "malformed indentation".
> > 
> > Hence, I think it would read better if we write:
> > 
> > 	res = error(_("malformed identity line '%s'"), author);
> > 
> > 3 more characters is not that much :)
> 
> Looking through the existing strings "invalid ident line: %.*s" is already
> used by am so maybe we should reuse that (log.c also contains "invalid ident
> line: %s"). Is the translation correct?
> 
> #: builtin/am.c:1270
> #, c-format
> msgid "invalid ident line: %.*s"
> msgstr "dòng thụt lề không hợp lệ: %.*s"

That translation isn't correct either.
It seems like it's recurring pattern.
I'll take it to the Vietnamese translation team.

Anyway, I've checked with other translation that I can understand
in part. I think

	invalid ident line: %s

is better candidate for the message.
Since Spanish translation also mis-translates the message:

	es.po:9836:msgid "invalid ident line: %.*s"
	es.po-9837-msgstr "sangría no válida: %.*s"

"sangría" also means "indentation" in this context.

Thanks,
-Danh

> 
> Best Wishes
> 
> Phillip
> 
> > 
> > > +			goto out;
> > > +		}
> > > +		if (!ident.date_begin) {
> > > +			res = error(_("corrupted author without date information"));
> > > +			goto out;
> > > +		}
> > > +
> > > +		strbuf_addf(&date, "@%.*s %.*s",
> > > +			    (int)(ident.date_end - ident.date_begin),
> > > +			    ident.date_begin,
> > > +			    (int)(ident.tz_end - ident.tz_begin),
> > > +			    ident.tz_begin);
> > > +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> > > +		strbuf_release(&date);
> > > +
> > > +		if (res)
> > > +			goto out;
> > > +	}
> > > +
> > >   	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
> > >   		res = error(_("git write-tree failed to write a tree"));
> > >   		goto out;
> > > @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
> > >   			opts->signoff = 1;
> > >   		}
> > > +		if (file_exists(rebase_path_cdate_is_adate())) {
> > > +			opts->allow_ff = 0;
> > > +			opts->committer_date_is_author_date = 1;
> > > +		}
> > > +
> > >   		if (file_exists(rebase_path_reschedule_failed_exec()))
> > >   			opts->reschedule_failed_exec = 1;
> > > @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
> > >   		write_file(rebase_path_drop_redundant_commits(), "%s", "");
> > >   	if (opts->keep_redundant_commits)
> > >   		write_file(rebase_path_keep_redundant_commits(), "%s", "");
> > > +	if (opts->committer_date_is_author_date)
> > > +		write_file(rebase_path_cdate_is_adate(), "%s", "");
> > >   	if (opts->reschedule_failed_exec)
> > >   		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
> > > @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
> > >   			goto leave_merge;
> > >   		}
> > > +		if (opts->committer_date_is_author_date)
> > > +			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> > > +					 author_date_from_env_array(&cmd.env_array));
> > > +
> > >   		cmd.git_cmd = 1;
> > >   		argv_array_push(&cmd.args, "merge");
> > >   		argv_array_push(&cmd.args, "-s");
> > > @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
> > >   	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
> > >   	if (opts->allow_ff)
> > >   		assert(!(opts->signoff || opts->no_commit ||
> > > -				opts->record_origin || opts->edit));
> > > +				opts->record_origin || opts->edit ||
> > > +				opts->committer_date_is_author_date));
> > >   	if (read_and_refresh_cache(r, opts))
> > >   		return -1;
> > > diff --git a/sequencer.h b/sequencer.h
> > > index 0bee85093e..4ab94119ae 100644
> > > --- a/sequencer.h
> > > +++ b/sequencer.h
> > > @@ -45,6 +45,7 @@ struct replay_opts {
> > >   	int verbose;
> > >   	int quiet;
> > >   	int reschedule_failed_exec;
> > > +	int committer_date_is_author_date;
> > >   	int mainline;
> > > diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> > > index 55ca46786d..c8234062c6 100755
> > > --- a/t/t3422-rebase-incompatible-options.sh
> > > +++ b/t/t3422-rebase-incompatible-options.sh
> > > @@ -61,7 +61,6 @@ test_rebase_am_only () {
> > >   }
> > >   test_rebase_am_only --whitespace=fix
> > > -test_rebase_am_only --committer-date-is-author-date
> > >   test_rebase_am_only -C4
> > >   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> > > diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> > > index 4f8a6e51c9..50a63d8ebe 100755
> > > --- a/t/t3436-rebase-more-options.sh
> > > +++ b/t/t3436-rebase-more-options.sh
> > > @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
> > >   . "$TEST_DIRECTORY"/lib-rebase.sh
> > > +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> > > +export GIT_AUTHOR_DATE
> > > +
> > >   # This is a special case in which both am and interactive backends
> > >   # provide the same output. It was done intentionally because
> > >   # both the backends fall short of optimal behaviour.
> > > @@ -21,11 +24,20 @@ test_expect_success 'setup' '
> > >   	test_write_lines "line 1" "new line 2" "line 3" >file &&
> > >   	git commit -am "update file" &&
> > >   	git tag side &&
> > > +	test_commit commit1 foo foo1 &&
> > > +	test_commit commit2 foo foo2 &&
> > > +	test_commit commit3 foo foo3 &&
> > >   	git checkout --orphan master &&
> > > +	rm foo &&
> > >   	test_write_lines "line 1" "        line 2" "line 3" >file &&
> > >   	git commit -am "add file" &&
> > > -	git tag main
> > > +	git tag main &&
> > > +
> > > +	mkdir test-bin &&
> > > +	write_script test-bin/git-merge-test <<-\EOF
> > > +	exec git-merge-recursive "$@"
> > > +	EOF
> > >   '
> > >   test_expect_success '--ignore-whitespace works with apply backend' '
> > > @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
> > >   	git diff --exit-code side
> > >   '
> > > +test_ctime_is_atime () {
> > > +	git log $1 --format=%ai >authortime &&
> > > +	git log $1 --format=%ci >committertime &&
> > > +	test_cmp authortime committertime
> > > +}
> > > +
> > > +test_expect_success '--committer-date-is-author-date works with apply backend' '
> > > +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> > > +	git rebase --apply --committer-date-is-author-date HEAD^ &&
> > > +	test_ctime_is_atime -1
> > > +'
> > > +
> > > +test_expect_success '--committer-date-is-author-date works with merge backend' '
> > > +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> > > +	git rebase -m --committer-date-is-author-date HEAD^ &&
> > > +	test_ctime_is_atime -1
> > > +'
> > > +
> > > +test_expect_success '--committer-date-is-author-date works with rebase -r' '
> > > +	git checkout side &&
> > > +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> > > +	git rebase -r --root --committer-date-is-author-date &&
> > > +	test_ctime_is_atime
> > > +'
> > > +
> > > +test_expect_success '--committer-date-is-author-date works when forking merge' '
> > > +	git checkout side &&
> > > +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> > > +	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
> > > +					--committer-date-is-author-date &&
> > > +	test_ctime_is_atime
> > > +'
> > > +
> > > +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
> > > +	git checkout commit2 &&
> > > +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
> > > +	test_must_fail git rebase -m --committer-date-is-author-date \
> > > +		--onto HEAD^^ HEAD^ &&
> > > +	echo resolved > foo &&
> > 
> > Nitpick: no space after ">" :D
> > 

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-16 13:06         ` Đoàn Trần Công Danh
@ 2020-07-16 15:17           ` Phillip Wood
  2020-07-16 17:34             ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 15:17 UTC (permalink / raw)
  To: Đoàn Trần Công Danh, phillip.wood
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

Hi Danh

On 16/07/2020 14:06, Đoàn Trần Công Danh wrote:
> Hi Phillip,
> 
> On 2020-07-16 09:23:17+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
>>>> [...]
>>>> +	if (opts->committer_date_is_author_date) {
>>>> +		struct ident_split ident;
>>>> +		struct strbuf date = STRBUF_INIT;
>>>> +
>>>> +		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
>>>> +			res = error(_("malformed ident line '%s'"), author);
>>>
>>> I've checked with the translation for my native language (vi).
>>> The translators seem to misread ident (as in identity) as
>>> indent (as in indentation).
>>>
>>> The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:
>>>
>>> 	#~ msgid "malformed ident line"
>>> 	#~ msgstr "thụt đầu dòng dị hình"
>>>
>>> Translating back to English, it reads: "malformed indentation".
>>>
>>> Hence, I think it would read better if we write:
>>>
>>> 	res = error(_("malformed identity line '%s'"), author);
>>>
>>> 3 more characters is not that much :)
>>
>> Looking through the existing strings "invalid ident line: %.*s" is already
>> used by am so maybe we should reuse that (log.c also contains "invalid ident
>> line: %s"). Is the translation correct?
>>
>> #: builtin/am.c:1270
>> #, c-format
>> msgid "invalid ident line: %.*s"
>> msgstr "dòng thụt lề không hợp lệ: %.*s"
> 
> That translation isn't correct either.
> It seems like it's recurring pattern.
> I'll take it to the Vietnamese translation team.
> 
> Anyway, I've checked with other translation that I can understand
> in part. I think
> 
> 	invalid ident line: %s
> 
> is better candidate for the message.

Yes I realized after sending my email that the string we're printing is 
NUL terminated so we don't need to specify the length with '*'. I think 
the best thing would be to change the message in this patch to 'invalid 
ident line: %s' and then have a follow up after this is merged to change 
all the "invalid ident line" messages to use "identity" instead. Would 
you be interested in taking on the follow up patch?

Best Wishes

Phillip

> Since Spanish translation also mis-translates the message:
> 
> 	es.po:9836:msgid "invalid ident line: %.*s"
> 	es.po-9837-msgstr "sangría no válida: %.*s"
> 
> "sangría" also means "indentation" in this context.
> 
> Thanks,
> -Danh
> 
>>
>> Best Wishes
>>
>> Phillip
>>
>>>
>>>> +			goto out;
>>>> +		}
>>>> +		if (!ident.date_begin) {
>>>> +			res = error(_("corrupted author without date information"));
>>>> +			goto out;
>>>> +		}
>>>> +
>>>> +		strbuf_addf(&date, "@%.*s %.*s",
>>>> +			    (int)(ident.date_end - ident.date_begin),
>>>> +			    ident.date_begin,
>>>> +			    (int)(ident.tz_end - ident.tz_begin),
>>>> +			    ident.tz_begin);
>>>> +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
>>>> +		strbuf_release(&date);
>>>> +
>>>> +		if (res)
>>>> +			goto out;
>>>> +	}
>>>> +
>>>>    	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>>>>    		res = error(_("git write-tree failed to write a tree"));
>>>>    		goto out;
>>>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
>>>>    			opts->signoff = 1;
>>>>    		}
>>>> +		if (file_exists(rebase_path_cdate_is_adate())) {
>>>> +			opts->allow_ff = 0;
>>>> +			opts->committer_date_is_author_date = 1;
>>>> +		}
>>>> +
>>>>    		if (file_exists(rebase_path_reschedule_failed_exec()))
>>>>    			opts->reschedule_failed_exec = 1;
>>>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>>>>    		write_file(rebase_path_drop_redundant_commits(), "%s", "");
>>>>    	if (opts->keep_redundant_commits)
>>>>    		write_file(rebase_path_keep_redundant_commits(), "%s", "");
>>>> +	if (opts->committer_date_is_author_date)
>>>> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>>>>    	if (opts->reschedule_failed_exec)
>>>>    		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>>>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
>>>>    			goto leave_merge;
>>>>    		}
>>>> +		if (opts->committer_date_is_author_date)
>>>> +			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>>>> +					 author_date_from_env_array(&cmd.env_array));
>>>> +
>>>>    		cmd.git_cmd = 1;
>>>>    		argv_array_push(&cmd.args, "merge");
>>>>    		argv_array_push(&cmd.args, "-s");
>>>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
>>>>    	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>>>>    	if (opts->allow_ff)
>>>>    		assert(!(opts->signoff || opts->no_commit ||
>>>> -				opts->record_origin || opts->edit));
>>>> +				opts->record_origin || opts->edit ||
>>>> +				opts->committer_date_is_author_date));
>>>>    	if (read_and_refresh_cache(r, opts))
>>>>    		return -1;
>>>> diff --git a/sequencer.h b/sequencer.h
>>>> index 0bee85093e..4ab94119ae 100644
>>>> --- a/sequencer.h
>>>> +++ b/sequencer.h
>>>> @@ -45,6 +45,7 @@ struct replay_opts {
>>>>    	int verbose;
>>>>    	int quiet;
>>>>    	int reschedule_failed_exec;
>>>> +	int committer_date_is_author_date;
>>>>    	int mainline;
>>>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
>>>> index 55ca46786d..c8234062c6 100755
>>>> --- a/t/t3422-rebase-incompatible-options.sh
>>>> +++ b/t/t3422-rebase-incompatible-options.sh
>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>>>    }
>>>>    test_rebase_am_only --whitespace=fix
>>>> -test_rebase_am_only --committer-date-is-author-date
>>>>    test_rebase_am_only -C4
>>>>    test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
>>>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
>>>> index 4f8a6e51c9..50a63d8ebe 100755
>>>> --- a/t/t3436-rebase-more-options.sh
>>>> +++ b/t/t3436-rebase-more-options.sh
>>>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>>>>    . "$TEST_DIRECTORY"/lib-rebase.sh
>>>> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>>>> +export GIT_AUTHOR_DATE
>>>> +
>>>>    # This is a special case in which both am and interactive backends
>>>>    # provide the same output. It was done intentionally because
>>>>    # both the backends fall short of optimal behaviour.
>>>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '
>>>>    	test_write_lines "line 1" "new line 2" "line 3" >file &&
>>>>    	git commit -am "update file" &&
>>>>    	git tag side &&
>>>> +	test_commit commit1 foo foo1 &&
>>>> +	test_commit commit2 foo foo2 &&
>>>> +	test_commit commit3 foo foo3 &&
>>>>    	git checkout --orphan master &&
>>>> +	rm foo &&
>>>>    	test_write_lines "line 1" "        line 2" "line 3" >file &&
>>>>    	git commit -am "add file" &&
>>>> -	git tag main
>>>> +	git tag main &&
>>>> +
>>>> +	mkdir test-bin &&
>>>> +	write_script test-bin/git-merge-test <<-\EOF
>>>> +	exec git-merge-recursive "$@"
>>>> +	EOF
>>>>    '
>>>>    test_expect_success '--ignore-whitespace works with apply backend' '
>>>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
>>>>    	git diff --exit-code side
>>>>    '
>>>> +test_ctime_is_atime () {
>>>> +	git log $1 --format=%ai >authortime &&
>>>> +	git log $1 --format=%ci >committertime &&
>>>> +	test_cmp authortime committertime
>>>> +}
>>>> +
>>>> +test_expect_success '--committer-date-is-author-date works with apply backend' '
>>>> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>>>> +	git rebase --apply --committer-date-is-author-date HEAD^ &&
>>>> +	test_ctime_is_atime -1
>>>> +'
>>>> +
>>>> +test_expect_success '--committer-date-is-author-date works with merge backend' '
>>>> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
>>>> +	git rebase -m --committer-date-is-author-date HEAD^ &&
>>>> +	test_ctime_is_atime -1
>>>> +'
>>>> +
>>>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
>>>> +	git checkout side &&
>>>> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>>>> +	git rebase -r --root --committer-date-is-author-date &&
>>>> +	test_ctime_is_atime
>>>> +'
>>>> +
>>>> +test_expect_success '--committer-date-is-author-date works when forking merge' '
>>>> +	git checkout side &&
>>>> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>>>> +	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
>>>> +					--committer-date-is-author-date &&
>>>> +	test_ctime_is_atime
>>>> +'
>>>> +
>>>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
>>>> +	git checkout commit2 &&
>>>> +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
>>>> +	test_must_fail git rebase -m --committer-date-is-author-date \
>>>> +		--onto HEAD^^ HEAD^ &&
>>>> +	echo resolved > foo &&
>>>
>>> Nitpick: no space after ">" :D
>>>
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v7 0/5] cleanup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (12 preceding siblings ...)
  2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
@ 2020-07-16 17:32 ` Phillip Wood
  2020-07-16 17:32   ` [PATCH v7 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
                     ` (6 more replies)
  2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
  14 siblings, 7 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 17:32 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Danh pointed out that the word "ident" gets misinterpreted by
translators as "indentation" leading to incorrect translations so I've
reworded an error message.

format-patch and am could do with having their similar messages
updated in the future

Phillip Wood (2):
  rebase -i: support --committer-date-is-author-date
  rebase -i: support --ignore-date

Rohit Ashiwal (3):
  rebase -i: add --ignore-whitespace flag
  sequencer: rename amend_author to author_to_free
  rebase: add --reset-author-date

 Documentation/git-rebase.txt           |  33 ++++-
 builtin/rebase.c                       |  47 +++++--
 sequencer.c                            | 112 ++++++++++++++-
 sequencer.h                            |   2 +
 t/t3422-rebase-incompatible-options.sh |   2 -
 t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++
 6 files changed, 353 insertions(+), 23 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

Range-diff against v6:
1:  0fc90eaff1 ! 1:  3865fdf461 rebase -i: support --ignore-date
    @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr
     +	struct strbuf new_author = STRBUF_INIT;
     +
     +	if (split_ident_line(&ident, author, strlen(author)) < 0) {
    -+		error(_("malformed ident line '%s'"), author);
    ++		error(_("invalid author identity: %s"), author);
     +		return NULL;
     +	}
     +
2:  21cf5e5512 = 2:  0b6b19cb68 rebase: add --reset-author-date
-- 
2.27.0


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v7 1/5] rebase -i: add --ignore-whitespace flag
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
@ 2020-07-16 17:32   ` Phillip Wood
  2020-07-16 17:32   ` [PATCH v7 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 17:32 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--ignore-whitespace option to the merge backend. This option treats
lines with only whitespace changes as unchanged and is implemented in
the merge backend by translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 19 +++++++-
 builtin/rebase.c                       | 19 ++++++--
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++
 4 files changed, 93 insertions(+), 6 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f7a6033607..b003784f01 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Ignore whitespace differences when trying to reconcile
+differences. Currently, each backend implements an approximation of
+this behavior:
++
+apply backend: When applying a patch, ignore changes in whitespace in
+context lines. Unfortunately, this means that if the "old" lines being
+replaced by the patch differ only in whitespace from the existing
+file, you will get a merge conflict instead of a successful patch
+application.
++
+merge backend: Treat lines with only whitespace changes as unchanged
+when merging. Unfortunately, this means that any patch hunks that were
+intended to modify whitespace and nothing else will be dropped, even
+if the other side had no changes that conflicted.
+
 --whitespace=<option>::
-	These flags are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 	Implies --apply.
 +
@@ -572,7 +587,6 @@ The following options:
  * --apply
  * --committer-date-is-author-date
  * --ignore-date
- * --ignore-whitespace
  * --whitespace
  * -C
 
@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 27a07d4e78..bd93e9742c 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
 		parse_strategy_opts(&replay, opts->strategy_opts);
 
@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct strbuf revisions = STRBUF_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id merge_base;
+	int ignore_whitespace = 0;
 	enum action action = ACTION_NONE;
 	const char *gpg_sign = NULL;
 	struct string_list exec = STRING_LIST_INIT_NODUP;
@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		imply_merge(&options, "--rebase-merges");
 	}
 
+	if (options.type == REBASE_APPLY) {
+		if (ignore_whitespace)
+			argv_array_push(&options.git_am_opts,
+					"--ignore-whitespace");
+	} else {
+		/* REBASE_MERGE and PRESERVE_MERGES */
+		if (ignore_whitespace) {
+			string_list_append(&strategy_options,
+					   "ignore-space-change");
+		}
+	}
+
 	if (strategy_options.nr) {
 		int i;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
new file mode 100755
index 0000000000..4f8a6e51c9
--- /dev/null
+++ b/t/t3436-rebase-more-options.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	test_write_lines "line 1" "	line 2" "line 3" >file &&
+	git add file &&
+	git commit -m "add file" &&
+
+	test_write_lines "line 1" "new line 2" "line 3" >file &&
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	test_write_lines "line 1" "        line 2" "line 3" >file &&
+	git commit -am "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with apply backend' '
+	test_must_fail git rebase --apply main side &&
+	git rebase --abort &&
+	git rebase --apply --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace works with merge backend' '
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
+			main side &&
+		git rebase --continue
+	) &&
+	git diff --exit-code side
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
+test_done
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v7 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
  2020-07-16 17:32   ` [PATCH v7 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-07-16 17:32   ` Phillip Wood
  2020-08-13 13:46     ` Johannes Schindelin
  2020-07-16 17:32   ` [PATCH v7 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 17:32 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--committer-date-is-author-date option to the merge backend. This
option uses the author date of the commit that is being rewritten as
the committer date when the new commit is created.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 10 +++--
 builtin/rebase.c                       | 17 +++++---
 sequencer.c                            | 60 +++++++++++++++++++++++++-
 sequencer.h                            |  1 +
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++++++++++-
 6 files changed, 136 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b003784f01..dfa70263e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of using the current time as the committer date, use
+	the author date of the commit being rebased as the committer
+	date. This option implies --force-rebase.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index bd93e9742c..2579380729 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -88,6 +88,7 @@ struct rebase_options {
 	int autosquash;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (ignore_whitespace)
 			argv_array_push(&options.git_am_opts,
 					"--ignore-whitespace");
+		if (options.committer_date_is_author_date)
+			argv_array_push(&options.git_am_opts,
+					"--committer-date-is-author-date");
 	} else {
 		/* REBASE_MERGE and PRESERVE_MERGES */
 		if (ignore_whitespace) {
diff --git a/sequencer.c b/sequencer.c
index 6fd2674632..368d397970 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -872,6 +873,22 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+static const char *author_date_from_env_array(const struct argv_array *env)
+{
+	int i;
+	const char *date;
+
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,
 			     gpg_opt, gpg_opt);
 	}
 
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 author_date_from_env_array(&cmd.env_array));
+
 	argv_array_push(&cmd.args, "commit");
 
 	if (!(flags & VERIFY_MSG))
@@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,
 		commit_list_insert(current_head, &parents);
 	}
 
+	if (opts->committer_date_is_author_date) {
+		struct ident_split ident;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
+			res = error(_("malformed ident line '%s'"), author);
+			goto out;
+		}
+		if (!ident.date_begin) {
+			res = error(_("corrupted author without date information"));
+			goto out;
+		}
+
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(ident.date_end - ident.date_begin),
+			    ident.date_begin,
+			    (int)(ident.tz_end - ident.tz_begin),
+			    ident.tz_begin);
+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		strbuf_release(&date);
+
+		if (res)
+			goto out;
+	}
+
 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
 		res = error(_("git write-tree failed to write a tree"));
 		goto out;
@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
 	if (opts->keep_redundant_commits)
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
 			goto leave_merge;
 		}
 
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 author_date_from_env_array(&cmd.env_array));
+
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
 		argv_array_push(&cmd.args, "-s");
@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+				opts->record_origin || opts->edit ||
+				opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 0bee85093e..4ab94119ae 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -45,6 +45,7 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 4f8a6e51c9..50a63d8ebe 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -21,11 +24,20 @@ test_expect_success 'setup' '
 	test_write_lines "line 1" "new line 2" "line 3" >file &&
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	rm foo &&
 	test_write_lines "line 1" "        line 2" "line 3" >file &&
 	git commit -am "add file" &&
-	git tag main
+	git tag main &&
+
+	mkdir test-bin &&
+	write_script test-bin/git-merge-test <<-\EOF
+	exec git-merge-recursive "$@"
+	EOF
 '
 
 test_expect_success '--ignore-whitespace works with apply backend' '
@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
 	git diff --exit-code side
 '
 
+test_ctime_is_atime () {
+	git log $1 --format=%ai >authortime &&
+	git log $1 --format=%ci >committertime &&
+	test_cmp authortime committertime
+}
+
+test_expect_success '--committer-date-is-author-date works with apply backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase --apply --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with merge backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase -m --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
+					--committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -1
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v7 3/5] sequencer: rename amend_author to author_to_free
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
  2020-07-16 17:32   ` [PATCH v7 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-07-16 17:32   ` [PATCH v7 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-07-16 17:32   ` Phillip Wood
  2020-07-16 17:32   ` [PATCH v7 4/5] rebase -i: support --ignore-date Phillip Wood
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 17:32 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The purpose of amend_author was to free() the malloc()'d string
obtained from get_author() when amending a commit. But we can
also use the variable to free() the author at our convenience.
Rename it to convey this meaning.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 sequencer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 368d397970..29f6d1bc39 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
-	char *amend_author = NULL;
+	char *author_to_free = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,
 			strbuf_addstr(msg, orig_message);
 			hook_commit = "HEAD";
 		}
-		author = amend_author = get_author(message);
+		author = author_to_free = get_author(message);
 		unuse_commit_buffer(current_head, message);
 		if (!author) {
 			res = error(_("unable to parse commit author"));
@@ -1474,7 +1474,7 @@ static int try_to_commit(struct repository *r,
 	free_commit_extra_headers(extra);
 	strbuf_release(&err);
 	strbuf_release(&commit_msg);
-	free(amend_author);
+	free(author_to_free);
 
 	return res;
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v7 4/5] rebase -i: support --ignore-date
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                     ` (2 preceding siblings ...)
  2020-07-16 17:32   ` [PATCH v7 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
@ 2020-07-16 17:32   ` Phillip Wood
  2020-08-13 14:07     ` Johannes Schindelin
  2020-07-16 17:32   ` [PATCH v7 5/5] rebase: add --reset-author-date Phillip Wood
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 17:32 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the --ignore-date
option to the merge backend. This option uses the current time as the
author date rather than reusing the original author date when
rewriting commits. We take care to handle the combination of
--ignore-date and --committer-date-is-author-date in the same way as
the apply backend.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt   |  7 +++--
 builtin/rebase.c               | 13 +++++---
 sequencer.c                    | 50 ++++++++++++++++++++++++++++--
 sequencer.h                    |  1 +
 t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index dfa70263e6..e2717e20e6 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the author date of the original commit, use
+	the current time as the	author date of the rebased commit.  This
+	option implies `--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --ignore-date
  * --whitespace
  * -C
 
@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 2579380729..583ac96fc7 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -89,6 +89,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date || options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
 		else if (skip_prefix(option, "-C", &p)) {
@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (options.committer_date_is_author_date)
 			argv_array_push(&options.git_am_opts,
 					"--committer-date-is-author-date");
+		if (options.ignore_date)
+			argv_array_push(&options.git_am_opts, "--ignore-date");
 	} else {
 		/* REBASE_MERGE and PRESERVE_MERGES */
 		if (ignore_whitespace) {
diff --git a/sequencer.c b/sequencer.c
index 29f6d1bc39..878fafdc41 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)
 	BUG("GIT_AUTHOR_DATE missing from author script");
 }
 
+/* Construct a free()able author string with current time as the author date */
+static char *ignore_author_date(const char *author)
+{
+	int len;
+	struct ident_split ident;
+	struct strbuf new_author = STRBUF_INIT;
+
+	if (split_ident_line(&ident, author, strlen(author)) < 0) {
+		error(_("invalid author identity: %s"), author);
+		return NULL;
+	}
+
+	len = ident.mail_end - ident.name_begin + 1;
+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
+	datestamp(&new_author);
+	return strbuf_detach(&new_author, NULL);
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
 
 	if (opts->committer_date_is_author_date)
 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
 				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,
 			    ident.date_begin,
 			    (int)(ident.tz_end - ident.tz_begin),
 			    ident.tz_begin);
-		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
+		res = setenv("GIT_COMMITTER_DATE",
+			     opts->ignore_date ? "" : date.buf, 1);
 		strbuf_release(&date);
 
 		if (res)
@@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
+	if (opts->ignore_date) {
+		author = ignore_author_date(author);
+		if (!author) {
+			res = -1;
+			goto out;
+		}
+		free(author_to_free);
+		author_to_free = (char *)author;
+	}
+
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
 				 oid, author, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,
 
 		if (opts->committer_date_is_author_date)
 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
 					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit ||
-				opts->committer_date_is_author_date));
+				opts->committer_date_is_author_date ||
+				opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 4ab94119ae..3587878e3b 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -46,6 +46,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 50a63d8ebe..0ede2b8900 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 	test_ctime_is_atime -1
 '
 
+# Checking for +0000 in the author date is sufficient since the
+# default timezone is UTC but the timezone used while committing is
+# +0530. The inverted logic in the grep is necessary to check all the
+# author dates in the file.
+test_ctime_is_ignored () {
+	git log $1 --format=%ai >authortime &&
+	! grep -v +0000 authortime
+}
+
+test_expect_success '--ignore-date works with apply backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with merge backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -m HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -m \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	test_ctime_is_ignored
+'
+
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -2 &&
+	test_ctime_is_ignored -2
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
+				--ignore-date --committer-date-is-author-date \
+				side side &&
+	test_ctime_is_atime -1 &&
+	test_ctime_is_ignored -1
+ '
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v7 5/5] rebase: add --reset-author-date
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                     ` (3 preceding siblings ...)
  2020-07-16 17:32   ` [PATCH v7 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-07-16 17:32   ` Phillip Wood
  2020-07-16 17:39   ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
  2020-08-13 14:24   ` Johannes Schindelin
  6 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 17:32 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The previous commit introduced --ignore-date flag to rebase -i, but the
name is rather vague as it does not say whether the author date or the
committer date is ignored. Add an alias to convey the precise purpose.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt   |  1 +
 builtin/rebase.c               |  4 +++-
 t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e2717e20e6..a5f82913fb 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies --force-rebase.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the author date of the original commit, use
 	the current time as the	author date of the rebased commit.  This
 	option implies `--force-rebase`.
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 583ac96fc7..b126fbe940 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
 			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 0ede2b8900..5b8963272a 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -117,53 +117,61 @@ test_ctime_is_ignored () {
 	! grep -v +0000 authortime
 }
 
-test_expect_success '--ignore-date works with apply backend' '
+test_expect_success '--reset-author-date works with apply backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --apply --ignore-date HEAD^ &&
+	git rebase --apply --reset-author-date HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with merge backend' '
+test_expect_success '--reset-author-date works with merge backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --ignore-date -m HEAD^ &&
+	git rebase --reset-author-date -m HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works after conflict resolution' '
-	test_must_fail git rebase --ignore-date -m \
+test_expect_success '--reset-author-date works after conflict resolution' '
+	test_must_fail git rebase --reset-author-date -m \
 		--onto commit2^^ commit2^ commit2 &&
 	echo resolved >foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with rebase -r' '
+test_expect_success '--reset-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
-	git rebase -r --root --ignore-date &&
+	git rebase -r --root --reset-author-date &&
 	test_ctime_is_ignored
 '
 
-test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
 	test_must_fail git rebase -m --committer-date-is-author-date \
-		--ignore-date --onto commit2^^ commit2^ commit3 &&
+		--reset-author-date --onto commit2^^ commit2^ commit3 &&
 	git checkout --theirs foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_atime -2 &&
 	test_ctime_is_ignored -2
 '
 
-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
 	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
 		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
-				--ignore-date --committer-date-is-author-date \
-				side side &&
+				--reset-author-date \
+				--committer-date-is-author-date side side &&
 	test_ctime_is_atime -1 &&
 	test_ctime_is_ignored -1
  '
 
+test_expect_success '--ignore-date is an alias for --reset-author-date' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
+	git rebase -m --ignore-date HEAD^ &&
+	test_ctime_is_ignored -2
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-16 15:17           ` Phillip Wood
@ 2020-07-16 17:34             ` Phillip Wood
  2020-07-17  0:25               ` Đoàn Trần Công Danh
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-07-16 17:34 UTC (permalink / raw)
  To: phillip.wood, Đoàn Trần Công Danh
  Cc: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

On 16/07/2020 16:17, Phillip Wood wrote:
> Hi Danh
> 
> On 16/07/2020 14:06, Đoàn Trần Công Danh wrote:
>> Hi Phillip,
>>
>> On 2020-07-16 09:23:17+0100, Phillip Wood <phillip.wood123@gmail.com>
>> wrote:
>>>>> [...]
>>>>> +    if (opts->committer_date_is_author_date) {
>>>>> +        struct ident_split ident;
>>>>> +        struct strbuf date = STRBUF_INIT;
>>>>> +
>>>>> +        if (split_ident_line(&ident, author, (int)strlen(author))
>>>>> < 0) {
>>>>> +            res = error(_("malformed ident line '%s'"), author);
>>>>
>>>> I've checked with the translation for my native language (vi).
>>>> The translators seem to misread ident (as in identity) as
>>>> indent (as in indentation).
>>>>
>>>> The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:
>>>>
>>>>     #~ msgid "malformed ident line"
>>>>     #~ msgstr "thụt đầu dòng dị hình"
>>>>
>>>> Translating back to English, it reads: "malformed indentation".
>>>>
>>>> Hence, I think it would read better if we write:
>>>>
>>>>     res = error(_("malformed identity line '%s'"), author);
>>>>
>>>> 3 more characters is not that much :)
>>>
>>> Looking through the existing strings "invalid ident line: %.*s" is
>>> already
>>> used by am so maybe we should reuse that (log.c also contains
>>> "invalid ident
>>> line: %s"). Is the translation correct?
>>>
>>> #: builtin/am.c:1270
>>> #, c-format
>>> msgid "invalid ident line: %.*s"
>>> msgstr "dòng thụt lề không hợp lệ: %.*s"
>>
>> That translation isn't correct either.
>> It seems like it's recurring pattern.
>> I'll take it to the Vietnamese translation team.
>>
>> Anyway, I've checked with other translation that I can understand
>> in part. I think
>>
>>     invalid ident line: %s
>>
>> is better candidate for the message.
> 
> Yes I realized after sending my email that the string we're printing is
> NUL terminated so we don't need to specify the length with '*'. I think
> the best thing would be to change the message in this patch to 'invalid
> ident line: %s' and then have a follow up after this is merged to change
> all the "invalid ident line" messages to use "identity" instead. Would
> you be interested in taking on the follow up patch?

In the end I decided it was better just to change the message in this
patch to something more descriptive. We can update the other commands
separately. For format-patch we should probably update the option
description for `--from` as well as the error message.

Best Wishes

Phillip

> 
> Best Wishes
> 
> Phillip
> 
>> Since Spanish translation also mis-translates the message:
>>
>>     es.po:9836:msgid "invalid ident line: %.*s"
>>     es.po-9837-msgstr "sangría no válida: %.*s"
>>
>> "sangría" also means "indentation" in this context.
>>
>> Thanks,
>> -Danh
>>
>>>
>>> Best Wishes
>>>
>>> Phillip
>>>
>>>>
>>>>> +            goto out;
>>>>> +        }
>>>>> +        if (!ident.date_begin) {
>>>>> +            res = error(_("corrupted author without date
>>>>> information"));
>>>>> +            goto out;
>>>>> +        }
>>>>> +
>>>>> +        strbuf_addf(&date, "@%.*s %.*s",
>>>>> +                (int)(ident.date_end - ident.date_begin),
>>>>> +                ident.date_begin,
>>>>> +                (int)(ident.tz_end - ident.tz_begin),
>>>>> +                ident.tz_begin);
>>>>> +        res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
>>>>> +        strbuf_release(&date);
>>>>> +
>>>>> +        if (res)
>>>>> +            goto out;
>>>>> +    }
>>>>> +
>>>>>        if (write_index_as_tree(&tree, r->index, r->index_file, 0,
>>>>> NULL)) {
>>>>>            res = error(_("git write-tree failed to write a tree"));
>>>>>            goto out;
>>>>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct
>>>>> replay_opts *opts)
>>>>>                opts->signoff = 1;
>>>>>            }
>>>>> +        if (file_exists(rebase_path_cdate_is_adate())) {
>>>>> +            opts->allow_ff = 0;
>>>>> +            opts->committer_date_is_author_date = 1;
>>>>> +        }
>>>>> +
>>>>>            if (file_exists(rebase_path_reschedule_failed_exec()))
>>>>>                opts->reschedule_failed_exec = 1;
>>>>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts
>>>>> *opts, const char *head_name,
>>>>>            write_file(rebase_path_drop_redundant_commits(), "%s", "");
>>>>>        if (opts->keep_redundant_commits)
>>>>>            write_file(rebase_path_keep_redundant_commits(), "%s", "");
>>>>> +    if (opts->committer_date_is_author_date)
>>>>> +        write_file(rebase_path_cdate_is_adate(), "%s", "");
>>>>>        if (opts->reschedule_failed_exec)
>>>>>            write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>>>>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
>>>>>                goto leave_merge;
>>>>>            }
>>>>> +        if (opts->committer_date_is_author_date)
>>>>> +            argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
>>>>> +                     author_date_from_env_array(&cmd.env_array));
>>>>> +
>>>>>            cmd.git_cmd = 1;
>>>>>            argv_array_push(&cmd.args, "merge");
>>>>>            argv_array_push(&cmd.args, "-s");
>>>>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
>>>>>        setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>>>>>        if (opts->allow_ff)
>>>>>            assert(!(opts->signoff || opts->no_commit ||
>>>>> -                opts->record_origin || opts->edit));
>>>>> +                opts->record_origin || opts->edit ||
>>>>> +                opts->committer_date_is_author_date));
>>>>>        if (read_and_refresh_cache(r, opts))
>>>>>            return -1;
>>>>> diff --git a/sequencer.h b/sequencer.h
>>>>> index 0bee85093e..4ab94119ae 100644
>>>>> --- a/sequencer.h
>>>>> +++ b/sequencer.h
>>>>> @@ -45,6 +45,7 @@ struct replay_opts {
>>>>>        int verbose;
>>>>>        int quiet;
>>>>>        int reschedule_failed_exec;
>>>>> +    int committer_date_is_author_date;
>>>>>        int mainline;
>>>>> diff --git a/t/t3422-rebase-incompatible-options.sh
>>>>> b/t/t3422-rebase-incompatible-options.sh
>>>>> index 55ca46786d..c8234062c6 100755
>>>>> --- a/t/t3422-rebase-incompatible-options.sh
>>>>> +++ b/t/t3422-rebase-incompatible-options.sh
>>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>>>>>    }
>>>>>    test_rebase_am_only --whitespace=fix
>>>>> -test_rebase_am_only --committer-date-is-author-date
>>>>>    test_rebase_am_only -C4
>>>>>    test_expect_success REBASE_P '--preserve-merges incompatible
>>>>> with --signoff' '
>>>>> diff --git a/t/t3436-rebase-more-options.sh
>>>>> b/t/t3436-rebase-more-options.sh
>>>>> index 4f8a6e51c9..50a63d8ebe 100755
>>>>> --- a/t/t3436-rebase-more-options.sh
>>>>> +++ b/t/t3436-rebase-more-options.sh
>>>>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility
>>>>> between am and interactive backe
>>>>>    . "$TEST_DIRECTORY"/lib-rebase.sh
>>>>> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
>>>>> +export GIT_AUTHOR_DATE
>>>>> +
>>>>>    # This is a special case in which both am and interactive backends
>>>>>    # provide the same output. It was done intentionally because
>>>>>    # both the backends fall short of optimal behaviour.
>>>>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '
>>>>>        test_write_lines "line 1" "new line 2" "line 3" >file &&
>>>>>        git commit -am "update file" &&
>>>>>        git tag side &&
>>>>> +    test_commit commit1 foo foo1 &&
>>>>> +    test_commit commit2 foo foo2 &&
>>>>> +    test_commit commit3 foo foo3 &&
>>>>>        git checkout --orphan master &&
>>>>> +    rm foo &&
>>>>>        test_write_lines "line 1" "        line 2" "line 3" >file &&
>>>>>        git commit -am "add file" &&
>>>>> -    git tag main
>>>>> +    git tag main &&
>>>>> +
>>>>> +    mkdir test-bin &&
>>>>> +    write_script test-bin/git-merge-test <<-\EOF
>>>>> +    exec git-merge-recursive "$@"
>>>>> +    EOF
>>>>>    '
>>>>>    test_expect_success '--ignore-whitespace works with apply
>>>>> backend' '
>>>>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is
>>>>> remembered when continuing' '
>>>>>        git diff --exit-code side
>>>>>    '
>>>>> +test_ctime_is_atime () {
>>>>> +    git log $1 --format=%ai >authortime &&
>>>>> +    git log $1 --format=%ci >committertime &&
>>>>> +    test_cmp authortime committertime
>>>>> +}
>>>>> +
>>>>> +test_expect_success '--committer-date-is-author-date works with
>>>>> apply backend' '
>>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git commit --amend
>>>>> --reset-author &&
>>>>> +    git rebase --apply --committer-date-is-author-date HEAD^ &&
>>>>> +    test_ctime_is_atime -1
>>>>> +'
>>>>> +
>>>>> +test_expect_success '--committer-date-is-author-date works with
>>>>> merge backend' '
>>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git commit --amend
>>>>> --reset-author &&
>>>>> +    git rebase -m --committer-date-is-author-date HEAD^ &&
>>>>> +    test_ctime_is_atime -1
>>>>> +'
>>>>> +
>>>>> +test_expect_success '--committer-date-is-author-date works with
>>>>> rebase -r' '
>>>>> +    git checkout side &&
>>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>>>>> +    git rebase -r --root --committer-date-is-author-date &&
>>>>> +    test_ctime_is_atime
>>>>> +'
>>>>> +
>>>>> +test_expect_success '--committer-date-is-author-date works when
>>>>> forking merge' '
>>>>> +    git checkout side &&
>>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
>>>>> +    PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
>>>>> +                    --committer-date-is-author-date &&
>>>>> +    test_ctime_is_atime
>>>>> +'
>>>>> +
>>>>> +test_expect_success '--committer-date-is-author-date works when
>>>>> committing conflict resolution' '
>>>>> +    git checkout commit2 &&
>>>>> +    GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only
>>>>> --reset-author &&
>>>>> +    test_must_fail git rebase -m --committer-date-is-author-date \
>>>>> +        --onto HEAD^^ HEAD^ &&
>>>>> +    echo resolved > foo &&
>>>>
>>>> Nitpick: no space after ">" :D
>>>>
>>


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                     ` (4 preceding siblings ...)
  2020-07-16 17:32   ` [PATCH v7 5/5] rebase: add --reset-author-date Phillip Wood
@ 2020-07-16 17:39   ` Junio C Hamano
  2020-08-13 14:24   ` Johannes Schindelin
  6 siblings, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-07-16 17:39 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> format-patch and am could do with having their similar messages
> updated in the future

That's a good #leftoverbits topic.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-16 17:34             ` Phillip Wood
@ 2020-07-17  0:25               ` Đoàn Trần Công Danh
  0 siblings, 0 replies; 130+ messages in thread
From: Đoàn Trần Công Danh @ 2020-07-17  0:25 UTC (permalink / raw)
  To: Phillip Wood
  Cc: phillip.wood, Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Alban Gruin, Git Mailing List

On 2020-07-16 18:34:51+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:
> >> That translation isn't correct either.
> >> It seems like it's recurring pattern.
> >> I'll take it to the Vietnamese translation team.
> >>
> >> Anyway, I've checked with other translation that I can understand
> >> in part. I think
> >>
> >>     invalid ident line: %s
> >>
> >> is better candidate for the message.
> > 
> > Yes I realized after sending my email that the string we're printing is
> > NUL terminated so we don't need to specify the length with '*'. I think
> > the best thing would be to change the message in this patch to 'invalid
> > ident line: %s' and then have a follow up after this is merged to change
> > all the "invalid ident line" messages to use "identity" instead. Would
> > you be interested in taking on the follow up patch?
> 
> In the end I decided it was better just to change the message in this
> patch to something more descriptive. We can update the other commands
> separately. For format-patch we should probably update the option
> description for `--from` as well as the error message.

Yes, I also think we should leave the other messages there for now.
When this topic get merged, we will come back to see which one should
be updated/changed.

All other parts look sane to me.

I don't mind get my hand wet if noone steps in.

Thanks,
Danh

> 
> Best Wishes
> 
> Phillip
> 
> > 
> > Best Wishes
> > 
> > Phillip
> > 
> >> Since Spanish translation also mis-translates the message:
> >>
> >>     es.po:9836:msgid "invalid ident line: %.*s"
> >>     es.po-9837-msgstr "sangría no válida: %.*s"
> >>
> >> "sangría" also means "indentation" in this context.
> >>
> >> Thanks,
> >> -Danh
> >>
> >>>
> >>> Best Wishes
> >>>
> >>> Phillip
> >>>
> >>>>
> >>>>> +            goto out;
> >>>>> +        }
> >>>>> +        if (!ident.date_begin) {
> >>>>> +            res = error(_("corrupted author without date
> >>>>> information"));
> >>>>> +            goto out;
> >>>>> +        }
> >>>>> +
> >>>>> +        strbuf_addf(&date, "@%.*s %.*s",
> >>>>> +                (int)(ident.date_end - ident.date_begin),
> >>>>> +                ident.date_begin,
> >>>>> +                (int)(ident.tz_end - ident.tz_begin),
> >>>>> +                ident.tz_begin);
> >>>>> +        res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> >>>>> +        strbuf_release(&date);
> >>>>> +
> >>>>> +        if (res)
> >>>>> +            goto out;
> >>>>> +    }
> >>>>> +
> >>>>>        if (write_index_as_tree(&tree, r->index, r->index_file, 0,
> >>>>> NULL)) {
> >>>>>            res = error(_("git write-tree failed to write a tree"));
> >>>>>            goto out;
> >>>>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct
> >>>>> replay_opts *opts)
> >>>>>                opts->signoff = 1;
> >>>>>            }
> >>>>> +        if (file_exists(rebase_path_cdate_is_adate())) {
> >>>>> +            opts->allow_ff = 0;
> >>>>> +            opts->committer_date_is_author_date = 1;
> >>>>> +        }
> >>>>> +
> >>>>>            if (file_exists(rebase_path_reschedule_failed_exec()))
> >>>>>                opts->reschedule_failed_exec = 1;
> >>>>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts
> >>>>> *opts, const char *head_name,
> >>>>>            write_file(rebase_path_drop_redundant_commits(), "%s", "");
> >>>>>        if (opts->keep_redundant_commits)
> >>>>>            write_file(rebase_path_keep_redundant_commits(), "%s", "");
> >>>>> +    if (opts->committer_date_is_author_date)
> >>>>> +        write_file(rebase_path_cdate_is_adate(), "%s", "");
> >>>>>        if (opts->reschedule_failed_exec)
> >>>>>            write_file(rebase_path_reschedule_failed_exec(), "%s", "");
> >>>>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
> >>>>>                goto leave_merge;
> >>>>>            }
> >>>>> +        if (opts->committer_date_is_author_date)
> >>>>> +            argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> >>>>> +                     author_date_from_env_array(&cmd.env_array));
> >>>>> +
> >>>>>            cmd.git_cmd = 1;
> >>>>>            argv_array_push(&cmd.args, "merge");
> >>>>>            argv_array_push(&cmd.args, "-s");
> >>>>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
> >>>>>        setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
> >>>>>        if (opts->allow_ff)
> >>>>>            assert(!(opts->signoff || opts->no_commit ||
> >>>>> -                opts->record_origin || opts->edit));
> >>>>> +                opts->record_origin || opts->edit ||
> >>>>> +                opts->committer_date_is_author_date));
> >>>>>        if (read_and_refresh_cache(r, opts))
> >>>>>            return -1;
> >>>>> diff --git a/sequencer.h b/sequencer.h
> >>>>> index 0bee85093e..4ab94119ae 100644
> >>>>> --- a/sequencer.h
> >>>>> +++ b/sequencer.h
> >>>>> @@ -45,6 +45,7 @@ struct replay_opts {
> >>>>>        int verbose;
> >>>>>        int quiet;
> >>>>>        int reschedule_failed_exec;
> >>>>> +    int committer_date_is_author_date;
> >>>>>        int mainline;
> >>>>> diff --git a/t/t3422-rebase-incompatible-options.sh
> >>>>> b/t/t3422-rebase-incompatible-options.sh
> >>>>> index 55ca46786d..c8234062c6 100755
> >>>>> --- a/t/t3422-rebase-incompatible-options.sh
> >>>>> +++ b/t/t3422-rebase-incompatible-options.sh
> >>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {
> >>>>>    }
> >>>>>    test_rebase_am_only --whitespace=fix
> >>>>> -test_rebase_am_only --committer-date-is-author-date
> >>>>>    test_rebase_am_only -C4
> >>>>>    test_expect_success REBASE_P '--preserve-merges incompatible
> >>>>> with --signoff' '
> >>>>> diff --git a/t/t3436-rebase-more-options.sh
> >>>>> b/t/t3436-rebase-more-options.sh
> >>>>> index 4f8a6e51c9..50a63d8ebe 100755
> >>>>> --- a/t/t3436-rebase-more-options.sh
> >>>>> +++ b/t/t3436-rebase-more-options.sh
> >>>>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility
> >>>>> between am and interactive backe
> >>>>>    . "$TEST_DIRECTORY"/lib-rebase.sh
> >>>>> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> >>>>> +export GIT_AUTHOR_DATE
> >>>>> +
> >>>>>    # This is a special case in which both am and interactive backends
> >>>>>    # provide the same output. It was done intentionally because
> >>>>>    # both the backends fall short of optimal behaviour.
> >>>>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '
> >>>>>        test_write_lines "line 1" "new line 2" "line 3" >file &&
> >>>>>        git commit -am "update file" &&
> >>>>>        git tag side &&
> >>>>> +    test_commit commit1 foo foo1 &&
> >>>>> +    test_commit commit2 foo foo2 &&
> >>>>> +    test_commit commit3 foo foo3 &&
> >>>>>        git checkout --orphan master &&
> >>>>> +    rm foo &&
> >>>>>        test_write_lines "line 1" "        line 2" "line 3" >file &&
> >>>>>        git commit -am "add file" &&
> >>>>> -    git tag main
> >>>>> +    git tag main &&
> >>>>> +
> >>>>> +    mkdir test-bin &&
> >>>>> +    write_script test-bin/git-merge-test <<-\EOF
> >>>>> +    exec git-merge-recursive "$@"
> >>>>> +    EOF
> >>>>>    '
> >>>>>    test_expect_success '--ignore-whitespace works with apply
> >>>>> backend' '
> >>>>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is
> >>>>> remembered when continuing' '
> >>>>>        git diff --exit-code side
> >>>>>    '
> >>>>> +test_ctime_is_atime () {
> >>>>> +    git log $1 --format=%ai >authortime &&
> >>>>> +    git log $1 --format=%ci >committertime &&
> >>>>> +    test_cmp authortime committertime
> >>>>> +}
> >>>>> +
> >>>>> +test_expect_success '--committer-date-is-author-date works with
> >>>>> apply backend' '
> >>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git commit --amend
> >>>>> --reset-author &&
> >>>>> +    git rebase --apply --committer-date-is-author-date HEAD^ &&
> >>>>> +    test_ctime_is_atime -1
> >>>>> +'
> >>>>> +
> >>>>> +test_expect_success '--committer-date-is-author-date works with
> >>>>> merge backend' '
> >>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git commit --amend
> >>>>> --reset-author &&
> >>>>> +    git rebase -m --committer-date-is-author-date HEAD^ &&
> >>>>> +    test_ctime_is_atime -1
> >>>>> +'
> >>>>> +
> >>>>> +test_expect_success '--committer-date-is-author-date works with
> >>>>> rebase -r' '
> >>>>> +    git checkout side &&
> >>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> >>>>> +    git rebase -r --root --committer-date-is-author-date &&
> >>>>> +    test_ctime_is_atime
> >>>>> +'
> >>>>> +
> >>>>> +test_expect_success '--committer-date-is-author-date works when
> >>>>> forking merge' '
> >>>>> +    git checkout side &&
> >>>>> +    GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> >>>>> +    PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
> >>>>> +                    --committer-date-is-author-date &&
> >>>>> +    test_ctime_is_atime
> >>>>> +'
> >>>>> +
> >>>>> +test_expect_success '--committer-date-is-author-date works when
> >>>>> committing conflict resolution' '
> >>>>> +    git checkout commit2 &&
> >>>>> +    GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only
> >>>>> --reset-author &&
> >>>>> +    test_must_fail git rebase -m --committer-date-is-author-date \
> >>>>> +        --onto HEAD^^ HEAD^ &&
> >>>>> +    echo resolved > foo &&
> >>>>
> >>>> Nitpick: no space after ">" :D
> >>>>
> >>
> 

-- 
Danh

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v7 2/5] rebase -i: support --committer-date-is-author-date
  2020-07-16 17:32   ` [PATCH v7 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-08-13 13:46     ` Johannes Schindelin
  0 siblings, 0 replies; 130+ messages in thread
From: Johannes Schindelin @ 2020-08-13 13:46 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi Phillip,

On Thu, 16 Jul 2020, Phillip Wood wrote:

> @@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,
>  		commit_list_insert(current_head, &parents);
>  	}
>
> +	if (opts->committer_date_is_author_date) {
> +		struct ident_split ident;
> +		struct strbuf date = STRBUF_INIT;
> +
> +		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
> +			res = error(_("malformed ident line '%s'"), author);
> +			goto out;
> +		}
> +		if (!ident.date_begin) {
> +			res = error(_("corrupted author without date information"));
> +			goto out;
> +		}
> +
> +		strbuf_addf(&date, "@%.*s %.*s",
> +			    (int)(ident.date_end - ident.date_begin),
> +			    ident.date_begin,
> +			    (int)(ident.tz_end - ident.tz_begin),
> +			    ident.tz_begin);
> +		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);

I am slightly worried that we do not unset this environment variable (or
revert to its previous value, if it had any).

I had a brief look and it seems that there are only two callers of
`commit_tree_extended()` (which uses `git_committer_info(IDENT_STRICT)` to
fill in the committer date), so it _should_ be possible to extend the
signature of `commit_tree_extended()` to specify the committer information
explicitly.

The bigger question is whether we _actually_ need this, and I _think_ that
the answer is "not right now", so I would be fine with the patch as-is.
Just thought that I point it out (and thereby demonstrate that I actually
looked at the patch ;-)).

Ciao,
Dscho

> +		strbuf_release(&date);
> +
> +		if (res)
> +			goto out;
> +	}
> +
>  	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
>  		res = error(_("git write-tree failed to write a tree"));
>  		goto out;
> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
>  			opts->signoff = 1;
>  		}
>
> +		if (file_exists(rebase_path_cdate_is_adate())) {
> +			opts->allow_ff = 0;
> +			opts->committer_date_is_author_date = 1;
> +		}
> +
>  		if (file_exists(rebase_path_reschedule_failed_exec()))
>  			opts->reschedule_failed_exec = 1;
>
> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>  		write_file(rebase_path_drop_redundant_commits(), "%s", "");
>  	if (opts->keep_redundant_commits)
>  		write_file(rebase_path_keep_redundant_commits(), "%s", "");
> +	if (opts->committer_date_is_author_date)
> +		write_file(rebase_path_cdate_is_adate(), "%s", "");
>  	if (opts->reschedule_failed_exec)
>  		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>
> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
>  			goto leave_merge;
>  		}
>
> +		if (opts->committer_date_is_author_date)
> +			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +					 author_date_from_env_array(&cmd.env_array));
> +
>  		cmd.git_cmd = 1;
>  		argv_array_push(&cmd.args, "merge");
>  		argv_array_push(&cmd.args, "-s");
> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
>  	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
>  	if (opts->allow_ff)
>  		assert(!(opts->signoff || opts->no_commit ||
> -				opts->record_origin || opts->edit));
> +				opts->record_origin || opts->edit ||
> +				opts->committer_date_is_author_date));
>  	if (read_and_refresh_cache(r, opts))
>  		return -1;
>
> diff --git a/sequencer.h b/sequencer.h
> index 0bee85093e..4ab94119ae 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -45,6 +45,7 @@ struct replay_opts {
>  	int verbose;
>  	int quiet;
>  	int reschedule_failed_exec;
> +	int committer_date_is_author_date;
>
>  	int mainline;
>
> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
> index 55ca46786d..c8234062c6 100755
> --- a/t/t3422-rebase-incompatible-options.sh
> +++ b/t/t3422-rebase-incompatible-options.sh
> @@ -61,7 +61,6 @@ test_rebase_am_only () {
>  }
>
>  test_rebase_am_only --whitespace=fix
> -test_rebase_am_only --committer-date-is-author-date
>  test_rebase_am_only -C4
>
>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 4f8a6e51c9..50a63d8ebe 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>
>  . "$TEST_DIRECTORY"/lib-rebase.sh
>
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>  # This is a special case in which both am and interactive backends
>  # provide the same output. It was done intentionally because
>  # both the backends fall short of optimal behaviour.
> @@ -21,11 +24,20 @@ test_expect_success 'setup' '
>  	test_write_lines "line 1" "new line 2" "line 3" >file &&
>  	git commit -am "update file" &&
>  	git tag side &&
> +	test_commit commit1 foo foo1 &&
> +	test_commit commit2 foo foo2 &&
> +	test_commit commit3 foo foo3 &&
>
>  	git checkout --orphan master &&
> +	rm foo &&
>  	test_write_lines "line 1" "        line 2" "line 3" >file &&
>  	git commit -am "add file" &&
> -	git tag main
> +	git tag main &&
> +
> +	mkdir test-bin &&
> +	write_script test-bin/git-merge-test <<-\EOF
> +	exec git-merge-recursive "$@"
> +	EOF
>  '
>
>  test_expect_success '--ignore-whitespace works with apply backend' '
> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
>  	git diff --exit-code side
>  '
>
> +test_ctime_is_atime () {
> +	git log $1 --format=%ai >authortime &&
> +	git log $1 --format=%ci >committertime &&
> +	test_cmp authortime committertime
> +}
> +
> +test_expect_success '--committer-date-is-author-date works with apply backend' '
> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +	git rebase --apply --committer-date-is-author-date HEAD^ &&
> +	test_ctime_is_atime -1
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with merge backend' '
> +	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
> +	git rebase -m --committer-date-is-author-date HEAD^ &&
> +	test_ctime_is_atime -1
> +'
> +
> +test_expect_success '--committer-date-is-author-date works with rebase -r' '
> +	git checkout side &&
> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +	git rebase -r --root --committer-date-is-author-date &&
> +	test_ctime_is_atime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when forking merge' '
> +	git checkout side &&
> +	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
> +	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
> +					--committer-date-is-author-date &&
> +	test_ctime_is_atime
> +'
> +
> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
> +	git checkout commit2 &&
> +	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
> +	test_must_fail git rebase -m --committer-date-is-author-date \
> +		--onto HEAD^^ HEAD^ &&
> +	echo resolved > foo &&
> +	git add foo &&
> +	git rebase --continue &&
> +	test_ctime_is_atime -1
> +'
> +
>  # This must be the last test in this file
>  test_expect_success '$EDITOR and friends are unchanged' '
>  	test_editor_unchanged
> --
> 2.27.0
>
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v7 4/5] rebase -i: support --ignore-date
  2020-07-16 17:32   ` [PATCH v7 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-08-13 14:07     ` Johannes Schindelin
  0 siblings, 0 replies; 130+ messages in thread
From: Johannes Schindelin @ 2020-08-13 14:07 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi Phillip,

On Thu, 16 Jul 2020, Phillip Wood wrote:

> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,
>
>  	if (opts->committer_date_is_author_date)
>  		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +				 opts->ignore_date ?
> +				 "" :
>  				 author_date_from_env_array(&cmd.env_array));
> +	if (opts->ignore_date)
> +		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");

Technically, if we switched those two `if` blocks, we would not have to
edit the committer date one. But this way is much clearer.

>
>  	argv_array_push(&cmd.args, "commit");
>
> @@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,
>  			    ident.date_begin,
>  			    (int)(ident.tz_end - ident.tz_begin),
>  			    ident.tz_begin);
> -		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
> +		res = setenv("GIT_COMMITTER_DATE",
> +			     opts->ignore_date ? "" : date.buf, 1);

Isn't this constructing the `date` string for nothing, if
`opts->ignore_date` is set?

I would much rather see it done this way:

-	if (opts->committer_date_is_author_date) {
+	if (opts->committer_date_is_author_date && opts->ignore_date)
+		setenv("GIT_COMMITTER_DATE", "", 1);
+	else if (opts->committer_date_is_author_date) {

Not enough of a reason to re-roll, though.

>  		strbuf_release(&date);
>
>  		if (res)
> @@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,
>
>  	reset_ident_date();
>
> +	if (opts->ignore_date) {
> +		author = ignore_author_date(author);
> +		if (!author) {
> +			res = -1;
> +			goto out;
> +		}
> +		free(author_to_free);

A better cadence might be to first `free(author_to_free)`, then assign
`author = author_to_free = ignore_author_date(author);` (at least in my
perspective, it reads more naturally).

But again, not a big reason for a re-roll.

The rest of the patch looks good to me.

Thank you,
Dscho

> +		author_to_free = (char *)author;

> +	}
> +
>  	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
>  				 oid, author, opts->gpg_sign, extra)) {
>  		res = error(_("failed to write commit object"));
> @@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)
>  			opts->committer_date_is_author_date = 1;
>  		}
>
> +		if (file_exists(rebase_path_ignore_date())) {
> +			opts->allow_ff = 0;
> +			opts->ignore_date = 1;
> +		}
> +
>  		if (file_exists(rebase_path_reschedule_failed_exec()))
>  			opts->reschedule_failed_exec = 1;
>
> @@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
>  		write_file(rebase_path_keep_redundant_commits(), "%s", "");
>  	if (opts->committer_date_is_author_date)
>  		write_file(rebase_path_cdate_is_adate(), "%s", "");
> +	if (opts->ignore_date)
> +		write_file(rebase_path_ignore_date(), "%s", "");
>  	if (opts->reschedule_failed_exec)
>  		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
>
> @@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,
>
>  		if (opts->committer_date_is_author_date)
>  			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
> +					 opts->ignore_date ?
> +					 "" :
>  					 author_date_from_env_array(&cmd.env_array));
> +		if (opts->ignore_date)
> +			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
>
>  		cmd.git_cmd = 1;
>  		argv_array_push(&cmd.args, "merge");
> @@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,
>  	if (opts->allow_ff)
>  		assert(!(opts->signoff || opts->no_commit ||
>  				opts->record_origin || opts->edit ||
> -				opts->committer_date_is_author_date));
> +				opts->committer_date_is_author_date ||
> +				opts->ignore_date));
>  	if (read_and_refresh_cache(r, opts))
>  		return -1;
>
> diff --git a/sequencer.h b/sequencer.h
> index 4ab94119ae..3587878e3b 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -46,6 +46,7 @@ struct replay_opts {
>  	int quiet;
>  	int reschedule_failed_exec;
>  	int committer_date_is_author_date;
> +	int ignore_date;
>
>  	int mainline;
>
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 50a63d8ebe..0ede2b8900 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl
>  	test_ctime_is_atime -1
>  '
>
> +# Checking for +0000 in the author date is sufficient since the
> +# default timezone is UTC but the timezone used while committing is
> +# +0530. The inverted logic in the grep is necessary to check all the
> +# author dates in the file.
> +test_ctime_is_ignored () {
> +	git log $1 --format=%ai >authortime &&
> +	! grep -v +0000 authortime
> +}
> +
> +test_expect_success '--ignore-date works with apply backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --apply --ignore-date HEAD^ &&
> +	test_ctime_is_ignored -1
> +'
> +
> +test_expect_success '--ignore-date works with merge backend' '
> +	git commit --amend --date="$GIT_AUTHOR_DATE" &&
> +	git rebase --ignore-date -m HEAD^ &&
> +	test_ctime_is_ignored -1
> +'
> +
> +test_expect_success '--ignore-date works after conflict resolution' '
> +	test_must_fail git rebase --ignore-date -m \
> +		--onto commit2^^ commit2^ commit2 &&
> +	echo resolved >foo &&
> +	git add foo &&
> +	git rebase --continue &&
> +	test_ctime_is_ignored -1
> +'
> +
> +test_expect_success '--ignore-date works with rebase -r' '
> +	git checkout side &&
> +	git merge --no-ff commit3 &&
> +	git rebase -r --root --ignore-date &&
> +	test_ctime_is_ignored
> +'
> +
> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '
> +	test_must_fail git rebase -m --committer-date-is-author-date \
> +		--ignore-date --onto commit2^^ commit2^ commit3 &&
> +	git checkout --theirs foo &&
> +	git add foo &&
> +	git rebase --continue &&
> +	test_ctime_is_atime -2 &&
> +	test_ctime_is_ignored -2
> +'
> +
> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
> +	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
> +		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
> +				--ignore-date --committer-date-is-author-date \
> +				side side &&
> +	test_ctime_is_atime -1 &&
> +	test_ctime_is_ignored -1
> + '
> +
>  # This must be the last test in this file
>  test_expect_success '$EDITOR and friends are unchanged' '
>  	test_editor_unchanged
> --
> 2.27.0
>
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
                     ` (5 preceding siblings ...)
  2020-07-16 17:39   ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
@ 2020-08-13 14:24   ` Johannes Schindelin
  2020-08-13 17:46     ` Junio C Hamano
  6 siblings, 1 reply; 130+ messages in thread
From: Johannes Schindelin @ 2020-08-13 14:24 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Junio C Hamano, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Hi Phillip,

On Thu, 16 Jul 2020, Phillip Wood wrote:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Danh pointed out that the word "ident" gets misinterpreted by
> translators as "indentation" leading to incorrect translations so I've
> reworded an error message.
>
> format-patch and am could do with having their similar messages
> updated in the future

Thank you for this patch series!

To be honest, my hope was that I would get support for `git rebase -i
--whitespace=fix` out of that GSoC project... but I take what I can get,
and this patch series is in a pretty good shape.

I offered three small suggestions how I think it could be improved, still,
but I would be pretty happy with seeing the patches moving to `next`
as-are.

Thank you,
Dscho

>
> Phillip Wood (2):
>   rebase -i: support --committer-date-is-author-date
>   rebase -i: support --ignore-date
>
> Rohit Ashiwal (3):
>   rebase -i: add --ignore-whitespace flag
>   sequencer: rename amend_author to author_to_free
>   rebase: add --reset-author-date
>
>  Documentation/git-rebase.txt           |  33 ++++-
>  builtin/rebase.c                       |  47 +++++--
>  sequencer.c                            | 112 ++++++++++++++-
>  sequencer.h                            |   2 +
>  t/t3422-rebase-incompatible-options.sh |   2 -
>  t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++
>  6 files changed, 353 insertions(+), 23 deletions(-)
>  create mode 100755 t/t3436-rebase-more-options.sh
>
> Range-diff against v6:
> 1:  0fc90eaff1 ! 1:  3865fdf461 rebase -i: support --ignore-date
>     @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr
>      +	struct strbuf new_author = STRBUF_INIT;
>      +
>      +	if (split_ident_line(&ident, author, strlen(author)) < 0) {
>     -+		error(_("malformed ident line '%s'"), author);
>     ++		error(_("invalid author identity: %s"), author);
>      +		return NULL;
>      +	}
>      +
> 2:  21cf5e5512 = 2:  0b6b19cb68 rebase: add --reset-author-date
> --
> 2.27.0
>
>

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options
  2020-08-13 14:24   ` Johannes Schindelin
@ 2020-08-13 17:46     ` Junio C Hamano
  2020-08-13 19:51       ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-08-13 17:46 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Phillip Wood, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> I offered three small suggestions how I think it could be improved, still,
> but I would be pretty happy with seeing the patches moving to `next`
> as-are.

I tend to agree with those points I saw you mentioned.

The unconditional exporting of the committer-date without undoing
looked like a bad pattern waiting to be copied and pasted.  I
have not yet fully followed the codepath but I tend to agree with
your suspicion that commit_tree_extended() might be a better place
to do this.

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options
  2020-08-13 17:46     ` Junio C Hamano
@ 2020-08-13 19:51       ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-08-13 19:51 UTC (permalink / raw)
  To: Junio C Hamano, Johannes Schindelin
  Cc: Phillip Wood, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

On 13/08/2020 18:46, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
>> I offered three small suggestions how I think it could be improved, still,
>> but I would be pretty happy with seeing the patches moving to `next`
>> as-are.
> 
> I tend to agree with those points I saw you mentioned.
> 
> The unconditional exporting of the committer-date without undoing
> looked like a bad pattern waiting to be copied and pasted. 

I think it is copied and pasted from builtin/am.c

> I have not yet fully followed the codepath but I tend to agree with
> your suspicion that commit_tree_extended() might be a better place
> to do this.

It looks like it should be simple enough to do that, I'll reroll

Thanks for your comments dscho

Phillip

> Thanks.
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v8 0/5] cleanup ra/rebase-i-more-options
  2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
                   ` (13 preceding siblings ...)
  2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
@ 2020-08-17 17:39 ` Phillip Wood
  2020-08-17 17:40   ` [PATCH v8 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
                     ` (4 more replies)
  14 siblings, 5 replies; 130+ messages in thread
From: Phillip Wood @ 2020-08-17 17:39 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Thanks to dscho for his comments on v7. Patch 2 is new, it extends
commit_tree_extended() to take an explicit committer and changes am to
use that rather than exporting GIT_COMMITTER_DATE. The old patch 3 is
gone as it renamed a variable in preparation for repurposing it in the
next patch but it is no longer repurposed. The changes in patches 3 &
4 use the new argument to commit_tree_extended() rather than exporting
GIT_COMMITTER_DATE in try_to_commit().

Phillip Wood (3):
  am: stop exporting GIT_COMMITTER_DATE
  rebase -i: support --committer-date-is-author-date
  rebase -i: support --ignore-date

Rohit Ashiwal (2):
  rebase -i: add --ignore-whitespace flag
  rebase: add --reset-author-date

 Documentation/git-rebase.txt           |  33 ++++-
 builtin/am.c                           |  28 +++-
 builtin/commit.c                       |   4 +-
 builtin/rebase.c                       |  47 +++++--
 commit.c                               |  11 +-
 commit.h                               |   7 +-
 ident.c                                |  24 ++--
 sequencer.c                            | 130 +++++++++++++++++-
 sequencer.h                            |   4 +
 t/t3422-rebase-incompatible-options.sh |   2 -
 t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++
 11 files changed, 422 insertions(+), 48 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

Range-diff against v7:
1:  5bb4226007 = 1:  5bb4226007 rebase -i: add --ignore-whitespace flag
-:  ---------- > 2:  33f62dd2a0 am: stop exporting GIT_COMMITTER_DATE
2:  e5fdb574ed ! 3:  34431945c8 rebase -i: support --committer-date-is-author-date
    @@ Documentation/git-rebase.txt: if the other side had no changes that conflicted.
      --committer-date-is-author-date::
     +	Instead of using the current time as the committer date, use
     +	the author date of the commit being rebased as the committer
    -+	date. This option implies --force-rebase.
    ++	date. This option implies `--force-rebase`.
     +
      --ignore-date::
     -	These flags are passed to 'git am' to easily change the dates
    @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs
      static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
      static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
      static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
    +@@ sequencer.c: int sequencer_remove_state(struct replay_opts *opts)
    + 		}
    + 	}
    + 
    ++	free(opts->committer_name);
    ++	free(opts->committer_email);
    + 	free(opts->gpg_sign);
    + 	free(opts->strategy);
    + 	for (i = 0; i < opts->xopts_nr; i++)
     @@ sequencer.c: static char *get_author(const char *message)
      	return NULL;
      }
    @@ sequencer.c: static int run_git_commit(struct repository *r,
      
      	if (!(flags & VERIFY_MSG))
     @@ sequencer.c: static int try_to_commit(struct repository *r,
    - 		commit_list_insert(current_head, &parents);
    + 	struct strbuf err = STRBUF_INIT;
    + 	struct strbuf commit_msg = STRBUF_INIT;
    + 	char *amend_author = NULL;
    ++	const char *committer = NULL;
    + 	const char *hook_commit = NULL;
    + 	enum commit_msg_cleanup_mode cleanup;
    + 	int res = 0;
    +@@ sequencer.c: static int try_to_commit(struct repository *r,
    + 		goto out;
      	}
      
    +-	reset_ident_date();
     +	if (opts->committer_date_is_author_date) {
    -+		struct ident_split ident;
    ++		struct ident_split id;
     +		struct strbuf date = STRBUF_INIT;
     +
    -+		if (split_ident_line(&ident, author, (int)strlen(author)) < 0) {
    -+			res = error(_("malformed ident line '%s'"), author);
    ++		if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
    ++			res = error(_("invalid author identity '%s'"), author);
     +			goto out;
     +		}
    -+		if (!ident.date_begin) {
    -+			res = error(_("corrupted author without date information"));
    ++		if (!id.date_begin) {
    ++			res = error(_("corrupt author: missing date information"));
     +			goto out;
     +		}
    -+
     +		strbuf_addf(&date, "@%.*s %.*s",
    -+			    (int)(ident.date_end - ident.date_begin),
    -+			    ident.date_begin,
    -+			    (int)(ident.tz_end - ident.tz_begin),
    -+			    ident.tz_begin);
    -+		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
    ++			    (int)(id.date_end - id.date_begin), id.date_begin,
    ++			    (int)(id.tz_end - id.tz_begin), id.tz_begin);
    ++		committer = fmt_ident(opts->committer_name,
    ++				      opts->committer_email,
    ++				      WANT_COMMITTER_IDENT, date.buf,
    ++				      IDENT_STRICT);
     +		strbuf_release(&date);
    -+
    -+		if (res)
    -+			goto out;
    ++	} else {
    ++		reset_ident_date();
     +	}
    -+
    - 	if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {
    - 		res = error(_("git write-tree failed to write a tree"));
    + 
    + 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,
    +-				 author, NULL, opts->gpg_sign, extra)) {
    ++				 author, committer, opts->gpg_sign, extra)) {
    + 		res = error(_("failed to write commit object"));
      		goto out;
    + 	}
     @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)
      			opts->signoff = 1;
      		}
    @@ sequencer.c: static int pick_commits(struct repository *r,
      	if (opts->allow_ff)
      		assert(!(opts->signoff || opts->no_commit ||
     -				opts->record_origin || opts->edit));
    -+				opts->record_origin || opts->edit ||
    -+				opts->committer_date_is_author_date));
    ++			 opts->record_origin || opts->edit ||
    ++			 opts->committer_date_is_author_date));
      	if (read_and_refresh_cache(r, opts))
      		return -1;
      
    +@@ sequencer.c: static int commit_staged_changes(struct repository *r,
    + 	return 0;
    + }
    + 
    ++static int init_committer(struct replay_opts *opts)
    ++{
    ++	struct ident_split id;
    ++	const char *committer;
    ++
    ++	committer = git_committer_info(IDENT_STRICT);
    ++	if (split_ident_line(&id, committer, strlen(committer)) < 0)
    ++		return error(_("invalid committer '%s'"), committer);
    ++	opts->committer_name =
    ++		xmemdupz(id.name_begin, id.name_end - id.name_begin);
    ++	opts->committer_email =
    ++		xmemdupz(id.mail_begin, id.mail_end - id.mail_end);
    ++
    ++	return 0;
    ++}
    ++
    + int sequencer_continue(struct repository *r, struct replay_opts *opts)
    + {
    + 	struct todo_list todo_list = TODO_LIST_INIT;
    +@@ sequencer.c: int sequencer_continue(struct repository *r, struct replay_opts *opts)
    + 	if (read_populate_opts(opts))
    + 		return -1;
    + 	if (is_rebase_i(opts)) {
    ++		if (opts->committer_date_is_author_date && init_committer(opts))
    ++			return -1;
    ++
    + 		if ((res = read_populate_todo(r, &todo_list, opts)))
    + 			goto release_todo_list;
    + 
    +@@ sequencer.c: int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
    + 
    + 	res = -1;
    + 
    ++	if (opts->committer_date_is_author_date && init_committer(opts))
    ++		goto cleanup;
    ++
    + 	if (checkout_onto(r, opts, onto_name, &oid, orig_head))
    + 		goto cleanup;
    + 
     
      ## sequencer.h ##
     @@ sequencer.h: struct replay_opts {
    @@ sequencer.h: struct replay_opts {
      
      	int mainline;
      
    ++	char *committer_name;
    ++	char *committer_email;
    + 	char *gpg_sign;
    + 	enum commit_msg_cleanup_mode default_msg_cleanup;
    + 	int explicit_cleanup;
     
      ## t/t3422-rebase-incompatible-options.sh ##
     @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {
3:  cf5c9a2456 < -:  ---------- sequencer: rename amend_author to author_to_free
4:  3865fdf461 ! 4:  060c0ea2d0 rebase -i: support --ignore-date
    @@ Commit message
     
      ## Documentation/git-rebase.txt ##
     @@ Documentation/git-rebase.txt: See also INCOMPATIBLE OPTIONS below.
    - 	date. This option implies --force-rebase.
    + 	date. This option implies `--force-rebase`.
      
      --ignore-date::
     -	This flag is passed to 'git am' to change the author date
    @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs
      static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
      static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
      static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
    -@@ sequencer.c: static const char *author_date_from_env_array(const struct argv_array *env)
    - 	BUG("GIT_AUTHOR_DATE missing from author script");
    - }
    - 
    -+/* Construct a free()able author string with current time as the author date */
    -+static char *ignore_author_date(const char *author)
    -+{
    -+	int len;
    -+	struct ident_split ident;
    -+	struct strbuf new_author = STRBUF_INIT;
    -+
    -+	if (split_ident_line(&ident, author, strlen(author)) < 0) {
    -+		error(_("invalid author identity: %s"), author);
    -+		return NULL;
    -+	}
    -+
    -+	len = ident.mail_end - ident.name_begin + 1;
    -+	strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
    -+	datestamp(&new_author);
    -+	return strbuf_detach(&new_author, NULL);
    -+}
    -+
    - static const char staged_changes_advice[] =
    - N_("you have staged changes in your working tree\n"
    - "If these changes are meant to be squashed into the previous commit, run:\n"
     @@ sequencer.c: static int run_git_commit(struct repository *r,
      
      	if (opts->committer_date_is_author_date)
    @@ sequencer.c: static int run_git_commit(struct repository *r,
      	argv_array_push(&cmd.args, "commit");
      
     @@ sequencer.c: static int try_to_commit(struct repository *r,
    - 			    ident.date_begin,
    - 			    (int)(ident.tz_end - ident.tz_begin),
    - 			    ident.tz_begin);
    --		res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
    -+		res = setenv("GIT_COMMITTER_DATE",
    -+			     opts->ignore_date ? "" : date.buf, 1);
    + 		struct ident_split id;
    + 		struct strbuf date = STRBUF_INIT;
    + 
    +-		if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
    +-			res = error(_("invalid author identity '%s'"), author);
    +-			goto out;
    ++		if (!opts->ignore_date) {
    ++			if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
    ++				res = error(_("invalid author identity '%s'"),
    ++					    author);
    ++				goto out;
    ++			}
    ++			if (!id.date_begin) {
    ++				res = error(_(
    ++					"corrupt author: missing date information"));
    ++				goto out;
    ++			}
    ++			strbuf_addf(&date, "@%.*s %.*s",
    ++				    (int)(id.date_end - id.date_begin),
    ++				    id.date_begin,
    ++				    (int)(id.tz_end - id.tz_begin),
    ++				    id.tz_begin);
    ++		} else {
    ++			reset_ident_date();
    + 		}
    +-		if (!id.date_begin) {
    +-			res = error(_("corrupt author: missing date information"));
    +-			goto out;
    +-		}
    +-		strbuf_addf(&date, "@%.*s %.*s",
    +-			    (int)(id.date_end - id.date_begin), id.date_begin,
    +-			    (int)(id.tz_end - id.tz_begin), id.tz_begin);
    + 		committer = fmt_ident(opts->committer_name,
    + 				      opts->committer_email,
    +-				      WANT_COMMITTER_IDENT, date.buf,
    ++				      WANT_COMMITTER_IDENT,
    ++				      opts->ignore_date ? NULL : date.buf,
    + 				      IDENT_STRICT);
      		strbuf_release(&date);
    - 
    - 		if (res)
    -@@ sequencer.c: static int try_to_commit(struct repository *r,
    - 
    - 	reset_ident_date();
    + 	} else {
    + 		reset_ident_date();
    + 	}
      
     +	if (opts->ignore_date) {
    -+		author = ignore_author_date(author);
    -+		if (!author) {
    -+			res = -1;
    ++		struct ident_split id;
    ++		char *name, *email;
    ++
    ++		if (split_ident_line(&id, author, strlen(author)) < 0) {
    ++			error(_("invalid author identity '%s'"), author);
     +			goto out;
     +		}
    -+		free(author_to_free);
    -+		author_to_free = (char *)author;
    ++		name = xmemdupz(id.name_begin, id.name_end - id.name_begin);
    ++		email = xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
    ++		author = fmt_ident(name, email, WANT_AUTHOR_IDENT, NULL,
    ++				   IDENT_STRICT);
    ++		free(name);
    ++		free(email);
     +	}
     +
    - 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
    - 				 oid, author, opts->gpg_sign, extra)) {
    + 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,
    + 				 author, committer, opts->gpg_sign, extra)) {
      		res = error(_("failed to write commit object"));
     @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)
      			opts->committer_date_is_author_date = 1;
    @@ sequencer.c: static int do_merge(struct repository *r,
     @@ sequencer.c: static int pick_commits(struct repository *r,
      	if (opts->allow_ff)
      		assert(!(opts->signoff || opts->no_commit ||
    - 				opts->record_origin || opts->edit ||
    --				opts->committer_date_is_author_date));
    -+				opts->committer_date_is_author_date ||
    -+				opts->ignore_date));
    + 			 opts->record_origin || opts->edit ||
    +-			 opts->committer_date_is_author_date));
    ++			 opts->committer_date_is_author_date ||
    ++			 opts->ignore_date));
      	if (read_and_refresh_cache(r, opts))
      		return -1;
      
5:  0b6b19cb68 ! 5:  92ed3bed9f rebase: add --reset-author-date
    @@ Commit message
     
      ## Documentation/git-rebase.txt ##
     @@ Documentation/git-rebase.txt: See also INCOMPATIBLE OPTIONS below.
    - 	date. This option implies --force-rebase.
    + 	date. This option implies `--force-rebase`.
      
      --ignore-date::
     +--reset-author-date::
-- 
2.28.0


^ permalink raw reply	[flat|nested] 130+ messages in thread

* [PATCH v8 1/5] rebase -i: add --ignore-whitespace flag
  2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
@ 2020-08-17 17:40   ` Phillip Wood
  2020-08-17 17:40   ` [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE Phillip Wood
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-08-17 17:40 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--ignore-whitespace option to the merge backend. This option treats
lines with only whitespace changes as unchanged and is implemented in
the merge backend by translating it to -Xignore-space-change.

Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 19 +++++++-
 builtin/rebase.c                       | 19 ++++++--
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++
 4 files changed, 93 insertions(+), 6 deletions(-)
 create mode 100755 t/t3436-rebase-more-options.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f7a6033607..b003784f01 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
 with `--keep-base` in order to drop those commits from your branch.
 
 --ignore-whitespace::
+	Ignore whitespace differences when trying to reconcile
+differences. Currently, each backend implements an approximation of
+this behavior:
++
+apply backend: When applying a patch, ignore changes in whitespace in
+context lines. Unfortunately, this means that if the "old" lines being
+replaced by the patch differ only in whitespace from the existing
+file, you will get a merge conflict instead of a successful patch
+application.
++
+merge backend: Treat lines with only whitespace changes as unchanged
+when merging. Unfortunately, this means that any patch hunks that were
+intended to modify whitespace and nothing else will be dropped, even
+if the other side had no changes that conflicted.
+
 --whitespace=<option>::
-	These flags are passed to the 'git apply' program
+	This flag is passed to the 'git apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 	Implies --apply.
 +
@@ -572,7 +587,6 @@ The following options:
  * --apply
  * --committer-date-is-author-date
  * --ignore-date
- * --ignore-whitespace
  * --whitespace
  * -C
 
@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --signoff
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
+ * --preserve-merges and --ignore-whitespace
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 27a07d4e78..bd93e9742c 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
+
 	if (opts->strategy_opts)
 		parse_strategy_opts(&replay, opts->strategy_opts);
 
@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct strbuf revisions = STRBUF_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id merge_base;
+	int ignore_whitespace = 0;
 	enum action action = ACTION_NONE;
 	const char *gpg_sign = NULL;
 	struct string_list exec = STRING_LIST_INIT_NODUP;
@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
-				  NULL, N_("passed to 'git am'"),
-				  PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
 				  &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
+		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
+			 N_("ignore changes in whitespace")),
 		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
 				  N_("action"), N_("passed to 'git apply'"), 0),
 		OPT_BIT('f', "force-rebase", &options.flags,
@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		imply_merge(&options, "--rebase-merges");
 	}
 
+	if (options.type == REBASE_APPLY) {
+		if (ignore_whitespace)
+			argv_array_push(&options.git_am_opts,
+					"--ignore-whitespace");
+	} else {
+		/* REBASE_MERGE and PRESERVE_MERGES */
+		if (ignore_whitespace) {
+			string_list_append(&strategy_options,
+					   "ignore-space-change");
+		}
+	}
+
 	if (strategy_options.nr) {
 		int i;
 
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 50e7960702..55ca46786d 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --ignore-whitespace
 test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
new file mode 100755
index 0000000000..4f8a6e51c9
--- /dev/null
+++ b/t/t3436-rebase-more-options.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Rohit Ashiwal
+#
+
+test_description='tests to ensure compatibility between am and interactive backends'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# This is a special case in which both am and interactive backends
+# provide the same output. It was done intentionally because
+# both the backends fall short of optimal behaviour.
+test_expect_success 'setup' '
+	git checkout -b topic &&
+	test_write_lines "line 1" "	line 2" "line 3" >file &&
+	git add file &&
+	git commit -m "add file" &&
+
+	test_write_lines "line 1" "new line 2" "line 3" >file &&
+	git commit -am "update file" &&
+	git tag side &&
+
+	git checkout --orphan master &&
+	test_write_lines "line 1" "        line 2" "line 3" >file &&
+	git commit -am "add file" &&
+	git tag main
+'
+
+test_expect_success '--ignore-whitespace works with apply backend' '
+	test_must_fail git rebase --apply main side &&
+	git rebase --abort &&
+	git rebase --apply --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace works with merge backend' '
+	test_must_fail git rebase --merge main side &&
+	git rebase --abort &&
+	git rebase --merge --ignore-whitespace main side &&
+	git diff --exit-code side
+'
+
+test_expect_success '--ignore-whitespace is remembered when continuing' '
+	(
+		set_fake_editor &&
+		FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
+			main side &&
+		git rebase --continue
+	) &&
+	git diff --exit-code side
+'
+
+# This must be the last test in this file
+test_expect_success '$EDITOR and friends are unchanged' '
+	test_editor_unchanged
+'
+
+test_done
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE
  2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
  2020-08-17 17:40   ` [PATCH v8 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
@ 2020-08-17 17:40   ` Phillip Wood
  2020-08-17 19:12     ` Junio C Hamano
  2020-08-17 17:40   ` [PATCH v8 3/5] rebase -i: support --committer-date-is-author-date Phillip Wood
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-08-17 17:40 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

The implementation of --committer-date-is-author-date exports
GIT_COMMITTER_DATE to override the default committer date but does not
reset GIT_COMMITTER_DATE in the environment after creating the commit
so it is set in the environment of any hooks that get run. We're about
to add the same functionality to the sequencer and do not want to have
GIT_COMMITTER_DATE set when running hooks or exec commands so lets
update commit_tree_extended() to take an explicit committer so we
override the default date without setting GIT_COMMITTER_DATE in the
environment.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 builtin/am.c     | 28 +++++++++++++++++++++++-----
 builtin/commit.c |  4 ++--
 commit.c         | 11 +++++++----
 commit.h         |  7 +++----
 ident.c          | 24 ++++++++++++++----------
 sequencer.c      |  4 ++--
 6 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/builtin/am.c b/builtin/am.c
index e3dfd93c25..896cd0f827 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -98,6 +98,8 @@ struct am_state {
 	char *author_name;
 	char *author_email;
 	char *author_date;
+	char *committer_name;
+	char *committer_email;
 	char *msg;
 	size_t msg_len;
 
@@ -130,6 +132,8 @@ struct am_state {
  */
 static void am_state_init(struct am_state *state)
 {
+	const char *committer;
+	struct ident_split id;
 	int gpgsign;
 
 	memset(state, 0, sizeof(*state));
@@ -150,6 +154,14 @@ static void am_state_init(struct am_state *state)
 
 	if (!git_config_get_bool("commit.gpgsign", &gpgsign))
 		state->sign_commit = gpgsign ? "" : NULL;
+
+	committer = git_committer_info(IDENT_STRICT);
+	if (split_ident_line(&id, committer, strlen(committer)) < 0)
+		die(_("invalid committer: %s"), committer);
+	state->committer_name =
+		xmemdupz(id.name_begin, id.name_end - id.name_begin);
+	state->committer_email =
+		xmemdupz(id.mail_begin, id.mail_end - id.mail_end);
 }
 
 /**
@@ -161,6 +173,8 @@ static void am_state_release(struct am_state *state)
 	free(state->author_name);
 	free(state->author_email);
 	free(state->author_date);
+	free(state->committer_name);
+	free(state->committer_email);
 	free(state->msg);
 	argv_array_clear(&state->git_apply_opts);
 }
@@ -1556,7 +1570,7 @@ static void do_commit(const struct am_state *state)
 	struct object_id tree, parent, commit;
 	const struct object_id *old_oid;
 	struct commit_list *parents = NULL;
-	const char *reflog_msg, *author;
+	const char *reflog_msg, *author, *committer = NULL;
 	struct strbuf sb = STRBUF_INIT;
 
 	if (run_hook_le(NULL, "pre-applypatch", NULL))
@@ -1580,11 +1594,15 @@ static void do_commit(const struct am_state *state)
 			IDENT_STRICT);
 
 	if (state->committer_date_is_author_date)
-		setenv("GIT_COMMITTER_DATE",
-			state->ignore_date ? "" : state->author_date, 1);
+		committer = fmt_ident(state->committer_name,
+				      state->author_email, WANT_COMMITTER_IDENT,
+				      state->ignore_date ? NULL
+							 : state->author_date,
+				      IDENT_STRICT);
 
-	if (commit_tree(state->msg, state->msg_len, &tree, parents, &commit,
-			author, state->sign_commit))
+	if (commit_tree_extended(state->msg, state->msg_len, &tree, parents,
+				 &commit, author, committer, state->sign_commit,
+				 NULL))
 		die(_("failed to write commit object"));
 
 	reflog_msg = getenv("GIT_REFLOG_ACTION");
diff --git a/builtin/commit.c b/builtin/commit.c
index d3e7781e65..2785344fed 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1675,8 +1675,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 	}
 
 	if (commit_tree_extended(sb.buf, sb.len, &active_cache_tree->oid,
-				 parents, &oid, author_ident.buf, sign_commit,
-				 extra)) {
+				 parents, &oid, author_ident.buf, NULL,
+				 sign_commit, extra)) {
 		rollback_index_files();
 		die(_("failed to write commit object"));
 	}
diff --git a/commit.c b/commit.c
index c7099daeac..fb63c22cc1 100644
--- a/commit.c
+++ b/commit.c
@@ -1324,8 +1324,8 @@ int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,
 	int result;
 
 	append_merge_tag_headers(parents, &tail);
-	result = commit_tree_extended(msg, msg_len, tree, parents, ret,
-				      author, sign_commit, extra);
+	result = commit_tree_extended(msg, msg_len, tree, parents, ret, author,
+				      NULL, sign_commit, extra);
 	free_commit_extra_headers(extra);
 	return result;
 }
@@ -1448,7 +1448,8 @@ N_("Warning: commit message did not conform to UTF-8.\n"
 int commit_tree_extended(const char *msg, size_t msg_len,
 			 const struct object_id *tree,
 			 struct commit_list *parents, struct object_id *ret,
-			 const char *author, const char *sign_commit,
+			 const char *author, const char *committer,
+			 const char *sign_commit,
 			 struct commit_extra_header *extra)
 {
 	int result;
@@ -1481,7 +1482,9 @@ int commit_tree_extended(const char *msg, size_t msg_len,
 	if (!author)
 		author = git_author_info(IDENT_STRICT);
 	strbuf_addf(&buffer, "author %s\n", author);
-	strbuf_addf(&buffer, "committer %s\n", git_committer_info(IDENT_STRICT));
+	if (!committer)
+		committer = git_committer_info(IDENT_STRICT);
+	strbuf_addf(&buffer, "committer %s\n", committer);
 	if (!encoding_is_utf8)
 		strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding);
 
diff --git a/commit.h b/commit.h
index 008a0fa4a0..8f4227ae5c 100644
--- a/commit.h
+++ b/commit.h
@@ -316,10 +316,9 @@ int commit_tree(const char *msg, size_t msg_len,
 
 int commit_tree_extended(const char *msg, size_t msg_len,
 			 const struct object_id *tree,
-			 struct commit_list *parents,
-			 struct object_id *ret, const char *author,
-			 const char *sign_commit,
-			 struct commit_extra_header *);
+			 struct commit_list *parents, struct object_id *ret,
+			 const char *author, const char *committer,
+			 const char *sign_commit, struct commit_extra_header *);
 
 struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
 
diff --git a/ident.c b/ident.c
index e666ee4e59..7cbf223350 100644
--- a/ident.c
+++ b/ident.c
@@ -361,11 +361,15 @@ N_("\n"
 const char *fmt_ident(const char *name, const char *email,
 		      enum want_ident whose_ident, const char *date_str, int flag)
 {
-	static struct strbuf ident = STRBUF_INIT;
+	static int index;
+	static struct strbuf ident_pool[2] = { STRBUF_INIT, STRBUF_INIT };
 	int strict = (flag & IDENT_STRICT);
 	int want_date = !(flag & IDENT_NO_DATE);
 	int want_name = !(flag & IDENT_NO_NAME);
 
+	struct strbuf *ident = &ident_pool[index];
+	index = (index + 1) % ARRAY_SIZE(ident_pool);
+
 	if (!email) {
 		if (whose_ident == WANT_AUTHOR_IDENT && git_author_email.len)
 			email = git_author_email.buf;
@@ -421,25 +425,25 @@ const char *fmt_ident(const char *name, const char *email,
 			die(_("name consists only of disallowed characters: %s"), name);
 	}
 
-	strbuf_reset(&ident);
+	strbuf_reset(ident);
 	if (want_name) {
-		strbuf_addstr_without_crud(&ident, name);
-		strbuf_addstr(&ident, " <");
+		strbuf_addstr_without_crud(ident, name);
+		strbuf_addstr(ident, " <");
 	}
-	strbuf_addstr_without_crud(&ident, email);
+	strbuf_addstr_without_crud(ident, email);
 	if (want_name)
-			strbuf_addch(&ident, '>');
+		strbuf_addch(ident, '>');
 	if (want_date) {
-		strbuf_addch(&ident, ' ');
+		strbuf_addch(ident, ' ');
 		if (date_str && date_str[0]) {
-			if (parse_date(date_str, &ident) < 0)
+			if (parse_date(date_str, ident) < 0)
 				die(_("invalid date format: %s"), date_str);
 		}
 		else
-			strbuf_addstr(&ident, ident_default_date());
+			strbuf_addstr(ident, ident_default_date());
 	}
 
-	return ident.buf;
+	return ident->buf;
 }
 
 const char *fmt_name(enum want_ident whose_ident)
diff --git a/sequencer.c b/sequencer.c
index 6fd2674632..968a2d4ef3 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1408,8 +1408,8 @@ static int try_to_commit(struct repository *r,
 
 	reset_ident_date();
 
-	if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
-				 oid, author, opts->gpg_sign, extra)) {
+	if (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,
+				 author, NULL, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
 		goto out;
 	}
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v8 3/5] rebase -i: support --committer-date-is-author-date
  2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
  2020-08-17 17:40   ` [PATCH v8 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
  2020-08-17 17:40   ` [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE Phillip Wood
@ 2020-08-17 17:40   ` Phillip Wood
  2020-08-26 21:41     ` Junio C Hamano
  2020-08-17 17:40   ` [PATCH v8 4/5] rebase -i: support --ignore-date Phillip Wood
  2020-08-17 17:40   ` [PATCH v8 5/5] rebase: add --reset-author-date Phillip Wood
  4 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-08-17 17:40 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the
--committer-date-is-author-date option to the merge backend. This
option uses the author date of the commit that is being rewritten as
the committer date when the new commit is created.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt           | 10 ++-
 builtin/rebase.c                       | 17 +++--
 sequencer.c                            | 86 +++++++++++++++++++++++++-
 sequencer.h                            |  3 +
 t/t3422-rebase-incompatible-options.sh |  1 -
 t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++-
 6 files changed, 162 insertions(+), 13 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b003784f01..f9ddfe2e77 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.
 See also INCOMPATIBLE OPTIONS below.
 
 --committer-date-is-author-date::
+	Instead of using the current time as the committer date, use
+	the author date of the commit being rebased as the committer
+	date. This option implies `--force-rebase`.
+
 --ignore-date::
-	These flags are passed to 'git am' to easily change the dates
-	of the rebased commits (see linkgit:git-am[1]).
+	This flag is passed to 'git am' to change the author date
+	of each rebased commit (see linkgit:git-am[1]).
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --committer-date-is-author-date
  * --ignore-date
  * --whitespace
  * -C
@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --rebase-merges
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
+ * --preserve-merges and --committer-date-is-author-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index bd93e9742c..2579380729 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -88,6 +88,7 @@ struct rebase_options {
 	int autosquash;
 	char *gpg_sign_opt;
 	int autostash;
+	int committer_date_is_author_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
+	replay.committer_date_is_author_date =
+					opts->committer_date_is_author_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
 			 N_("add a Signed-off-by: line to each commit")),
-		OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
-				  &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "committer-date-is-author-date",
+			 &options.committer_date_is_author_date,
+			 N_("make committer date match author date")),
 		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
 				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
+	if (options.committer_date_is_author_date)
+		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--committer-date-is-author-date") ||
-		    !strcmp(option, "--ignore-date") ||
+		if (!strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (ignore_whitespace)
 			argv_array_push(&options.git_am_opts,
 					"--ignore-whitespace");
+		if (options.committer_date_is_author_date)
+			argv_array_push(&options.git_am_opts,
+					"--committer-date-is-author-date");
 	} else {
 		/* REBASE_MERGE and PRESERVE_MERGES */
 		if (ignore_whitespace) {
diff --git a/sequencer.c b/sequencer.c
index 968a2d4ef3..78d09f9252 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  * command-line.
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -302,6 +303,8 @@ int sequencer_remove_state(struct replay_opts *opts)
 		}
 	}
 
+	free(opts->committer_name);
+	free(opts->committer_email);
 	free(opts->gpg_sign);
 	free(opts->strategy);
 	for (i = 0; i < opts->xopts_nr; i++)
@@ -872,6 +875,22 @@ static char *get_author(const char *message)
 	return NULL;
 }
 
+static const char *author_date_from_env_array(const struct argv_array *env)
+{
+	int i;
+	const char *date;
+
+	for (i = 0; i < env->argc; i++)
+		if (skip_prefix(env->argv[i],
+				"GIT_AUTHOR_DATE=", &date))
+			return date;
+	/*
+	 * If GIT_AUTHOR_DATE is missing we should have already errored out when
+	 * reading the script
+	 */
+	BUG("GIT_AUTHOR_DATE missing from author script");
+}
+
 static const char staged_changes_advice[] =
 N_("you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -938,6 +957,10 @@ static int run_git_commit(struct repository *r,
 			     gpg_opt, gpg_opt);
 	}
 
+	if (opts->committer_date_is_author_date)
+		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 author_date_from_env_array(&cmd.env_array));
+
 	argv_array_push(&cmd.args, "commit");
 
 	if (!(flags & VERIFY_MSG))
@@ -1315,6 +1338,7 @@ static int try_to_commit(struct repository *r,
 	struct strbuf err = STRBUF_INIT;
 	struct strbuf commit_msg = STRBUF_INIT;
 	char *amend_author = NULL;
+	const char *committer = NULL;
 	const char *hook_commit = NULL;
 	enum commit_msg_cleanup_mode cleanup;
 	int res = 0;
@@ -1406,10 +1430,32 @@ static int try_to_commit(struct repository *r,
 		goto out;
 	}
 
-	reset_ident_date();
+	if (opts->committer_date_is_author_date) {
+		struct ident_split id;
+		struct strbuf date = STRBUF_INIT;
+
+		if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
+			res = error(_("invalid author identity '%s'"), author);
+			goto out;
+		}
+		if (!id.date_begin) {
+			res = error(_("corrupt author: missing date information"));
+			goto out;
+		}
+		strbuf_addf(&date, "@%.*s %.*s",
+			    (int)(id.date_end - id.date_begin), id.date_begin,
+			    (int)(id.tz_end - id.tz_begin), id.tz_begin);
+		committer = fmt_ident(opts->committer_name,
+				      opts->committer_email,
+				      WANT_COMMITTER_IDENT, date.buf,
+				      IDENT_STRICT);
+		strbuf_release(&date);
+	} else {
+		reset_ident_date();
+	}
 
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,
-				 author, NULL, opts->gpg_sign, extra)) {
+				 author, committer, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
 		goto out;
 	}
@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->signoff = 1;
 		}
 
+		if (file_exists(rebase_path_cdate_is_adate())) {
+			opts->allow_ff = 0;
+			opts->committer_date_is_author_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_drop_redundant_commits(), "%s", "");
 	if (opts->keep_redundant_commits)
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
+	if (opts->committer_date_is_author_date)
+		write_file(rebase_path_cdate_is_adate(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,
 			goto leave_merge;
 		}
 
+		if (opts->committer_date_is_author_date)
+			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 author_date_from_env_array(&cmd.env_array));
+
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
 		argv_array_push(&cmd.args, "-s");
@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
-				opts->record_origin || opts->edit));
+			 opts->record_origin || opts->edit ||
+			 opts->committer_date_is_author_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
@@ -4258,6 +4316,22 @@ static int commit_staged_changes(struct repository *r,
 	return 0;
 }
 
+static int init_committer(struct replay_opts *opts)
+{
+	struct ident_split id;
+	const char *committer;
+
+	committer = git_committer_info(IDENT_STRICT);
+	if (split_ident_line(&id, committer, strlen(committer)) < 0)
+		return error(_("invalid committer '%s'"), committer);
+	opts->committer_name =
+		xmemdupz(id.name_begin, id.name_end - id.name_begin);
+	opts->committer_email =
+		xmemdupz(id.mail_begin, id.mail_end - id.mail_end);
+
+	return 0;
+}
+
 int sequencer_continue(struct repository *r, struct replay_opts *opts)
 {
 	struct todo_list todo_list = TODO_LIST_INIT;
@@ -4269,6 +4343,9 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
 	if (read_populate_opts(opts))
 		return -1;
 	if (is_rebase_i(opts)) {
+		if (opts->committer_date_is_author_date && init_committer(opts))
+			return -1;
+
 		if ((res = read_populate_todo(r, &todo_list, opts)))
 			goto release_todo_list;
 
@@ -5145,6 +5222,9 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
 
 	res = -1;
 
+	if (opts->committer_date_is_author_date && init_committer(opts))
+		goto cleanup;
+
 	if (checkout_onto(r, opts, onto_name, &oid, orig_head))
 		goto cleanup;
 
diff --git a/sequencer.h b/sequencer.h
index 0bee85093e..7ca657fe2c 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -45,9 +45,12 @@ struct replay_opts {
 	int verbose;
 	int quiet;
 	int reschedule_failed_exec;
+	int committer_date_is_author_date;
 
 	int mainline;
 
+	char *committer_name;
+	char *committer_email;
 	char *gpg_sign;
 	enum commit_msg_cleanup_mode default_msg_cleanup;
 	int explicit_cleanup;
diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh
index 55ca46786d..c8234062c6 100755
--- a/t/t3422-rebase-incompatible-options.sh
+++ b/t/t3422-rebase-incompatible-options.sh
@@ -61,7 +61,6 @@ test_rebase_am_only () {
 }
 
 test_rebase_am_only --whitespace=fix
-test_rebase_am_only --committer-date-is-author-date
 test_rebase_am_only -C4
 
 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 4f8a6e51c9..50a63d8ebe 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
+export GIT_AUTHOR_DATE
+
 # This is a special case in which both am and interactive backends
 # provide the same output. It was done intentionally because
 # both the backends fall short of optimal behaviour.
@@ -21,11 +24,20 @@ test_expect_success 'setup' '
 	test_write_lines "line 1" "new line 2" "line 3" >file &&
 	git commit -am "update file" &&
 	git tag side &&
+	test_commit commit1 foo foo1 &&
+	test_commit commit2 foo foo2 &&
+	test_commit commit3 foo foo3 &&
 
 	git checkout --orphan master &&
+	rm foo &&
 	test_write_lines "line 1" "        line 2" "line 3" >file &&
 	git commit -am "add file" &&
-	git tag main
+	git tag main &&
+
+	mkdir test-bin &&
+	write_script test-bin/git-merge-test <<-\EOF
+	exec git-merge-recursive "$@"
+	EOF
 '
 
 test_expect_success '--ignore-whitespace works with apply backend' '
@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '
 	git diff --exit-code side
 '
 
+test_ctime_is_atime () {
+	git log $1 --format=%ai >authortime &&
+	git log $1 --format=%ci >committertime &&
+	test_cmp authortime committertime
+}
+
+test_expect_success '--committer-date-is-author-date works with apply backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase --apply --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with merge backend' '
+	GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
+	git rebase -m --committer-date-is-author-date HEAD^ &&
+	test_ctime_is_atime -1
+'
+
+test_expect_success '--committer-date-is-author-date works with rebase -r' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	git rebase -r --root --committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when forking merge' '
+	git checkout side &&
+	GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
+	PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
+					--committer-date-is-author-date &&
+	test_ctime_is_atime
+'
+
+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
+	git checkout commit2 &&
+	GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--onto HEAD^^ HEAD^ &&
+	echo resolved > foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -1
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v8 4/5] rebase -i: support --ignore-date
  2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
                     ` (2 preceding siblings ...)
  2020-08-17 17:40   ` [PATCH v8 3/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-08-17 17:40   ` Phillip Wood
  2020-08-19 10:22     ` Phillip Wood
  2020-08-17 17:40   ` [PATCH v8 5/5] rebase: add --reset-author-date Phillip Wood
  4 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-08-17 17:40 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List
  Cc: Phillip Wood

From: Phillip Wood <phillip.wood@dunelm.org.uk>

Rebase is implemented with two different backends - 'apply' and
'merge' each of which support a different set of options. In
particular the apply backend supports a number of options implemented
by 'git am' that are not implemented in the merge backend. This means
that the available options are different depending on which backend is
used which is confusing. This patch adds support for the --ignore-date
option to the merge backend. This option uses the current time as the
author date rather than reusing the original author date when
rewriting commits. We take care to handle the combination of
--ignore-date and --committer-date-is-author-date in the same way as
the apply backend.

Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 Documentation/git-rebase.txt   |  7 ++--
 builtin/rebase.c               | 13 ++++---
 sequencer.c                    | 66 +++++++++++++++++++++++++++-------
 sequencer.h                    |  1 +
 t/t3436-rebase-more-options.sh | 56 +++++++++++++++++++++++++++++
 5 files changed, 123 insertions(+), 20 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f9ddfe2e77..79cecd2929 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies `--force-rebase`.
 
 --ignore-date::
-	This flag is passed to 'git am' to change the author date
-	of each rebased commit (see linkgit:git-am[1]).
+	Instead of using the author date of the original commit, use
+	the current time as the	author date of the rebased commit.  This
+	option implies `--force-rebase`.
 +
 See also INCOMPATIBLE OPTIONS below.
 
@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
 The following options:
 
  * --apply
- * --ignore-date
  * --whitespace
  * -C
 
@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
  * --preserve-merges and --empty=
  * --preserve-merges and --ignore-whitespace
  * --preserve-merges and --committer-date-is-author-date
+ * --preserve-merges and --ignore-date
  * --keep-base and --onto
  * --keep-base and --root
 
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 2579380729..583ac96fc7 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -89,6 +89,7 @@ struct rebase_options {
 	char *gpg_sign_opt;
 	int autostash;
 	int committer_date_is_author_date;
+	int ignore_date;
 	char *cmd;
 	int allow_empty_message;
 	int rebase_merges, rebase_cousins;
@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.committer_date_is_author_date =
 					opts->committer_date_is_author_date;
+	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
 	replay.strategy = opts->strategy;
 
@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
-				  N_("passed to 'git am'"), PARSE_OPT_NOARG),
+		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+			 N_("ignore author date and use current date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	    options.autosquash) {
 		allow_preemptive_ff = 0;
 	}
-	if (options.committer_date_is_author_date)
+	if (options.committer_date_is_author_date || options.ignore_date)
 		options.flags |= REBASE_FORCE;
 
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
-		if (!strcmp(option, "--ignore-date") ||
-		    !strcmp(option, "--whitespace=fix") ||
+		if (!strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
 			allow_preemptive_ff = 0;
 		else if (skip_prefix(option, "-C", &p)) {
@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		if (options.committer_date_is_author_date)
 			argv_array_push(&options.git_am_opts,
 					"--committer-date-is-author-date");
+		if (options.ignore_date)
+			argv_array_push(&options.git_am_opts, "--ignore-date");
 	} else {
 		/* REBASE_MERGE and PRESERVE_MERGES */
 		if (ignore_whitespace) {
diff --git a/sequencer.c b/sequencer.c
index 78d09f9252..4ccb5451a9 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
  */
 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
+static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -959,7 +960,11 @@ static int run_git_commit(struct repository *r,
 
 	if (opts->committer_date_is_author_date)
 		argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+				 opts->ignore_date ?
+				 "" :
 				 author_date_from_env_array(&cmd.env_array));
+	if (opts->ignore_date)
+		argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 	argv_array_push(&cmd.args, "commit");
 
@@ -1434,26 +1439,51 @@ static int try_to_commit(struct repository *r,
 		struct ident_split id;
 		struct strbuf date = STRBUF_INIT;
 
-		if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
-			res = error(_("invalid author identity '%s'"), author);
-			goto out;
+		if (!opts->ignore_date) {
+			if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
+				res = error(_("invalid author identity '%s'"),
+					    author);
+				goto out;
+			}
+			if (!id.date_begin) {
+				res = error(_(
+					"corrupt author: missing date information"));
+				goto out;
+			}
+			strbuf_addf(&date, "@%.*s %.*s",
+				    (int)(id.date_end - id.date_begin),
+				    id.date_begin,
+				    (int)(id.tz_end - id.tz_begin),
+				    id.tz_begin);
+		} else {
+			reset_ident_date();
 		}
-		if (!id.date_begin) {
-			res = error(_("corrupt author: missing date information"));
-			goto out;
-		}
-		strbuf_addf(&date, "@%.*s %.*s",
-			    (int)(id.date_end - id.date_begin), id.date_begin,
-			    (int)(id.tz_end - id.tz_begin), id.tz_begin);
 		committer = fmt_ident(opts->committer_name,
 				      opts->committer_email,
-				      WANT_COMMITTER_IDENT, date.buf,
+				      WANT_COMMITTER_IDENT,
+				      opts->ignore_date ? NULL : date.buf,
 				      IDENT_STRICT);
 		strbuf_release(&date);
 	} else {
 		reset_ident_date();
 	}
 
+	if (opts->ignore_date) {
+		struct ident_split id;
+		char *name, *email;
+
+		if (split_ident_line(&id, author, strlen(author)) < 0) {
+			error(_("invalid author identity '%s'"), author);
+			goto out;
+		}
+		name = xmemdupz(id.name_begin, id.name_end - id.name_begin);
+		email = xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
+		author = fmt_ident(name, email, WANT_AUTHOR_IDENT, NULL,
+				   IDENT_STRICT);
+		free(name);
+		free(email);
+	}
+
 	if (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,
 				 author, committer, opts->gpg_sign, extra)) {
 		res = error(_("failed to write commit object"));
@@ -2583,6 +2613,11 @@ static int read_populate_opts(struct replay_opts *opts)
 			opts->committer_date_is_author_date = 1;
 		}
 
+		if (file_exists(rebase_path_ignore_date())) {
+			opts->allow_ff = 0;
+			opts->ignore_date = 1;
+		}
+
 		if (file_exists(rebase_path_reschedule_failed_exec()))
 			opts->reschedule_failed_exec = 1;
 
@@ -2675,6 +2710,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
 		write_file(rebase_path_keep_redundant_commits(), "%s", "");
 	if (opts->committer_date_is_author_date)
 		write_file(rebase_path_cdate_is_adate(), "%s", "");
+	if (opts->ignore_date)
+		write_file(rebase_path_ignore_date(), "%s", "");
 	if (opts->reschedule_failed_exec)
 		write_file(rebase_path_reschedule_failed_exec(), "%s", "");
 
@@ -3597,7 +3634,11 @@ static int do_merge(struct repository *r,
 
 		if (opts->committer_date_is_author_date)
 			argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
+					 opts->ignore_date ?
+					 "" :
 					 author_date_from_env_array(&cmd.env_array));
+		if (opts->ignore_date)
+			argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
 
 		cmd.git_cmd = 1;
 		argv_array_push(&cmd.args, "merge");
@@ -3877,7 +3918,8 @@ static int pick_commits(struct repository *r,
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 			 opts->record_origin || opts->edit ||
-			 opts->committer_date_is_author_date));
+			 opts->committer_date_is_author_date ||
+			 opts->ignore_date));
 	if (read_and_refresh_cache(r, opts))
 		return -1;
 
diff --git a/sequencer.h b/sequencer.h
index 7ca657fe2c..20493a2be2 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -46,6 +46,7 @@ struct replay_opts {
 	int quiet;
 	int reschedule_failed_exec;
 	int committer_date_is_author_date;
+	int ignore_date;
 
 	int mainline;
 
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 50a63d8ebe..0ede2b8900 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl
 	test_ctime_is_atime -1
 '
 
+# Checking for +0000 in the author date is sufficient since the
+# default timezone is UTC but the timezone used while committing is
+# +0530. The inverted logic in the grep is necessary to check all the
+# author dates in the file.
+test_ctime_is_ignored () {
+	git log $1 --format=%ai >authortime &&
+	! grep -v +0000 authortime
+}
+
+test_expect_success '--ignore-date works with apply backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with merge backend' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --ignore-date -m HEAD^ &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works after conflict resolution' '
+	test_must_fail git rebase --ignore-date -m \
+		--onto commit2^^ commit2^ commit2 &&
+	echo resolved >foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_ignored -1
+'
+
+test_expect_success '--ignore-date works with rebase -r' '
+	git checkout side &&
+	git merge --no-ff commit3 &&
+	git rebase -r --root --ignore-date &&
+	test_ctime_is_ignored
+'
+
+test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+	test_must_fail git rebase -m --committer-date-is-author-date \
+		--ignore-date --onto commit2^^ commit2^ commit3 &&
+	git checkout --theirs foo &&
+	git add foo &&
+	git rebase --continue &&
+	test_ctime_is_atime -2 &&
+	test_ctime_is_ignored -2
+'
+
+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
+		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
+				--ignore-date --committer-date-is-author-date \
+				side side &&
+	test_ctime_is_atime -1 &&
+	test_ctime_is_ignored -1
+ '
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* [PATCH v8 5/5] rebase: add --reset-author-date
  2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
                     ` (3 preceding siblings ...)
  2020-08-17 17:40   ` [PATCH v8 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-08-17 17:40   ` Phillip Wood
  4 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-08-17 17:40 UTC (permalink / raw)
  To: Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>

The previous commit introduced --ignore-date flag to rebase -i, but the
name is rather vague as it does not say whether the author date or the
committer date is ignored. Add an alias to convey the precise purpose.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
---
 Documentation/git-rebase.txt   |  1 +
 builtin/rebase.c               |  4 +++-
 t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 79cecd2929..1ee3bb4fac 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.
 	date. This option implies `--force-rebase`.
 
 --ignore-date::
+--reset-author-date::
 	Instead of using the author date of the original commit, use
 	the current time as the	author date of the rebased commit.  This
 	option implies `--force-rebase`.
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 583ac96fc7..b126fbe940 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
-		OPT_BOOL(0, "ignore-date", &options.ignore_date,
+		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
 			 N_("ignore author date and use current date")),
+		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
+				N_("synonym of --reset-author-date")),
 		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
 				  N_("passed to 'git apply'"), 0),
 		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 0ede2b8900..5b8963272a 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -117,53 +117,61 @@ test_ctime_is_ignored () {
 	! grep -v +0000 authortime
 }
 
-test_expect_success '--ignore-date works with apply backend' '
+test_expect_success '--reset-author-date works with apply backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --apply --ignore-date HEAD^ &&
+	git rebase --apply --reset-author-date HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with merge backend' '
+test_expect_success '--reset-author-date works with merge backend' '
 	git commit --amend --date="$GIT_AUTHOR_DATE" &&
-	git rebase --ignore-date -m HEAD^ &&
+	git rebase --reset-author-date -m HEAD^ &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works after conflict resolution' '
-	test_must_fail git rebase --ignore-date -m \
+test_expect_success '--reset-author-date works after conflict resolution' '
+	test_must_fail git rebase --reset-author-date -m \
 		--onto commit2^^ commit2^ commit2 &&
 	echo resolved >foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_ignored -1
 '
 
-test_expect_success '--ignore-date works with rebase -r' '
+test_expect_success '--reset-author-date works with rebase -r' '
 	git checkout side &&
 	git merge --no-ff commit3 &&
-	git rebase -r --root --ignore-date &&
+	git rebase -r --root --reset-author-date &&
 	test_ctime_is_ignored
 '
 
-test_expect_success '--ignore-date with --committer-date-is-author-date works' '
+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
 	test_must_fail git rebase -m --committer-date-is-author-date \
-		--ignore-date --onto commit2^^ commit2^ commit3 &&
+		--reset-author-date --onto commit2^^ commit2^ commit3 &&
 	git checkout --theirs foo &&
 	git add foo &&
 	git rebase --continue &&
 	test_ctime_is_atime -2 &&
 	test_ctime_is_ignored -2
 '
 
-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
 	GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
 		PATH="./test-bin:$PATH" git rebase -i --strategy=test \
-				--ignore-date --committer-date-is-author-date \
-				side side &&
+				--reset-author-date \
+				--committer-date-is-author-date side side &&
 	test_ctime_is_atime -1 &&
 	test_ctime_is_ignored -1
  '
 
+test_expect_success '--ignore-date is an alias for --reset-author-date' '
+	git commit --amend --date="$GIT_AUTHOR_DATE" &&
+	git rebase --apply --ignore-date HEAD^ &&
+	git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
+	git rebase -m --ignore-date HEAD^ &&
+	test_ctime_is_ignored -2
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE
  2020-08-17 17:40   ` [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE Phillip Wood
@ 2020-08-17 19:12     ` Junio C Hamano
  2020-08-19 10:20       ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-08-17 19:12 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> The implementation of --committer-date-is-author-date exports
> GIT_COMMITTER_DATE to override the default committer date but does not
> reset GIT_COMMITTER_DATE in the environment after creating the commit
> so it is set in the environment of any hooks that get run. We're about
> to add the same functionality to the sequencer and do not want to have
> GIT_COMMITTER_DATE set when running hooks or exec commands so lets
> update commit_tree_extended() to take an explicit committer so we
> override the default date without setting GIT_COMMITTER_DATE in the
> environment.
>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  builtin/am.c     | 28 +++++++++++++++++++++++-----
>  builtin/commit.c |  4 ++--
>  commit.c         | 11 +++++++----
>  commit.h         |  7 +++----
>  ident.c          | 24 ++++++++++++++----------
>  sequencer.c      |  4 ++--
>  6 files changed, 51 insertions(+), 27 deletions(-)

Nice.

Obviously this would affect the environment while am is running, and
the change is observable by post-applypatch hook.  I am not sure if
this change-in-behaviour would negatively affect people's hooks, but
given the large end-user population we have, somebody somewhere will
get hit.

> diff --git a/ident.c b/ident.c
> index e666ee4e59..7cbf223350 100644
> --- a/ident.c
> +++ b/ident.c
> @@ -361,11 +361,15 @@ N_("\n"
>  const char *fmt_ident(const char *name, const char *email,
>  		      enum want_ident whose_ident, const char *date_str, int flag)
>  {
> -	static struct strbuf ident = STRBUF_INIT;
> +	static int index;
> +	static struct strbuf ident_pool[2] = { STRBUF_INIT, STRBUF_INIT };
>  	int strict = (flag & IDENT_STRICT);
>  	int want_date = !(flag & IDENT_NO_DATE);
>  	int want_name = !(flag & IDENT_NO_NAME);
>  
> +	struct strbuf *ident = &ident_pool[index];
> +	index = (index + 1) % ARRAY_SIZE(ident_pool);

2-element rotating buffer because we happen to care at most two
idents at the same time, author's and committer's?

How many callers of fmt_ident() do we have these days?  I wonder if
we can introduce a new API that lets/forces the caller to prepare a
strbuf and migrate the current callers of this function to it, of if
it is too large a churn for the purpose of this series.

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE
  2020-08-17 19:12     ` Junio C Hamano
@ 2020-08-19 10:20       ` Phillip Wood
  2020-08-19 15:51         ` Junio C Hamano
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-08-19 10:20 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

On 17/08/2020 20:12, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>>
>> The implementation of --committer-date-is-author-date exports
>> GIT_COMMITTER_DATE to override the default committer date but does not
>> reset GIT_COMMITTER_DATE in the environment after creating the commit
>> so it is set in the environment of any hooks that get run. We're about
>> to add the same functionality to the sequencer and do not want to have
>> GIT_COMMITTER_DATE set when running hooks or exec commands so lets
>> update commit_tree_extended() to take an explicit committer so we
>> override the default date without setting GIT_COMMITTER_DATE in the
>> environment.
>>
>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> ---
>>  builtin/am.c     | 28 +++++++++++++++++++++++-----
>>  builtin/commit.c |  4 ++--
>>  commit.c         | 11 +++++++----
>>  commit.h         |  7 +++----
>>  ident.c          | 24 ++++++++++++++----------
>>  sequencer.c      |  4 ++--
>>  6 files changed, 51 insertions(+), 27 deletions(-)
> 
> Nice.
> 
> Obviously this would affect the environment while am is running, and
> the change is observable by post-applypatch hook.  I am not sure if
> this change-in-behaviour would negatively affect people's hooks, but
> given the large end-user population we have, somebody somewhere will
> get hit.

Yes I did think about that but decided it was probably better to fix it.
At the moment the pre-applypatch gets GIT_COMMITTER_DATE set to the date
of the last commit which does not make much sense. If anyone does need
the committer date in the post-applypatch hook they can look at HEAD. We
should perhaps mention that in the release notes

>> diff --git a/ident.c b/ident.c
>> index e666ee4e59..7cbf223350 100644
>> --- a/ident.c
>> +++ b/ident.c
>> @@ -361,11 +361,15 @@ N_("\n"
>>  const char *fmt_ident(const char *name, const char *email,
>>  		      enum want_ident whose_ident, const char *date_str, int flag)
>>  {
>> -	static struct strbuf ident = STRBUF_INIT;
>> +	static int index;
>> +	static struct strbuf ident_pool[2] = { STRBUF_INIT, STRBUF_INIT };
>>  	int strict = (flag & IDENT_STRICT);
>>  	int want_date = !(flag & IDENT_NO_DATE);
>>  	int want_name = !(flag & IDENT_NO_NAME);
>>  
>> +	struct strbuf *ident = &ident_pool[index];
>> +	index = (index + 1) % ARRAY_SIZE(ident_pool);
> 
> 2-element rotating buffer because we happen to care at most two
> idents at the same time, author's and committer's?
> 
> How many callers of fmt_ident() do we have these days?  I wonder if
> we can introduce a new API that lets/forces the caller to prepare a
> strbuf and migrate the current callers of this function to it, of if
> it is too large a churn for the purpose of this series.

After this series is applied there are the following callers

blame.c:207: ident = fmt_ident("Not Committed Yet", "not.committed.yet",
builtin/am.c:1591: author = fmt_ident(state->author_name,
state->author_email,
builtin/am.c:1597: committer = fmt_ident(state->committer_name,
builtin/commit.c:638: strbuf_addstr(author_ident, fmt_ident(name, email,
WANT_AUTHOR_IDENT, date,
ident.c:466: return fmt_ident(name, email, whose_ident, NULL,
ident.c:476: return fmt_ident(getenv("GIT_AUTHOR_NAME"),
ident.c:489: return fmt_ident(getenv("GIT_COMMITTER_NAME"),
sequencer.c:1461: committer = fmt_ident(opts->committer_name,
sequencer.c:1481: author = fmt_ident(name, email, WANT_AUTHOR_IDENT, NULL,

In blame.c we'd have to add an strbuf to pass in,

The caller in builtin/commit.c would obviously be easy to convert as it
is stuffing the result into an strbuf already.

For am and the sequencer fmt_ident() is in a function which is called
from a loop and it is convenient not to have to worry about passing an
strbuf around or allocating and freeing it on each function call

The callers in ident (fmt_name(), git_author_info() and
git_committer_info()) return the string so they would need their own
strbuf or have to be changed so the caller passed one in. There are
quite a few callers of those functions and they seem to either
immediately call split_ident_line() or duplicate the returned string
(mostly the latter).

So it would be a bit of work to do it but not an enormous amount
(assuming we don't change the signature of git_author_info() etc in
ident.c, although given the pattern of callers it might be worth doing
that if they are mostly duplicating the returned string anyway)

I'm going to be off line for 10-14 days from the beginning of next week,
I could take a look at it after that, or we could leave it for a future
improvement - what do you think?

Best Wishes

Phillip


> 
> Thanks.
> 


^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 4/5] rebase -i: support --ignore-date
  2020-08-17 17:40   ` [PATCH v8 4/5] rebase -i: support --ignore-date Phillip Wood
@ 2020-08-19 10:22     ` Phillip Wood
  2020-08-19 22:20       ` Junio C Hamano
  0 siblings, 1 reply; 130+ messages in thread
From: Phillip Wood @ 2020-08-19 10:22 UTC (permalink / raw)
  To: Phillip Wood, Johannes Schindelin, Junio C Hamano, Elijah Newren,
	Rohit Ashiwal, Đoàn Trần Công Danh,
	Alban Gruin, Git Mailing List

On 17/08/2020 18:40, Phillip Wood wrote:
> From: Phillip Wood <phillip.wood@dunelm.org.uk>
> 
> Rebase is implemented with two different backends - 'apply' and
> 'merge' each of which support a different set of options. In
> particular the apply backend supports a number of options implemented
> by 'git am' that are not implemented in the merge backend. This means
> that the available options are different depending on which backend is
> used which is confusing. This patch adds support for the --ignore-date
> option to the merge backend. This option uses the current time as the
> author date rather than reusing the original author date when
> rewriting commits. We take care to handle the combination of
> --ignore-date and --committer-date-is-author-date in the same way as
> the apply backend.
> 
> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  Documentation/git-rebase.txt   |  7 ++--
>  builtin/rebase.c               | 13 ++++---
>  sequencer.c                    | 66 +++++++++++++++++++++++++++-------
>  sequencer.h                    |  1 +
>  t/t3436-rebase-more-options.sh | 56 +++++++++++++++++++++++++++++
>  5 files changed, 123 insertions(+), 20 deletions(-)
> 
>  [...]
> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 50a63d8ebe..0ede2b8900 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl
>  	test_ctime_is_atime -1
>  '
>  
> +# Checking for +0000 in the author date is sufficient since the
> +# default timezone is UTC but the timezone used while committing is
> +# +0530. The inverted logic in the grep is necessary to check all the
> +# author dates in the file.
> +test_ctime_is_ignored () {
> +	git log $1 --format=%ai >authortime &&
> +	! grep -v +0000 authortime
> +}


I don't know what I was thinking when I wrote that - it should be called
test_atime_is_ignored() as it's testing the author date

Best Wishes

Phillip

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE
  2020-08-19 10:20       ` Phillip Wood
@ 2020-08-19 15:51         ` Junio C Hamano
  2020-08-20 15:23           ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-08-19 15:51 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> For am and the sequencer fmt_ident() is in a function which is called
> from a loop and it is convenient not to have to worry about passing an
> strbuf around or allocating and freeing it on each function call

That's strbuf on caller's stack, right?  The actual string pointed
by the strbuf's buf pointer will be needed and on the heap with or
without the clean-up on top of the patch we are discussing, so I do
not think alloc/free would be in the picture when considering the
pros-and-cons.

> The callers in ident (fmt_name(), git_author_info() and
> git_committer_info()) return the string so they would need their own
> strbuf or have to be changed so the caller passed one in. There are
> quite a few callers of those functions and they seem to either
> immediately call split_ident_line() or duplicate the returned string
> (mostly the latter).
>
> So it would be a bit of work to do it but not an enormous amount
> (assuming we don't change the signature of git_author_info() etc in
> ident.c, although given the pattern of callers it might be worth doing
> that if they are mostly duplicating the returned string anyway)

I'd say that is more than "while at it" clean-up.  It would be
easier to review and slightly easier to do if done before this patch
introduces rotating strbuf, but ...

> I'm going to be off line for 10-14 days from the beginning of next week,
> I could take a look at it after that, or we could leave it for a future
> improvement - what do you think?

... I can be talked into punting it for later, at least for now.

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 4/5] rebase -i: support --ignore-date
  2020-08-19 10:22     ` Phillip Wood
@ 2020-08-19 22:20       ` Junio C Hamano
  2020-08-20 15:16         ` Phillip Wood
  0 siblings, 1 reply; 130+ messages in thread
From: Junio C Hamano @ 2020-08-19 22:20 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Phillip Wood, Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

Phillip Wood <phillip.wood123@gmail.com> writes:

>> +# Checking for +0000 in the author date is sufficient since the
>> +# default timezone is UTC but the timezone used while committing is
>> +# +0530. The inverted logic in the grep is necessary to check all the
>> +# author dates in the file.
>> +test_ctime_is_ignored () {
>> +	git log $1 --format=%ai >authortime &&
>> +	! grep -v +0000 authortime
>> +}
>
>
> I don't know what I was thinking when I wrote that - it should be called
> test_atime_is_ignored() as it's testing the author date

Will tweak locally.  No need to resend.

Thanks.

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 4/5] rebase -i: support --ignore-date
  2020-08-19 22:20       ` Junio C Hamano
@ 2020-08-20 15:16         ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-08-20 15:16 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Phillip Wood, Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List

On 19/08/2020 23:20, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>>> +# Checking for +0000 in the author date is sufficient since the
>>> +# default timezone is UTC but the timezone used while committing is
>>> +# +0530. The inverted logic in the grep is necessary to check all the
>>> +# author dates in the file.
>>> +test_ctime_is_ignored () {
>>> +	git log $1 --format=%ai >authortime &&
>>> +	! grep -v +0000 authortime
>>> +}
>>
>>
>> I don't know what I was thinking when I wrote that - it should be called
>> test_atime_is_ignored() as it's testing the author date
> 
> Will tweak locally.  No need to resend.

Thanks for doing that

Best wishes

Phillip

> Thanks.
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE
  2020-08-19 15:51         ` Junio C Hamano
@ 2020-08-20 15:23           ` Phillip Wood
  0 siblings, 0 replies; 130+ messages in thread
From: Phillip Wood @ 2020-08-20 15:23 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

On 19/08/2020 16:51, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>> For am and the sequencer fmt_ident() is in a function which is called
>> from a loop and it is convenient not to have to worry about passing an
>> strbuf around or allocating and freeing it on each function call
> 
> That's strbuf on caller's stack, right?  The actual string pointed
> by the strbuf's buf pointer will be needed and on the heap with or
> without the clean-up on top of the patch we are discussing, so I do
> not think alloc/free would be in the picture when considering the
> pros-and-cons.

At the moment we use the same allocation for the whole program (ignoring 
reallocation if the string grows). If we were to add an strbuf as a 
local variable in the function that gets called by the commit picking 
loop we either need to make it static and accept the leak or alloc and 
free the string each time the function is called. Either way I'd be 
amazed if it has any effect on the performance given we're performing a 
merge with each loop iteration.

>> The callers in ident (fmt_name(), git_author_info() and
>> git_committer_info()) return the string so they would need their own
>> strbuf or have to be changed so the caller passed one in. There are
>> quite a few callers of those functions and they seem to either
>> immediately call split_ident_line() or duplicate the returned string
>> (mostly the latter).
>>
>> So it would be a bit of work to do it but not an enormous amount
>> (assuming we don't change the signature of git_author_info() etc in
>> ident.c, although given the pattern of callers it might be worth doing
>> that if they are mostly duplicating the returned string anyway)
> 
> I'd say that is more than "while at it" clean-up.  It would be
> easier to review and slightly easier to do if done before this patch
> introduces rotating strbuf, but ...
> 
>> I'm going to be off line for 10-14 days from the beginning of next week,
>> I could take a look at it after that, or we could leave it for a future
>> improvement - what do you think?
> 
> ... I can be talked into punting it for later, at least for now.

I'm tempted to say leave it for now but if this isn't in next by the 
time I'm back online I'll look at rerolling.

Best Wishes

Phillip
> 
> Thanks.
> 

^ permalink raw reply	[flat|nested] 130+ messages in thread

* Re: [PATCH v8 3/5] rebase -i: support --committer-date-is-author-date
  2020-08-17 17:40   ` [PATCH v8 3/5] rebase -i: support --committer-date-is-author-date Phillip Wood
@ 2020-08-26 21:41     ` Junio C Hamano
  0 siblings, 0 replies; 130+ messages in thread
From: Junio C Hamano @ 2020-08-26 21:41 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Johannes Schindelin, Elijah Newren, Rohit Ashiwal,
	Đoàn Trần Công Danh, Alban Gruin,
	Git Mailing List, Phillip Wood

Phillip Wood <phillip.wood123@gmail.com> writes:

> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
> index 4f8a6e51c9..50a63d8ebe 100755
> --- a/t/t3436-rebase-more-options.sh
> +++ b/t/t3436-rebase-more-options.sh
> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe
>  
>  . "$TEST_DIRECTORY"/lib-rebase.sh
>  
> +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
> +export GIT_AUTHOR_DATE
> +
>  # This is a special case in which both am and interactive backends
>  # provide the same output. It was done intentionally because
>  # both the backends fall short of optimal behaviour.
> @@ -21,11 +24,20 @@ test_expect_success 'setup' '
>  	test_write_lines "line 1" "new line 2" "line 3" >file &&
>  	git commit -am "update file" &&
> + ...
> +	mkdir test-bin &&
> +	write_script test-bin/git-merge-test <<-\EOF
> +	exec git-merge-recursive "$@"

This should be

	exec git merge-recursive "$@"

> +	EOF
>  '

^ permalink raw reply	[flat|nested] 130+ messages in thread

end of thread, other threads:[~2020-08-26 21:41 UTC | newest]

Thread overview: 130+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-07 14:11 [PATCH 0/6] fixup ra/rebase-i-more-options Phillip Wood
2020-04-07 14:11 ` [PATCH 1/6] Revert "Revert "Merge branch 'ra/rebase-i-more-options'"" Phillip Wood
2020-04-07 15:16   ` Elijah Newren
2020-04-07 18:01     ` Phillip Wood
2020-04-07 21:04     ` Junio C Hamano
2020-04-07 21:31       ` Junio C Hamano
2020-04-12 17:47         ` Johannes Schindelin
2020-04-13  9:58           ` Phillip Wood
2020-04-13 22:05             ` Junio C Hamano
2020-04-07 14:11 ` [PATCH 2/6] t3433: remove loops from tests Phillip Wood
2020-04-07 14:30   ` Elijah Newren
2020-04-07 14:11 ` [PATCH 3/6] t3433: only compare commit dates Phillip Wood
2020-04-07 14:11 ` [PATCH 4/6] rebase -i: fix --committer-date-is-author-date Phillip Wood
2020-04-07 15:05   ` Elijah Newren
2020-04-07 18:11     ` Phillip Wood
2020-04-07 14:11 ` [PATCH 5/6] Revert "sequencer: allow callers of read_author_script() to ignore fields" Phillip Wood
2020-04-07 15:06   ` Elijah Newren
2020-04-07 14:11 ` [PATCH 6/6] t3433: improve coverage Phillip Wood
2020-04-07 15:13   ` Elijah Newren
2020-04-07 18:16     ` Phillip Wood
2020-04-07 15:17 ` [PATCH 0/6] fixup ra/rebase-i-more-options Elijah Newren
2020-04-07 18:18   ` Phillip Wood
2020-04-07 23:04 ` Junio C Hamano
2020-04-29 10:25 ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Phillip Wood
2020-04-29 10:25   ` [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
2020-05-13  3:54     ` Elijah Newren
2020-05-14  9:47       ` Phillip Wood
2020-04-29 10:25   ` [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
2020-05-10 11:14     ` Alban Gruin
2020-05-13  4:08     ` Elijah Newren
2020-04-29 10:25   ` [PATCH v2 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
2020-04-29 10:25   ` [PATCH v2 4/5] rebase -i: support --ignore-date Phillip Wood
2020-05-10 11:14     ` Alban Gruin
2020-05-12 14:47       ` Phillip Wood
2020-05-13 15:33         ` Junio C Hamano
2020-05-13  3:54     ` Elijah Newren
2020-04-29 10:25   ` [PATCH v2 5/5] rebase: add --reset-author-date Phillip Wood
2020-04-29 19:59   ` [PATCH v2 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
2020-05-13  3:57     ` Elijah Newren
2020-05-21 10:14 ` [PATCH v3 " Phillip Wood
2020-05-21 10:14   ` [PATCH v3 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
2020-05-21 10:14   ` [PATCH v3 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
2020-05-21 10:14   ` [PATCH v3 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
2020-05-21 10:14   ` [PATCH v3 4/5] rebase -i: support --ignore-date Phillip Wood
2020-05-23 12:30     ` Đoàn Trần Công Danh
2020-05-23 15:43       ` Phillip Wood
2020-05-23 15:52         ` Đoàn Trần Công Danh
2020-05-23 18:50           ` Phillip Wood
2020-05-23 23:05             ` Đoàn Trần Công Danh
2020-05-27  9:55               ` Phillip Wood
2020-05-24 16:32           ` Junio C Hamano
2020-05-21 10:14   ` [PATCH v3 5/5] rebase: add --reset-author-date Phillip Wood
2020-05-22 15:54   ` [PATCH v3 0/5] cleanup ra/rebase-i-more-options Elijah Newren
2020-05-23  8:55     ` Phillip Wood
2020-05-23  6:59   ` Johannes Schindelin
2020-05-27 17:33 ` [PATCH v4 " Phillip Wood
2020-05-27 17:33   ` [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
2020-05-29  2:38     ` Johannes Schindelin
2020-06-01  9:23       ` Kerry, Richard
2020-06-01 10:26       ` Phillip Wood
2020-06-01 21:03         ` Johannes Schindelin
2020-05-27 17:33   ` [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
2020-05-29  2:52     ` Johannes Schindelin
2020-06-01 10:33       ` Phillip Wood
2020-05-27 17:33   ` [PATCH v4 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
2020-05-27 17:33   ` [PATCH v4 4/5] rebase -i: support --ignore-date Phillip Wood
2020-05-27 17:33   ` [PATCH v4 5/5] rebase: add --reset-author-date Phillip Wood
2020-05-27 17:57     ` [PATCH v4 6/5] fixup! " Phillip Wood
2020-05-28 13:17       ` Đoàn Trần Công Danh
2020-05-29  2:59         ` Johannes Schindelin
2020-06-01 10:36           ` Phillip Wood
2020-05-27 21:10   ` [PATCH v4 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
2020-06-26  9:55 ` [PATCH v5 " Phillip Wood
2020-06-26  9:55   ` [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
2020-06-26 13:37     ` Đoàn Trần Công Danh
2020-06-26 14:43       ` Phillip Wood
2020-06-26 16:03         ` Junio C Hamano
2020-06-29 14:14         ` Đoàn Trần Công Danh
2020-07-13 10:02           ` Phillip Wood
2020-06-26 15:43     ` Junio C Hamano
2020-06-26  9:55   ` [PATCH v5 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
2020-06-26  9:55   ` [PATCH v5 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
2020-06-26  9:55   ` [PATCH v5 4/5] rebase -i: support --ignore-date Phillip Wood
2020-06-26 14:09     ` Đoàn Trần Công Danh
2020-06-26 14:38       ` Phillip Wood
2020-06-26 16:29     ` Junio C Hamano
2020-06-26  9:55   ` [PATCH v5 5/5] rebase: add --reset-author-date Phillip Wood
2020-06-26 16:35     ` Junio C Hamano
2020-06-26 18:07       ` Phillip Wood
2020-06-26 15:04   ` [PATCH v5 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
2020-07-13 10:10 ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Phillip Wood
2020-07-13 10:10   ` [PATCH v6 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
2020-07-13 10:10   ` [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
2020-07-15 14:27     ` Đoàn Trần Công Danh
2020-07-16  8:23       ` Phillip Wood
2020-07-16 13:06         ` Đoàn Trần Công Danh
2020-07-16 15:17           ` Phillip Wood
2020-07-16 17:34             ` Phillip Wood
2020-07-17  0:25               ` Đoàn Trần Công Danh
2020-07-13 10:10   ` [PATCH v6 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
2020-07-13 10:10   ` [PATCH v6 4/5] rebase -i: support --ignore-date Phillip Wood
2020-07-13 10:10   ` [PATCH v6 5/5] rebase: add --reset-author-date Phillip Wood
2020-07-13 15:28   ` [PATCH v6 0/5] fixup ra/rebase-i-more-options Junio C Hamano
2020-07-15  8:55     ` Phillip Wood
2020-07-16 17:32 ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Phillip Wood
2020-07-16 17:32   ` [PATCH v7 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
2020-07-16 17:32   ` [PATCH v7 2/5] rebase -i: support --committer-date-is-author-date Phillip Wood
2020-08-13 13:46     ` Johannes Schindelin
2020-07-16 17:32   ` [PATCH v7 3/5] sequencer: rename amend_author to author_to_free Phillip Wood
2020-07-16 17:32   ` [PATCH v7 4/5] rebase -i: support --ignore-date Phillip Wood
2020-08-13 14:07     ` Johannes Schindelin
2020-07-16 17:32   ` [PATCH v7 5/5] rebase: add --reset-author-date Phillip Wood
2020-07-16 17:39   ` [PATCH v7 0/5] cleanup ra/rebase-i-more-options Junio C Hamano
2020-08-13 14:24   ` Johannes Schindelin
2020-08-13 17:46     ` Junio C Hamano
2020-08-13 19:51       ` Phillip Wood
2020-08-17 17:39 ` [PATCH v8 " Phillip Wood
2020-08-17 17:40   ` [PATCH v8 1/5] rebase -i: add --ignore-whitespace flag Phillip Wood
2020-08-17 17:40   ` [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE Phillip Wood
2020-08-17 19:12     ` Junio C Hamano
2020-08-19 10:20       ` Phillip Wood
2020-08-19 15:51         ` Junio C Hamano
2020-08-20 15:23           ` Phillip Wood
2020-08-17 17:40   ` [PATCH v8 3/5] rebase -i: support --committer-date-is-author-date Phillip Wood
2020-08-26 21:41     ` Junio C Hamano
2020-08-17 17:40   ` [PATCH v8 4/5] rebase -i: support --ignore-date Phillip Wood
2020-08-19 10:22     ` Phillip Wood
2020-08-19 22:20       ` Junio C Hamano
2020-08-20 15:16         ` Phillip Wood
2020-08-17 17:40   ` [PATCH v8 5/5] rebase: add --reset-author-date Phillip Wood

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