{"thread":{"id":"53176","subject":"[PATCH 0/6] fixup ra/rebase-i-more-options","startedAt":"2020-04-07T14:11:49Z","lastAt":"2020-08-26T21:41:29Z","messageCount":130,"participants":["Phillip Wood","Elijah Newren","Junio C Hamano","Johannes Schindelin","Alban Gruin","Đoàn Trần Công Danh","Kerry, Richard"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"394921","messageId":"20200407141125.30872-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":null,"subject":"[PATCH 0/6] fixup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T14:11:19Z","receivedAt":"2020-04-07T14:11:49Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThe tests for ra/rebase-i-more-options were not as comprehensive as\nthey could have been and some of the tests that we did have didn't do\na good job of testing what they purported to. This series cleans up\nthe tests and fixes a couple of bugs (thanks to Jonathan Nieder for\nreporting one of them). The bug fix reworks the code to try and make\nit clearer.\n\nI've opted to add some cleanup commits on top of Rohit's work rather\nthan reworking his patches. These are based on top of 4d924528d8\n(\"Revert \"Merge branch 'ra/rebase-i-more-options'\"\", 2020-01-12) there\nare some conflicts when merging into pu. I had a quick look at the\nconflicts and they appeared to be relatively straight forward to\nresolve. If that impression is wrong let me know and I can rebase onto\nmaster or try doing the merge myself and pushing it to github.\n\nPhillip Wood (6):\n  Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"\n  t3433: remove loops from tests\n  t3433: only compare commit dates\n  rebase -i: fix --committer-date-is-author-date\n  Revert \"sequencer: allow callers of read_author_script() to ignore\n    fields\"\n  t3433: improve coverage\n\n Documentation/git-rebase.txt            |  27 +++-\n builtin/rebase.c                        |  49 ++++--\n sequencer.c                             | 109 ++++++++++++-\n sequencer.h                             |   2 +\n t/t3422-rebase-incompatible-options.sh  |   2 -\n t/t3433-rebase-options-compatibility.sh | 201 ++++++++++++++++++++++++\n 7 files changed, 368 insertions(+), 25 deletions(-)\n create mode 100755 t/t3433-rebase-options-compatibility.sh\n\n-- \n2.26.0\n\n"},{"id":"394922","messageId":"20200407141125.30872-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH 2/6] t3433: remove loops from tests","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T14:11:21Z","receivedAt":"2020-04-07T14:11:54Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nLooping inside a test is asking for trouble as we only detect any\nfailure on the last iteration. Instead get all the dates at once which\nis also more efficient. Note the previous code accidentally compared the\ndiffs as well as the dates this is fixed as well.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n t/t3433-rebase-options-compatibility.sh | 18 +++++-------------\n 1 file changed, 5 insertions(+), 13 deletions(-)\n\ndiff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 5166f158dd..2b4d75f1ef 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -90,13 +90,9 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n \tgit rebase -r --root --committer-date-is-author-date &&\n-\tgit rev-list HEAD >rev_list &&\n-\twhile read HASH\n-\tdo\n-\t\tgit show $HASH --pretty=\"format:%ai\" >authortime\n-\t\tgit show $HASH --pretty=\"format:%ci\" >committertime\n-\t\ttest_cmp authortime committertime\n-\tdone <rev_list\n+\tgit log --pretty=\"format:%ai\" >authortime &&\n+\tgit log --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n '\n \n # Checking for +0000 in author time is enough since default\n@@ -120,12 +116,8 @@ test_expect_success '--ignore-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n \tgit rebase -r --root --ignore-date &&\n-\tgit rev-list HEAD >rev_list &&\n-\twhile read HASH\n-\tdo\n-\t\tgit show $HASH --pretty=\"format:%ai\" >authortime\n-\t\tgrep \"+0000\" authortime\n-\tdone <rev_list\n+\tgit log --pretty=%ai >authortime &&\n+\t! grep -v \"+0000\" authortime\n '\n \n test_done\n-- \n2.26.0\n\n"},{"id":"394924","messageId":"20200407141125.30872-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T14:11:20Z","receivedAt":"2020-04-07T14:11:56Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThis reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.\n\nThis is being reverted to enable some fixups for\nra/rebase-i-more-options to be built on this commit.\n---\n Documentation/git-rebase.txt            |  27 ++++-\n builtin/rebase.c                        |  49 ++++++--\n sequencer.c                             | 141 ++++++++++++++++++++++--\n sequencer.h                             |   2 +\n t/t3422-rebase-incompatible-options.sh  |   2 -\n t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++\n 7 files changed, 327 insertions(+), 28 deletions(-)\n create mode 100755 t/t3433-rebase-options-compatibility.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 0c4f038dd6..1d0e2d27cc 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -393,16 +393,31 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tBehaves differently depending on which backend is selected.\n++\n+'am' backend: When applying a patch, ignore changes in whitespace in\n+context lines if necessary.\n++\n+'interactive' backend: Treat lines with only whitespace changes as\n+unchanged for the sake of a three-way merge.\n+\n --whitespace=<option>::\n-\tThese flag are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of recording the time the rebased commits are\n+\tcreated as the committer date, reuse the author date\n+\tas the committer date. This implies --force-rebase.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+--reset-author-date::\n+\tBy default, the author date of the original commit is used\n+\tas the author date for the resulting commit.  This option\n+\ttells Git to use the current timestamp instead and implies\n+\t`--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -539,10 +554,7 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --committer-date-is-author-date\n- * --ignore-date\n  * --whitespace\n- * --ignore-whitespace\n  * -C\n \n are incompatible with the following options:\n@@ -565,6 +577,9 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --interactive\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n+ * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 8081741f8a..e354ec84bb 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -79,8 +79,11 @@ struct rebase_options {\n \tint allow_rerere_autoupdate;\n \tint keep_empty;\n \tint autosquash;\n+\tint ignore_whitespace;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -99,6 +102,7 @@ struct rebase_options {\n \n static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n {\n+\tstruct strbuf strategy_buf = STRBUF_INIT;\n \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n \n \treplay.action = REPLAY_INTERACTIVE_REBASE;\n@@ -112,10 +116,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.allow_empty_message = opts->allow_empty_message;\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n-\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n+\t\tstrbuf_addstr(&strategy_buf, opts->strategy_opts);\n+\tif (opts->ignore_whitespace)\n+\t\tstrbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n+\tif (strategy_buf.len)\n+\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n+\n+\tstrbuf_release(&strategy_buf);\n \n \tif (opts->squash_onto) {\n \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n@@ -517,6 +531,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n \n+\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n+\n \tif (!is_null_oid(&squash_onto))\n \t\topts.squash_onto = &squash_onto;\n \n@@ -970,6 +986,12 @@ static int run_am(struct rebase_options *opts)\n \tam.git_cmd = 1;\n \targv_array_push(&am.args, \"am\");\n \n+\tif (opts->ignore_whitespace)\n+\t\targv_array_push(&am.args, \"--ignore-whitespace\");\n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--ignore-date\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1437,16 +1459,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n@@ -1719,11 +1742,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t    state_dir_base, cmd_live_rebase, buf.buf);\n \t}\n \n+\tif (options.committer_date_is_author_date ||\n+\t    options.ignore_date)\n+\t\toptions.flags |= REBASE_FORCE;\n+\n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\toptions.flags |= REBASE_FORCE;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\ndiff --git a/sequencer.c b/sequencer.c\nindex b9dbf1adb0..763ccbbc45 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -147,6 +147,8 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -823,9 +825,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,\n \t\terror(_(\"missing 'GIT_AUTHOR_DATE'\"));\n \tif (date_i < 0 || email_i < 0 || date_i < 0 || err)\n \t\tgoto finish;\n-\t*name = kv.items[name_i].util;\n-\t*email = kv.items[email_i].util;\n-\t*date = kv.items[date_i].util;\n+\n+\tif (name)\n+\t\t*name = kv.items[name_i].util;\n+\telse\n+\t\tfree(kv.items[name_i].util);\n+\tif (email)\n+\t\t*email = kv.items[email_i].util;\n+\telse\n+\t\tfree(kv.items[email_i].util);\n+\tif (date)\n+\t\t*date = kv.items[date_i].util;\n+\telse\n+\t\tfree(kv.items[date_i].util);\n \tretval = 0;\n finish:\n \tstring_list_clear(&kv, !!retval);\n@@ -868,6 +880,47 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+/* Returns a \"date\" string that needs to be free()'d by the caller */\n+static char *read_author_date_or_null(void)\n+{\n+\tchar *date;\n+\n+\tif (read_author_script(rebase_path_author_script(),\n+\t\t\t       NULL, NULL, &date, 0))\n+\t\treturn NULL;\n+\treturn date;\n+}\n+\n+/* Construct a free()able author string with current time as the author date */\n+static char *ignore_author_date(const char *author)\n+{\n+\tint len = strlen(author);\n+\tstruct ident_split ident;\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\n+\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\terror(_(\"malformed ident line\"));\n+\t\treturn NULL;\n+\t}\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\n+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n+static void push_dates(struct child_process *child, int change_committer_date)\n+{\n+\ttime_t now = time(NULL);\n+\tstruct strbuf date = STRBUF_INIT;\n+\n+\tstrbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n+\targv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n+\tif (change_committer_date)\n+\t\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n+\tstrbuf_release(&date);\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -927,6 +980,25 @@ static int run_git_commit(struct repository *r,\n \n \tcmd.git_cmd = 1;\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tint res = -1;\n+\t\tstruct strbuf datebuf = STRBUF_INIT;\n+\t\tchar *date = read_author_date_or_null();\n+\n+\t\tif (!date)\n+\t\t\treturn -1;\n+\n+\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : datebuf.buf, 1);\n+\n+\t\tstrbuf_release(&datebuf);\n+\t\tfree(date);\n+\n+\t\tif (res)\n+\t\t\treturn -1;\n+\t}\n+\n \tif (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {\n \t\tconst char *gpg_opt = gpg_sign_opt_quoted(opts);\n \n@@ -942,6 +1014,8 @@ static int run_git_commit(struct repository *r,\n \t\targv_array_push(&cmd.args, \"--amend\");\n \tif (opts->gpg_sign)\n \t\targv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n+\tif (opts->ignore_date)\n+\t\tpush_dates(&cmd, opts->committer_date_is_author_date);\n \tif (defmsg)\n \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n \telse if (!(flags & EDIT_MSG))\n@@ -1310,14 +1384,13 @@ static int try_to_commit(struct repository *r,\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n-\tchar *amend_author = NULL;\n+\tchar *author_to_free = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n \n \tif (parse_head(r, &current_head))\n \t\treturn -1;\n-\n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n \t\tconst char *out_enc = get_commit_output_encoding();\n@@ -1332,7 +1405,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tstrbuf_addstr(msg, orig_message);\n \t\t\thook_commit = \"HEAD\";\n \t\t}\n-\t\tauthor = amend_author = get_author(message);\n+\t\tauthor = author_to_free = get_author(message);\n \t\tunuse_commit_buffer(current_head, message);\n \t\tif (!author) {\n \t\t\tres = error(_(\"unable to parse commit author\"));\n@@ -1345,6 +1418,31 @@ static int try_to_commit(struct repository *r,\n \t\tcommit_list_insert(current_head, &parents);\n \t}\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tint len = strlen(author);\n+\t\tstruct ident_split ident;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\t\tres = error(_(\"malformed ident line\"));\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!ident.date_begin) {\n+\t\t\tres = error(_(\"corrupted author without date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n+\t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n+\t\tstrbuf_release(&date);\n+\n+\t\tif (res)\n+\t\t\tgoto out;\n+\t}\n+\n \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n \t\tres = error(_(\"git write-tree failed to write a tree\"));\n \t\tgoto out;\n@@ -1404,6 +1502,15 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tauthor = ignore_author_date(author);\n+\t\tif (!author) {\n+\t\t\tres = -1;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tfree(author_to_free);\n+\t\tauthor_to_free = (char *)author;\n+\t}\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -1424,7 +1531,7 @@ static int try_to_commit(struct repository *r,\n \tfree_commit_extra_headers(extra);\n \tstrbuf_release(&err);\n \tstrbuf_release(&commit_msg);\n-\tfree(amend_author);\n+\tfree(author_to_free);\n \n \treturn res;\n }\n@@ -2492,6 +2599,16 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2574,6 +2691,10 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_gpg_sign_opt(), \"-S%s\\n\", opts->gpg_sign);\n \tif (opts->signoff)\n \t\twrite_file(rebase_path_signoff(), \"--signoff\\n\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3514,6 +3635,8 @@ static int do_merge(struct repository *r,\n \t\targv_array_push(&cmd.args, git_path_merge_msg(r));\n \t\tif (opts->gpg_sign)\n \t\t\targv_array_push(&cmd.args, opts->gpg_sign);\n+\t\tif (opts->ignore_date)\n+\t\t\tpush_dates(&cmd, opts->committer_date_is_author_date);\n \n \t\t/* Add the tips to be merged */\n \t\tfor (j = to_merge; j; j = j->next)\n@@ -3786,7 +3909,9 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t\topts->record_origin || opts->edit ||\n+\t\t\t\topts->committer_date_is_author_date ||\n+\t\t\t\topts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 9f9ae291e3..e9a0e03ea2 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -43,6 +43,8 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,8 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nnew file mode 100755\nindex 0000000000..5166f158dd\n--- /dev/null\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -0,0 +1,131 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\tq_to_tab >file <<-\\EOF &&\n+\tline 1\n+\tQline 2\n+\tline 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tcat >file <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n+\n+\tgit checkout --orphan master &&\n+\tgit rm --cached foo &&\n+\trm foo &&\n+\tsed -e \"s/^|//\" >file <<-\\EOF &&\n+\t|line 1\n+\t|        line 2\n+\t|line 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with am backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--ignore-whitespace works with interactive backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with am backend' '\n+\tgit commit --amend &&\n+\tgit rebase --committer-date-is-author-date HEAD^ &&\n+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n+\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with interactive backend' '\n+\tgit commit --amend &&\n+\tgit rebase -i --committer-date-is-author-date HEAD^ &&\n+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n+\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\tgit rev-list HEAD >rev_list &&\n+\twhile read HASH\n+\tdo\n+\t\tgit show $HASH --pretty=\"format:%ai\" >authortime\n+\t\tgit show $HASH --pretty=\"format:%ci\" >committertime\n+\t\ttest_cmp authortime committertime\n+\tdone <rev_list\n+'\n+\n+# Checking for +0000 in author time is enough since default\n+# timezone is UTC, but the timezone used while committing\n+# sets to +0530.\n+test_expect_success '--ignore-date works with am backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date HEAD^ &&\n+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works with interactive backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -i HEAD^ &&\n+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\tgit rev-list HEAD >rev_list &&\n+\twhile read HASH\n+\tdo\n+\t\tgit show $HASH --pretty=\"format:%ai\" >authortime\n+\t\tgrep \"+0000\" authortime\n+\tdone <rev_list\n+'\n+\n+test_done\n-- \n2.26.0\n\n"},{"id":"394923","messageId":"20200407141125.30872-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH 3/6] t3433: only compare commit dates","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T14:11:22Z","receivedAt":"2020-04-07T14:11:57Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\n`git show` shows the diff by default so these tests which are about\nchecking dates were also comparing the diffs. Fix that by switching to\n`git log -1`\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n t/t3433-rebase-options-compatibility.sh | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 2b4d75f1ef..132f577fc9 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -73,16 +73,16 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n test_expect_success '--committer-date-is-author-date works with am backend' '\n \tgit commit --amend &&\n \tgit rebase --committer-date-is-author-date HEAD^ &&\n-\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n-\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n \ttest_cmp authortime committertime\n '\n \n test_expect_success '--committer-date-is-author-date works with interactive backend' '\n \tgit commit --amend &&\n \tgit rebase -i --committer-date-is-author-date HEAD^ &&\n-\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n-\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n \ttest_cmp authortime committertime\n '\n \n@@ -101,14 +101,14 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '\n test_expect_success '--ignore-date works with am backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n \tgit rebase --ignore-date HEAD^ &&\n-\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n test_expect_success '--ignore-date works with interactive backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n \tgit rebase --ignore-date -i HEAD^ &&\n-\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n-- \n2.26.0\n\n"},{"id":"394926","messageId":"20200407141125.30872-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH 4/6] rebase -i: fix --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T14:11:23Z","receivedAt":"2020-04-07T14:11:58Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nJohanathan Nieder reported that `rebase --committer-date-is-author-date`\nfailed with the error \"invalid date format: @@2592000 +0000\" when the\nbackend was switched to use the sequencer [1]. This is because when we\nread the date from the author script file is already prefixed by '@' so\nwe do not need to add one. This did not show up in our tests\nbecause once match_object_header_date() fails to match because of the\nextra '@' parse_date_basic() strips the prefix and a date with more than\n8 digits is parsed as a number of seconds by match_digit().\n\nWhile fixing this I also noticed that we were not setting\nGIT_COMMITTER_DATE in the environment when forking `git merge`. This was\nuntested. The tests we did have used commits where the author date was\nthe same as the current value $GIT_COMMITTER_DATE in the environment so\nthey did not test that we were actually using the author date when\ncreating the commit.\n\nAs we have already read GIT_AUTHOR_DATE into cmd.env_array we now use\nthat rather than re-reading the author-script file. I've moved the code\nthat handles opts->ignore date so that all the code setting the child\nenvironment is together and changed it so we no longer set\nGIT_COMMITTER_DATE twice when --ignore-date is combined with\n--committer-date-is-author-date.\n\n[1] https://lore.kernel.org/git/<20200110231436.GA24315@google.com>\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n sequencer.c                             | 68 ++++++++++---------------\n t/t3433-rebase-options-compatibility.sh | 29 +++++++++--\n 2 files changed, 52 insertions(+), 45 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 763ccbbc45..56f6e49289 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -880,17 +880,6 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n-/* Returns a \"date\" string that needs to be free()'d by the caller */\n-static char *read_author_date_or_null(void)\n-{\n-\tchar *date;\n-\n-\tif (read_author_script(rebase_path_author_script(),\n-\t\t\t       NULL, NULL, &date, 0))\n-\t\treturn NULL;\n-\treturn date;\n-}\n-\n /* Construct a free()able author string with current time as the author date */\n static char *ignore_author_date(const char *author)\n {\n@@ -909,16 +898,20 @@ static char *ignore_author_date(const char *author)\n \treturn strbuf_detach(&new_author, NULL);\n }\n \n-static void push_dates(struct child_process *child, int change_committer_date)\n+static const char *author_date_from_env_array(const struct argv_array *env)\n {\n-\ttime_t now = time(NULL);\n-\tstruct strbuf date = STRBUF_INIT;\n+\tint i;\n+\tconst char *date;\n \n-\tstrbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n-\targv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n-\tif (change_committer_date)\n-\t\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n-\tstrbuf_release(&date);\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n }\n \n static const char staged_changes_advice[] =\n@@ -980,31 +973,19 @@ static int run_git_commit(struct repository *r,\n \n \tcmd.git_cmd = 1;\n \n-\tif (opts->committer_date_is_author_date) {\n-\t\tint res = -1;\n-\t\tstruct strbuf datebuf = STRBUF_INIT;\n-\t\tchar *date = read_author_date_or_null();\n-\n-\t\tif (!date)\n-\t\t\treturn -1;\n-\n-\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n-\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n-\t\t\t     opts->ignore_date ? \"\" : datebuf.buf, 1);\n-\n-\t\tstrbuf_release(&datebuf);\n-\t\tfree(date);\n-\n-\t\tif (res)\n-\t\t\treturn -1;\n-\t}\n-\n \tif (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {\n \t\tconst char *gpg_opt = gpg_sign_opt_quoted(opts);\n \n \t\treturn error(_(staged_changes_advice),\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1014,8 +995,6 @@ static int run_git_commit(struct repository *r,\n \t\targv_array_push(&cmd.args, \"--amend\");\n \tif (opts->gpg_sign)\n \t\targv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n-\tif (opts->ignore_date)\n-\t\tpush_dates(&cmd, opts->committer_date_is_author_date);\n \tif (defmsg)\n \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n \telse if (!(flags & EDIT_MSG))\n@@ -3615,6 +3594,13 @@ static int do_merge(struct repository *r,\n \t\t\tret = error(_(staged_changes_advice), gpg_opt, gpg_opt);\n \t\t\tgoto leave_merge;\n \t\t}\n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3635,8 +3621,6 @@ static int do_merge(struct repository *r,\n \t\targv_array_push(&cmd.args, git_path_merge_msg(r));\n \t\tif (opts->gpg_sign)\n \t\t\targv_array_push(&cmd.args, opts->gpg_sign);\n-\t\tif (opts->ignore_date)\n-\t\t\tpush_dates(&cmd, opts->committer_date_is_author_date);\n \n \t\t/* Add the tips to be merged */\n \t\tfor (j = to_merge; j; j = j->next)\ndiff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 132f577fc9..8247d01442 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -71,15 +71,15 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n '\n \n test_expect_success '--committer-date-is-author-date works with am backend' '\n-\tgit commit --amend &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n \tgit rebase --committer-date-is-author-date HEAD^ &&\n \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgit log -1 --pretty=\"format:%ci\" >committertime &&\n \ttest_cmp authortime committertime\n '\n \n test_expect_success '--committer-date-is-author-date works with interactive backend' '\n-\tgit commit --amend &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n \tgit rebase -i --committer-date-is-author-date HEAD^ &&\n \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgit log -1 --pretty=\"format:%ci\" >committertime &&\n@@ -88,13 +88,36 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n \n test_expect_success '--committer-date-is-author-date works with rebase -r' '\n \tgit checkout side &&\n-\tgit merge --no-ff commit3 &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n \tgit rebase -r --root --committer-date-is-author-date &&\n \tgit log --pretty=\"format:%ai\" >authortime &&\n \tgit log --pretty=\"format:%ci\" >committertime &&\n \ttest_cmp authortime committertime\n '\n \n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n+\tgit log --pretty=\"format:%ai\" >authortime &&\n+\tgit log --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\tgit log -1 --format=%at HEAD >expect &&\n+\ttest_must_fail git rebase -i --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -1 --format=%ct HEAD >actual &&\n+\ttest_cmp expect actual\n+'\n+\n # Checking for +0000 in author time is enough since default\n # timezone is UTC, but the timezone used while committing\n # sets to +0530.\n-- \n2.26.0\n\n"},{"id":"394925","messageId":"20200407141125.30872-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH 5/6] Revert \"sequencer: allow callers of read_author_script() to ignore fields\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T14:11:24Z","receivedAt":"2020-04-07T14:11:59Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThis reverts commit c068bcc59b4f16322a77b6a47b53d44b05c51fec.\n\nThis functionality is no longer used as since the last commit we always\nwant all of the fields returned.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n sequencer.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 56f6e49289..17c7b18245 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -825,19 +825,9 @@ int read_author_script(const char *path, char **name, char **email, char **date,\n \t\terror(_(\"missing 'GIT_AUTHOR_DATE'\"));\n \tif (date_i < 0 || email_i < 0 || date_i < 0 || err)\n \t\tgoto finish;\n-\n-\tif (name)\n-\t\t*name = kv.items[name_i].util;\n-\telse\n-\t\tfree(kv.items[name_i].util);\n-\tif (email)\n-\t\t*email = kv.items[email_i].util;\n-\telse\n-\t\tfree(kv.items[email_i].util);\n-\tif (date)\n-\t\t*date = kv.items[date_i].util;\n-\telse\n-\t\tfree(kv.items[date_i].util);\n+\t*name = kv.items[name_i].util;\n+\t*email = kv.items[email_i].util;\n+\t*date = kv.items[date_i].util;\n \tretval = 0;\n finish:\n \tstring_list_clear(&kv, !!retval);\n-- \n2.26.0\n\n"},{"id":"394927","messageId":"20200407141125.30872-7-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH 6/6] t3433: improve coverage","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T14:11:25Z","receivedAt":"2020-04-07T14:12:00Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nAdd tests to check --ignore-whitespace and --ignore-date are remembered\nwhen running `rebase --continue` and to check\n--committer-date-is-author-date with --ignore-date gives the expected\nresult.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n t/t3433-rebase-options-compatibility.sh | 55 +++++++++++++++++++++++++\n 1 file changed, 55 insertions(+)\n\ndiff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 8247d01442..a13c341301 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -7,6 +7,8 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . ./test-lib.sh\n \n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n export GIT_AUTHOR_DATE\n \n@@ -70,6 +72,22 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n \ttest_cmp expect file\n '\n \n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" &&\n+\t\texport FAKE_LINES &&\n+\t\tgit rebase -i --ignore-whitespace main side\n+\t) &&\n+\tgit rebase --continue &&\n+\ttest_cmp expect file\n+'\n+\n test_expect_success '--committer-date-is-author-date works with am backend' '\n \tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n \tgit rebase --committer-date-is-author-date HEAD^ &&\n@@ -135,6 +153,16 @@ test_expect_success '--ignore-date works with interactive backend' '\n \tgrep \"+0000\" authortime\n '\n \n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -i \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log --pretty=%ai >authortime &&\n+\tgrep +0000 authortime\n+'\n+\n test_expect_success '--ignore-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n@@ -143,4 +171,31 @@ test_expect_success '--ignore-date works with rebase -r' '\n \t! grep -v \"+0000\" authortime\n '\n \n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -i --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -2 --pretty=%ai >authortime &&\n+\tgit log -2 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\t! grep -v \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tgit rebase -i --strategy=resolve --ignore-date \\\n+\t\t--committer-date-is-author-date side side &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgit log -1 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\tgrep \"+0000\" authortime\n+ '\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n test_done\n-- \n2.26.0\n\n"},{"id":"394953","messageId":"CABPp-BENw_tdukSEix+0EyjYbh4-jxyN9GYqHbuHNVaK9ax36Q@mail.gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-3-phillip.wood123@gmail.com","subject":"Re: [PATCH 2/6] t3433: remove loops from tests","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-04-07T14:30:13Z","receivedAt":"2020-04-07T14:30:26Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> Looping inside a test is asking for trouble as we only detect any\n> failure on the last iteration. Instead get all the dates at once which\n> is also more efficient. Note the previous code accidentally compared the\n> diffs as well as the dates this is fixed as well.\n\nAdd a semicolon between \"dates\" and \"this\" in the last sentence?\n\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  t/t3433-rebase-options-compatibility.sh | 18 +++++-------------\n>  1 file changed, 5 insertions(+), 13 deletions(-)\n>\n> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 5166f158dd..2b4d75f1ef 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -90,13 +90,9 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>         git checkout side &&\n>         git merge --no-ff commit3 &&\n>         git rebase -r --root --committer-date-is-author-date &&\n> -       git rev-list HEAD >rev_list &&\n> -       while read HASH\n> -       do\n> -               git show $HASH --pretty=\"format:%ai\" >authortime\n> -               git show $HASH --pretty=\"format:%ci\" >committertime\n> -               test_cmp authortime committertime\n> -       done <rev_list\n> +       git log --pretty=\"format:%ai\" >authortime &&\n> +       git log --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n>  '\n>\n>  # Checking for +0000 in author time is enough since default\n> @@ -120,12 +116,8 @@ test_expect_success '--ignore-date works with rebase -r' '\n>         git checkout side &&\n>         git merge --no-ff commit3 &&\n>         git rebase -r --root --ignore-date &&\n> -       git rev-list HEAD >rev_list &&\n> -       while read HASH\n> -       do\n> -               git show $HASH --pretty=\"format:%ai\" >authortime\n> -               grep \"+0000\" authortime\n> -       done <rev_list\n> +       git log --pretty=%ai >authortime &&\n> +       ! grep -v \"+0000\" authortime\n>  '\n\nThe new form is much more readable (and more correct and efficient, as\nyou point out).  Thanks.\n"},{"id":"394960","messageId":"CABPp-BFu0mgNnxcuZZ_kBJ3WWXxCNSZAFdmq9zKT4H9i47sNsA@mail.gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-5-phillip.wood123@gmail.com","subject":"Re: [PATCH 4/6] rebase -i: fix --committer-date-is-author-date","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-04-07T15:05:17Z","receivedAt":"2020-04-07T15:05:31Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> Johanathan Nieder reported that `rebase --committer-date-is-author-date`\n> failed with the error \"invalid date format: @@2592000 +0000\" when the\n> backend was switched to use the sequencer [1]. This is because when we\n> read the date from the author script file is already prefixed by '@' so\n> we do not need to add one. This did not show up in our tests\n> because once match_object_header_date() fails to match because of the\n> extra '@' parse_date_basic() strips the prefix and a date with more than\n> 8 digits is parsed as a number of seconds by match_digit().\n>\n> While fixing this I also noticed that we were not setting\n> GIT_COMMITTER_DATE in the environment when forking `git merge`. This was\n> untested. The tests we did have used commits where the author date was\n> the same as the current value $GIT_COMMITTER_DATE in the environment so\n> they did not test that we were actually using the author date when\n> creating the commit.\n>\n> As we have already read GIT_AUTHOR_DATE into cmd.env_array we now use\n> that rather than re-reading the author-script file. I've moved the code\n> that handles opts->ignore date so that all the code setting the child\n> environment is together and changed it so we no longer set\n> GIT_COMMITTER_DATE twice when --ignore-date is combined with\n> --committer-date-is-author-date.\n>\n> [1] https://lore.kernel.org/git/<20200110231436.GA24315@google.com>\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  sequencer.c                             | 68 ++++++++++---------------\n>  t/t3433-rebase-options-compatibility.sh | 29 +++++++++--\n>  2 files changed, 52 insertions(+), 45 deletions(-)\n>\n> diff --git a/sequencer.c b/sequencer.c\n> index 763ccbbc45..56f6e49289 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -880,17 +880,6 @@ static char *get_author(const char *message)\n>         return NULL;\n>  }\n>\n> -/* Returns a \"date\" string that needs to be free()'d by the caller */\n> -static char *read_author_date_or_null(void)\n> -{\n> -       char *date;\n> -\n> -       if (read_author_script(rebase_path_author_script(),\n> -                              NULL, NULL, &date, 0))\n> -               return NULL;\n> -       return date;\n> -}\n> -\n>  /* Construct a free()able author string with current time as the author date */\n>  static char *ignore_author_date(const char *author)\n>  {\n> @@ -909,16 +898,20 @@ static char *ignore_author_date(const char *author)\n>         return strbuf_detach(&new_author, NULL);\n>  }\n>\n> -static void push_dates(struct child_process *child, int change_committer_date)\n> +static const char *author_date_from_env_array(const struct argv_array *env)\n>  {\n> -       time_t now = time(NULL);\n> -       struct strbuf date = STRBUF_INIT;\n> +       int i;\n> +       const char *date;\n>\n> -       strbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n> -       argv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n> -       if (change_committer_date)\n> -               argv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n> -       strbuf_release(&date);\n> +       for (i = 0; i < env->argc; i++)\n> +               if (skip_prefix(env->argv[i],\n> +                               \"GIT_AUTHOR_DATE=\", &date))\n> +                       return date;\n\nIs there any risk that GIT_AUTHOR_DATE=<somedate> will appear twice in\n@child->env_array ?  If there is, should we read through the whole\nlist to make sure we take the last one?\n\n> +       /*\n> +        * If GIT_AUTHOR_DATE is missing we should have already errored out when\n> +        * reading the script\n> +        */\n> +       BUG(\"GIT_AUTHOR_DATE missing from author script\");\n>  }\n>\n>  static const char staged_changes_advice[] =\n> @@ -980,31 +973,19 @@ static int run_git_commit(struct repository *r,\n>\n>         cmd.git_cmd = 1;\n>\n> -       if (opts->committer_date_is_author_date) {\n> -               int res = -1;\n> -               struct strbuf datebuf = STRBUF_INIT;\n> -               char *date = read_author_date_or_null();\n> -\n> -               if (!date)\n> -                       return -1;\n> -\n> -               strbuf_addf(&datebuf, \"@%s\", date);\n> -               res = setenv(\"GIT_COMMITTER_DATE\",\n> -                            opts->ignore_date ? \"\" : datebuf.buf, 1);\n> -\n> -               strbuf_release(&datebuf);\n> -               free(date);\n> -\n> -               if (res)\n> -                       return -1;\n> -       }\n> -\n>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {\n>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);\n>\n>                 return error(_(staged_changes_advice),\n>                              gpg_opt, gpg_opt);\n>         }\n> +       if (opts->committer_date_is_author_date)\n> +               argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +                                opts->ignore_date ?\n> +                                \"\" :\n> +                                author_date_from_env_array(&cmd.env_array));\n> +       if (opts->ignore_date)\n> +               argv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>\n>         argv_array_push(&cmd.args, \"commit\");\n>\n> @@ -1014,8 +995,6 @@ static int run_git_commit(struct repository *r,\n>                 argv_array_push(&cmd.args, \"--amend\");\n>         if (opts->gpg_sign)\n>                 argv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n> -       if (opts->ignore_date)\n> -               push_dates(&cmd, opts->committer_date_is_author_date);\n>         if (defmsg)\n>                 argv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>         else if (!(flags & EDIT_MSG))\n> @@ -3615,6 +3594,13 @@ static int do_merge(struct repository *r,\n>                         ret = error(_(staged_changes_advice), gpg_opt, gpg_opt);\n>                         goto leave_merge;\n>                 }\n> +               if (opts->committer_date_is_author_date)\n> +                       argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +                                        opts->ignore_date ?\n> +                                        \"\" :\n> +                                        author_date_from_env_array(&cmd.env_array));\n> +               if (opts->ignore_date)\n> +                       argv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>\n>                 cmd.git_cmd = 1;\n>                 argv_array_push(&cmd.args, \"merge\");\n> @@ -3635,8 +3621,6 @@ static int do_merge(struct repository *r,\n>                 argv_array_push(&cmd.args, git_path_merge_msg(r));\n>                 if (opts->gpg_sign)\n>                         argv_array_push(&cmd.args, opts->gpg_sign);\n> -               if (opts->ignore_date)\n> -                       push_dates(&cmd, opts->committer_date_is_author_date);\n>\n>                 /* Add the tips to be merged */\n>                 for (j = to_merge; j; j = j->next)\n> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 132f577fc9..8247d01442 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -71,15 +71,15 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n>  '\n>\n>  test_expect_success '--committer-date-is-author-date works with am backend' '\n> -       git commit --amend &&\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>         git rebase --committer-date-is-author-date HEAD^ &&\n>         git log -1 --pretty=\"format:%ai\" >authortime &&\n>         git log -1 --pretty=\"format:%ci\" >committertime &&\n>         test_cmp authortime committertime\n>  '\n>\n>  test_expect_success '--committer-date-is-author-date works with interactive backend' '\n> -       git commit --amend &&\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>         git rebase -i --committer-date-is-author-date HEAD^ &&\n>         git log -1 --pretty=\"format:%ai\" >authortime &&\n>         git log -1 --pretty=\"format:%ci\" >committertime &&\n> @@ -88,13 +88,36 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n>\n>  test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>         git checkout side &&\n> -       git merge --no-ff commit3 &&\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>         git rebase -r --root --committer-date-is-author-date &&\n>         git log --pretty=\"format:%ai\" >authortime &&\n>         git log --pretty=\"format:%ci\" >committertime &&\n>         test_cmp authortime committertime\n>  '\n>\n> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n> +       git checkout side &&\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +       git rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n> +       git log --pretty=\"format:%ai\" >authortime &&\n> +       git log --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n> +\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n> +       git checkout commit2 &&\n> +       GIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n> +       git log -1 --format=%at HEAD >expect &&\n> +       test_must_fail git rebase -i --committer-date-is-author-date \\\n> +               --onto HEAD^^ HEAD^ &&\n> +       echo resolved > foo &&\n> +       git add foo &&\n> +       git rebase --continue &&\n> +       git log -1 --format=%ct HEAD >actual &&\n> +       test_cmp expect actual\n> +'\n> +\n>  # Checking for +0000 in author time is enough since default\n>  # timezone is UTC, but the timezone used while committing\n>  # sets to +0530.\n> --\n> 2.26.0\n>\n"},{"id":"394962","messageId":"CABPp-BEr8dHY1f6trPBMAZxoP7a3SbtNZahLA4pj6rNomAMLZg@mail.gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-6-phillip.wood123@gmail.com","subject":"Re: [PATCH 5/6] Revert \"sequencer: allow callers of read_author_script() to ignore fields\"","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-04-07T15:06:41Z","receivedAt":"2020-04-07T15:06:55Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> This reverts commit c068bcc59b4f16322a77b6a47b53d44b05c51fec.\n>\n> This functionality is no longer used as since the last commit we always\n> want all of the fields returned.\n\nThat's a little hard to parse.  Maybe s/used as since/used; since/ ?\n\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  sequencer.c | 16 +++-------------\n>  1 file changed, 3 insertions(+), 13 deletions(-)\n>\n> diff --git a/sequencer.c b/sequencer.c\n> index 56f6e49289..17c7b18245 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -825,19 +825,9 @@ int read_author_script(const char *path, char **name, char **email, char **date,\n>                 error(_(\"missing 'GIT_AUTHOR_DATE'\"));\n>         if (date_i < 0 || email_i < 0 || date_i < 0 || err)\n>                 goto finish;\n> -\n> -       if (name)\n> -               *name = kv.items[name_i].util;\n> -       else\n> -               free(kv.items[name_i].util);\n> -       if (email)\n> -               *email = kv.items[email_i].util;\n> -       else\n> -               free(kv.items[email_i].util);\n> -       if (date)\n> -               *date = kv.items[date_i].util;\n> -       else\n> -               free(kv.items[date_i].util);\n> +       *name = kv.items[name_i].util;\n> +       *email = kv.items[email_i].util;\n> +       *date = kv.items[date_i].util;\n>         retval = 0;\n>  finish:\n>         string_list_clear(&kv, !!retval);\n> --\n> 2.26.0\n>\n"},{"id":"394964","messageId":"CABPp-BFZknddcEcAz02T7Uej0jNWtKAUW8hwS6CdMfAa5BhGgA@mail.gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-7-phillip.wood123@gmail.com","subject":"Re: [PATCH 6/6] t3433: improve coverage","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-04-07T15:13:30Z","receivedAt":"2020-04-07T15:13:45Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> Add tests to check --ignore-whitespace and --ignore-date are remembered\n> when running `rebase --continue` and to check\n> --committer-date-is-author-date with --ignore-date gives the expected\n> result.\n\nThanks for adding these.\n\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  t/t3433-rebase-options-compatibility.sh | 55 +++++++++++++++++++++++++\n\nt3433 is taken by t3433-rebase-across-mode-change.sh in upstream.\nWhen you revert the reversion of Rohit's changes, perhaps you need to\nrename his t3433 to some other file?\n\nAlso, the name \"rebase-options-compatibility\" suggest to me that it's\njust checking whether certain options can be used together.  Perhaps\nthe --ignore-whitespace and --ignore-date tests you add should go\nsomewhere else?\n\n>  1 file changed, 55 insertions(+)\n>\n> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 8247d01442..a13c341301 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -7,6 +7,8 @@ test_description='tests to ensure compatibility between am and interactive backe\n>\n>  . ./test-lib.sh\n>\n> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n> +\n>  GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n>  export GIT_AUTHOR_DATE\n>\n> @@ -70,6 +72,22 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n>         test_cmp expect file\n>  '\n>\n> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n> +       cat >expect <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       (\n> +               set_fake_editor &&\n> +               FAKE_LINES=\"break 1\" &&\n> +               export FAKE_LINES &&\n> +               git rebase -i --ignore-whitespace main side\n> +       ) &&\n> +       git rebase --continue &&\n> +       test_cmp expect file\n> +'\n> +\n>  test_expect_success '--committer-date-is-author-date works with am backend' '\n>         GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>         git rebase --committer-date-is-author-date HEAD^ &&\n> @@ -135,6 +153,16 @@ test_expect_success '--ignore-date works with interactive backend' '\n>         grep \"+0000\" authortime\n>  '\n>\n> +test_expect_success '--ignore-date works after conflict resolution' '\n> +       test_must_fail git rebase --ignore-date -i \\\n> +               --onto commit2^^ commit2^ commit2 &&\n\nI don't see any todo list here; is there a reason you are using -i\ninstead of say -m?  (Similar question applies for the subsequent tests\nyou add below too?)\n\n> +       echo resolved >foo &&\n> +       git add foo &&\n> +       git rebase --continue &&\n> +       git log --pretty=%ai >authortime &&\n> +       grep +0000 authortime\n> +'\n> +\n>  test_expect_success '--ignore-date works with rebase -r' '\n>         git checkout side &&\n>         git merge --no-ff commit3 &&\n> @@ -143,4 +171,31 @@ test_expect_success '--ignore-date works with rebase -r' '\n>         ! grep -v \"+0000\" authortime\n>  '\n>\n> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n> +       test_must_fail git rebase -i --committer-date-is-author-date \\\n> +               --ignore-date --onto commit2^^ commit2^ commit3 &&\n> +       git checkout --theirs foo &&\n> +       git add foo &&\n> +       git rebase --continue &&\n> +       git log -2 --pretty=%ai >authortime &&\n> +       git log -2 --pretty=%ci >committertime &&\n> +       test_cmp authortime committertime &&\n> +       ! grep -v \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n> +       GIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n> +               git rebase -i --strategy=resolve --ignore-date \\\n> +               --committer-date-is-author-date side side &&\n> +       git log -1 --pretty=%ai >authortime &&\n> +       git log -1 --pretty=%ci >committertime &&\n> +       test_cmp authortime committertime &&\n> +       grep \"+0000\" authortime\n> + '\n> +\n> +# This must be the last test in this file\n> +test_expect_success '$EDITOR and friends are unchanged' '\n> +       test_editor_unchanged\n> +'\n> +\n>  test_done\n> --\n> 2.26.0\n>\n"},{"id":"394965","messageId":"CABPp-BEnmpET=6rEdDXJWnPjzV33a2x6rKB6FQ-o8y+8ssK4jw@mail.gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-2-phillip.wood123@gmail.com","subject":"Re: [PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-04-07T15:16:09Z","receivedAt":"2020-04-07T15:16:25Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.\n>\n> This is being reverted to enable some fixups for\n> ra/rebase-i-more-options to be built on this commit.\n\nThis makes sense to me, but it will be only the second 'Revert\n\"Revert...\"' commit in all of git.git and I'm curious if Junio will be\nunhappy with it.\n\n> ---\n>  Documentation/git-rebase.txt            |  27 ++++-\n>  builtin/rebase.c                        |  49 ++++++--\n>  sequencer.c                             | 141 ++++++++++++++++++++++--\n>  sequencer.h                             |   2 +\n>  t/t3422-rebase-incompatible-options.sh  |   2 -\n>  t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++\n>  7 files changed, 327 insertions(+), 28 deletions(-)\n>  create mode 100755 t/t3433-rebase-options-compatibility.sh\n>\n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 0c4f038dd6..1d0e2d27cc 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -393,16 +393,31 @@ your branch contains commits which were dropped, this option can be used\n>  with `--keep-base` in order to drop those commits from your branch.\n>\n>  --ignore-whitespace::\n> +       Behaves differently depending on which backend is selected.\n> ++\n> +'am' backend: When applying a patch, ignore changes in whitespace in\n> +context lines if necessary.\n> ++\n> +'interactive' backend: Treat lines with only whitespace changes as\n> +unchanged for the sake of a three-way merge.\n> +\n>  --whitespace=<option>::\n> -       These flag are passed to the 'git apply' program\n> +       This flag is passed to the 'git apply' program\n>         (see linkgit:git-apply[1]) that applies the patch.\n>  +\n>  See also INCOMPATIBLE OPTIONS below.\n>\n>  --committer-date-is-author-date::\n> +       Instead of recording the time the rebased commits are\n> +       created as the committer date, reuse the author date\n> +       as the committer date. This implies --force-rebase.\n> +\n>  --ignore-date::\n> -       These flags are passed to 'git am' to easily change the dates\n> -       of the rebased commits (see linkgit:git-am[1]).\n> +--reset-author-date::\n> +       By default, the author date of the original commit is used\n> +       as the author date for the resulting commit.  This option\n> +       tells Git to use the current timestamp instead and implies\n> +       `--force-rebase`.\n>  +\n>  See also INCOMPATIBLE OPTIONS below.\n>\n> @@ -539,10 +554,7 @@ INCOMPATIBLE OPTIONS\n>\n>  The following options:\n>\n> - * --committer-date-is-author-date\n> - * --ignore-date\n>   * --whitespace\n> - * --ignore-whitespace\n>   * -C\n>\n>  are incompatible with the following options:\n> @@ -565,6 +577,9 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --interactive\n>   * --preserve-merges and --signoff\n>   * --preserve-merges and --rebase-merges\n> + * --preserve-merges and --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n> + * --preserve-merges and --ignore-date\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 8081741f8a..e354ec84bb 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -79,8 +79,11 @@ struct rebase_options {\n>         int allow_rerere_autoupdate;\n>         int keep_empty;\n>         int autosquash;\n> +       int ignore_whitespace;\n>         char *gpg_sign_opt;\n>         int autostash;\n> +       int committer_date_is_author_date;\n> +       int ignore_date;\n>         char *cmd;\n>         int allow_empty_message;\n>         int rebase_merges, rebase_cousins;\n> @@ -99,6 +102,7 @@ struct rebase_options {\n>\n>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  {\n> +       struct strbuf strategy_buf = STRBUF_INIT;\n>         struct replay_opts replay = REPLAY_OPTS_INIT;\n>\n>         replay.action = REPLAY_INTERACTIVE_REBASE;\n> @@ -112,10 +116,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>         replay.allow_empty_message = opts->allow_empty_message;\n>         replay.verbose = opts->flags & REBASE_VERBOSE;\n>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;\n> +       replay.committer_date_is_author_date =\n> +                                       opts->committer_date_is_author_date;\n> +       replay.ignore_date = opts->ignore_date;\n>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>         replay.strategy = opts->strategy;\n> +\n>         if (opts->strategy_opts)\n> -               parse_strategy_opts(&replay, opts->strategy_opts);\n> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);\n> +       if (opts->ignore_whitespace)\n> +               strbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n> +       if (strategy_buf.len)\n> +               parse_strategy_opts(&replay, strategy_buf.buf);\n> +\n> +       strbuf_release(&strategy_buf);\n>\n>         if (opts->squash_onto) {\n>                 oidcpy(&replay.squash_onto, opts->squash_onto);\n> @@ -517,6 +531,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>         argc = parse_options(argc, argv, prefix, options,\n>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n>\n> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n> +\n>         if (!is_null_oid(&squash_onto))\n>                 opts.squash_onto = &squash_onto;\n>\n> @@ -970,6 +986,12 @@ static int run_am(struct rebase_options *opts)\n>         am.git_cmd = 1;\n>         argv_array_push(&am.args, \"am\");\n>\n> +       if (opts->ignore_whitespace)\n> +               argv_array_push(&am.args, \"--ignore-whitespace\");\n> +       if (opts->committer_date_is_author_date)\n> +               argv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n> +       if (opts->ignore_date)\n> +               argv_array_push(&opts->git_am_opts, \"--ignore-date\");\n>         if (opts->action && !strcmp(\"continue\", opts->action)) {\n>                 argv_array_push(&am.args, \"--resolved\");\n>                 argv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n> @@ -1437,16 +1459,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>                 OPT_BOOL(0, \"signoff\", &options.signoff,\n>                          N_(\"add a Signed-off-by: line to each commit\")),\n> -               OPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n> -                                 NULL, N_(\"passed to 'git am'\"),\n> -                                 PARSE_OPT_NOARG),\n> -               OPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n> -                                 &options.git_am_opts, NULL,\n> -                                 N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> -               OPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n> -                                 N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> +               OPT_BOOL(0, \"committer-date-is-author-date\",\n> +                        &options.committer_date_is_author_date,\n> +                        N_(\"make committer date match author date\")),\n> +               OPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n> +                        N_(\"ignore author date and use current date\")),\n> +               OPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n> +                               N_(\"synonym of --reset-author-date\")),\n>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>                                   N_(\"passed to 'git apply'\"), 0),\n> +               OPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n> +                        N_(\"ignore changes in whitespace\")),\n>                 OPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>                                   N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>                 OPT_BIT('f', \"force-rebase\", &options.flags,\n> @@ -1719,11 +1742,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>                     state_dir_base, cmd_live_rebase, buf.buf);\n>         }\n>\n> +       if (options.committer_date_is_author_date ||\n> +           options.ignore_date)\n> +               options.flags |= REBASE_FORCE;\n> +\n>         for (i = 0; i < options.git_am_opts.argc; i++) {\n>                 const char *option = options.git_am_opts.argv[i], *p;\n> -               if (!strcmp(option, \"--committer-date-is-author-date\") ||\n> -                   !strcmp(option, \"--ignore-date\") ||\n> -                   !strcmp(option, \"--whitespace=fix\") ||\n> +               if (!strcmp(option, \"--whitespace=fix\") ||\n>                     !strcmp(option, \"--whitespace=strip\"))\n>                         options.flags |= REBASE_FORCE;\n>                 else if (skip_prefix(option, \"-C\", &p)) {\n> diff --git a/sequencer.c b/sequencer.c\n> index b9dbf1adb0..763ccbbc45 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -147,6 +147,8 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   * command-line.\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n> +static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -823,9 +825,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,\n>                 error(_(\"missing 'GIT_AUTHOR_DATE'\"));\n>         if (date_i < 0 || email_i < 0 || date_i < 0 || err)\n>                 goto finish;\n> -       *name = kv.items[name_i].util;\n> -       *email = kv.items[email_i].util;\n> -       *date = kv.items[date_i].util;\n> +\n> +       if (name)\n> +               *name = kv.items[name_i].util;\n> +       else\n> +               free(kv.items[name_i].util);\n> +       if (email)\n> +               *email = kv.items[email_i].util;\n> +       else\n> +               free(kv.items[email_i].util);\n> +       if (date)\n> +               *date = kv.items[date_i].util;\n> +       else\n> +               free(kv.items[date_i].util);\n>         retval = 0;\n>  finish:\n>         string_list_clear(&kv, !!retval);\n> @@ -868,6 +880,47 @@ static char *get_author(const char *message)\n>         return NULL;\n>  }\n>\n> +/* Returns a \"date\" string that needs to be free()'d by the caller */\n> +static char *read_author_date_or_null(void)\n> +{\n> +       char *date;\n> +\n> +       if (read_author_script(rebase_path_author_script(),\n> +                              NULL, NULL, &date, 0))\n> +               return NULL;\n> +       return date;\n> +}\n> +\n> +/* Construct a free()able author string with current time as the author date */\n> +static char *ignore_author_date(const char *author)\n> +{\n> +       int len = strlen(author);\n> +       struct ident_split ident;\n> +       struct strbuf new_author = STRBUF_INIT;\n> +\n> +       if (split_ident_line(&ident, author, len) < 0) {\n> +               error(_(\"malformed ident line\"));\n> +               return NULL;\n> +       }\n> +       len = ident.mail_end - ident.name_begin + 1;\n> +\n> +       strbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n> +       datestamp(&new_author);\n> +       return strbuf_detach(&new_author, NULL);\n> +}\n> +\n> +static void push_dates(struct child_process *child, int change_committer_date)\n> +{\n> +       time_t now = time(NULL);\n> +       struct strbuf date = STRBUF_INIT;\n> +\n> +       strbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n> +       argv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n> +       if (change_committer_date)\n> +               argv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n> +       strbuf_release(&date);\n> +}\n> +\n>  static const char staged_changes_advice[] =\n>  N_(\"you have staged changes in your working tree\\n\"\n>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n> @@ -927,6 +980,25 @@ static int run_git_commit(struct repository *r,\n>\n>         cmd.git_cmd = 1;\n>\n> +       if (opts->committer_date_is_author_date) {\n> +               int res = -1;\n> +               struct strbuf datebuf = STRBUF_INIT;\n> +               char *date = read_author_date_or_null();\n> +\n> +               if (!date)\n> +                       return -1;\n> +\n> +               strbuf_addf(&datebuf, \"@%s\", date);\n> +               res = setenv(\"GIT_COMMITTER_DATE\",\n> +                            opts->ignore_date ? \"\" : datebuf.buf, 1);\n> +\n> +               strbuf_release(&datebuf);\n> +               free(date);\n> +\n> +               if (res)\n> +                       return -1;\n> +       }\n> +\n>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {\n>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);\n>\n> @@ -942,6 +1014,8 @@ static int run_git_commit(struct repository *r,\n>                 argv_array_push(&cmd.args, \"--amend\");\n>         if (opts->gpg_sign)\n>                 argv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n> +       if (opts->ignore_date)\n> +               push_dates(&cmd, opts->committer_date_is_author_date);\n>         if (defmsg)\n>                 argv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>         else if (!(flags & EDIT_MSG))\n> @@ -1310,14 +1384,13 @@ static int try_to_commit(struct repository *r,\n>         struct commit_extra_header *extra = NULL;\n>         struct strbuf err = STRBUF_INIT;\n>         struct strbuf commit_msg = STRBUF_INIT;\n> -       char *amend_author = NULL;\n> +       char *author_to_free = NULL;\n>         const char *hook_commit = NULL;\n>         enum commit_msg_cleanup_mode cleanup;\n>         int res = 0;\n>\n>         if (parse_head(r, &current_head))\n>                 return -1;\n> -\n>         if (flags & AMEND_MSG) {\n>                 const char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n>                 const char *out_enc = get_commit_output_encoding();\n> @@ -1332,7 +1405,7 @@ static int try_to_commit(struct repository *r,\n>                         strbuf_addstr(msg, orig_message);\n>                         hook_commit = \"HEAD\";\n>                 }\n> -               author = amend_author = get_author(message);\n> +               author = author_to_free = get_author(message);\n>                 unuse_commit_buffer(current_head, message);\n>                 if (!author) {\n>                         res = error(_(\"unable to parse commit author\"));\n> @@ -1345,6 +1418,31 @@ static int try_to_commit(struct repository *r,\n>                 commit_list_insert(current_head, &parents);\n>         }\n>\n> +       if (opts->committer_date_is_author_date) {\n> +               int len = strlen(author);\n> +               struct ident_split ident;\n> +               struct strbuf date = STRBUF_INIT;\n> +\n> +               if (split_ident_line(&ident, author, len) < 0) {\n> +                       res = error(_(\"malformed ident line\"));\n> +                       goto out;\n> +               }\n> +               if (!ident.date_begin) {\n> +                       res = error(_(\"corrupted author without date information\"));\n> +                       goto out;\n> +               }\n> +\n> +               strbuf_addf(&date, \"@%.*s %.*s\",\n> +                           (int)(ident.date_end - ident.date_begin), ident.date_begin,\n> +                           (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n> +               res = setenv(\"GIT_COMMITTER_DATE\",\n> +                            opts->ignore_date ? \"\" : date.buf, 1);\n> +               strbuf_release(&date);\n> +\n> +               if (res)\n> +                       goto out;\n> +       }\n> +\n>         if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>                 res = error(_(\"git write-tree failed to write a tree\"));\n>                 goto out;\n> @@ -1404,6 +1502,15 @@ static int try_to_commit(struct repository *r,\n>\n>         reset_ident_date();\n>\n> +       if (opts->ignore_date) {\n> +               author = ignore_author_date(author);\n> +               if (!author) {\n> +                       res = -1;\n> +                       goto out;\n> +               }\n> +               free(author_to_free);\n> +               author_to_free = (char *)author;\n> +       }\n>         if (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n>                                  oid, author, opts->gpg_sign, extra)) {\n>                 res = error(_(\"failed to write commit object\"));\n> @@ -1424,7 +1531,7 @@ static int try_to_commit(struct repository *r,\n>         free_commit_extra_headers(extra);\n>         strbuf_release(&err);\n>         strbuf_release(&commit_msg);\n> -       free(amend_author);\n> +       free(author_to_free);\n>\n>         return res;\n>  }\n> @@ -2492,6 +2599,16 @@ static int read_populate_opts(struct replay_opts *opts)\n>                         opts->signoff = 1;\n>                 }\n>\n> +               if (file_exists(rebase_path_cdate_is_adate())) {\n> +                       opts->allow_ff = 0;\n> +                       opts->committer_date_is_author_date = 1;\n> +               }\n> +\n> +               if (file_exists(rebase_path_ignore_date())) {\n> +                       opts->allow_ff = 0;\n> +                       opts->ignore_date = 1;\n> +               }\n> +\n>                 if (file_exists(rebase_path_reschedule_failed_exec()))\n>                         opts->reschedule_failed_exec = 1;\n>\n> @@ -2574,6 +2691,10 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>                 write_file(rebase_path_gpg_sign_opt(), \"-S%s\\n\", opts->gpg_sign);\n>         if (opts->signoff)\n>                 write_file(rebase_path_signoff(), \"--signoff\\n\");\n> +       if (opts->committer_date_is_author_date)\n> +               write_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n> +       if (opts->ignore_date)\n> +               write_file(rebase_path_ignore_date(), \"%s\", \"\");\n>         if (opts->reschedule_failed_exec)\n>                 write_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>\n> @@ -3514,6 +3635,8 @@ static int do_merge(struct repository *r,\n>                 argv_array_push(&cmd.args, git_path_merge_msg(r));\n>                 if (opts->gpg_sign)\n>                         argv_array_push(&cmd.args, opts->gpg_sign);\n> +               if (opts->ignore_date)\n> +                       push_dates(&cmd, opts->committer_date_is_author_date);\n>\n>                 /* Add the tips to be merged */\n>                 for (j = to_merge; j; j = j->next)\n> @@ -3786,7 +3909,9 @@ static int pick_commits(struct repository *r,\n>         setenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>         if (opts->allow_ff)\n>                 assert(!(opts->signoff || opts->no_commit ||\n> -                               opts->record_origin || opts->edit));\n> +                               opts->record_origin || opts->edit ||\n> +                               opts->committer_date_is_author_date ||\n> +                               opts->ignore_date));\n>         if (read_and_refresh_cache(r, opts))\n>                 return -1;\n>\n> diff --git a/sequencer.h b/sequencer.h\n> index 9f9ae291e3..e9a0e03ea2 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -43,6 +43,8 @@ struct replay_opts {\n>         int verbose;\n>         int quiet;\n>         int reschedule_failed_exec;\n> +       int committer_date_is_author_date;\n> +       int ignore_date;\n>\n>         int mainline;\n>\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 50e7960702..c8234062c6 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,8 +61,6 @@ test_rebase_am_only () {\n>  }\n>\n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --ignore-whitespace\n> -test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>\n>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> new file mode 100755\n> index 0000000000..5166f158dd\n> --- /dev/null\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -0,0 +1,131 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2019 Rohit Ashiwal\n> +#\n> +\n> +test_description='tests to ensure compatibility between am and interactive backends'\n> +\n> +. ./test-lib.sh\n> +\n> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> +export GIT_AUTHOR_DATE\n> +\n> +# This is a special case in which both am and interactive backends\n> +# provide the same output. It was done intentionally because\n> +# both the backends fall short of optimal behaviour.\n> +test_expect_success 'setup' '\n> +       git checkout -b topic &&\n> +       q_to_tab >file <<-\\EOF &&\n> +       line 1\n> +       Qline 2\n> +       line 3\n> +       EOF\n> +       git add file &&\n> +       git commit -m \"add file\" &&\n> +       cat >file <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       git commit -am \"update file\" &&\n> +       git tag side &&\n> +       test_commit commit1 foo foo1 &&\n> +       test_commit commit2 foo foo2 &&\n> +       test_commit commit3 foo foo3 &&\n> +\n> +       git checkout --orphan master &&\n> +       git rm --cached foo &&\n> +       rm foo &&\n> +       sed -e \"s/^|//\" >file <<-\\EOF &&\n> +       |line 1\n> +       |        line 2\n> +       |line 3\n> +       EOF\n> +       git add file &&\n> +       git commit -m \"add file\" &&\n> +       git tag main\n> +'\n> +\n> +test_expect_success '--ignore-whitespace works with am backend' '\n> +       cat >expect <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       test_must_fail git rebase main side &&\n> +       git rebase --abort &&\n> +       git rebase --ignore-whitespace main side &&\n> +       test_cmp expect file\n> +'\n> +\n> +test_expect_success '--ignore-whitespace works with interactive backend' '\n> +       cat >expect <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       test_must_fail git rebase --merge main side &&\n> +       git rebase --abort &&\n> +       git rebase --merge --ignore-whitespace main side &&\n> +       test_cmp expect file\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with am backend' '\n> +       git commit --amend &&\n> +       git rebase --committer-date-is-author-date HEAD^ &&\n> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n> +       git show HEAD --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with interactive backend' '\n> +       git commit --amend &&\n> +       git rebase -i --committer-date-is-author-date HEAD^ &&\n> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n> +       git show HEAD --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n> +       git checkout side &&\n> +       git merge --no-ff commit3 &&\n> +       git rebase -r --root --committer-date-is-author-date &&\n> +       git rev-list HEAD >rev_list &&\n> +       while read HASH\n> +       do\n> +               git show $HASH --pretty=\"format:%ai\" >authortime\n> +               git show $HASH --pretty=\"format:%ci\" >committertime\n> +               test_cmp authortime committertime\n> +       done <rev_list\n> +'\n> +\n> +# Checking for +0000 in author time is enough since default\n> +# timezone is UTC, but the timezone used while committing\n> +# sets to +0530.\n> +test_expect_success '--ignore-date works with am backend' '\n> +       git commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +       git rebase --ignore-date HEAD^ &&\n> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n> +       grep \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date works with interactive backend' '\n> +       git commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +       git rebase --ignore-date -i HEAD^ &&\n> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n> +       grep \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date works with rebase -r' '\n> +       git checkout side &&\n> +       git merge --no-ff commit3 &&\n> +       git rebase -r --root --ignore-date &&\n> +       git rev-list HEAD >rev_list &&\n> +       while read HASH\n> +       do\n> +               git show $HASH --pretty=\"format:%ai\" >authortime\n> +               grep \"+0000\" authortime\n> +       done <rev_list\n> +'\n> +\n> +test_done\n> --\n> 2.26.0\n>\n"},{"id":"394966","messageId":"CABPp-BF5Z8zJLZ3e4G8bDUJjheP4D4-aLoLcpqWuJC+OqLTpDg@mail.gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"Re: [PATCH 0/6] fixup ra/rebase-i-more-options","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-04-07T15:17:29Z","receivedAt":"2020-04-07T15:17:43Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Hi Phillip,\n\nOn Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> The tests for ra/rebase-i-more-options were not as comprehensive as\n> they could have been and some of the tests that we did have didn't do\n> a good job of testing what they purported to. This series cleans up\n> the tests and fixes a couple of bugs (thanks to Jonathan Nieder for\n> reporting one of them). The bug fix reworks the code to try and make\n> it clearer.\n>\n> I've opted to add some cleanup commits on top of Rohit's work rather\n> than reworking his patches. These are based on top of 4d924528d8\n> (\"Revert \"Merge branch 'ra/rebase-i-more-options'\"\", 2020-01-12) there\n> are some conflicts when merging into pu. I had a quick look at the\n> conflicts and they appeared to be relatively straight forward to\n> resolve. If that impression is wrong let me know and I can rebase onto\n> master or try doing the merge myself and pushing it to github.\n>\n> Phillip Wood (6):\n>   Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"\n>   t3433: remove loops from tests\n>   t3433: only compare commit dates\n>   rebase -i: fix --committer-date-is-author-date\n>   Revert \"sequencer: allow callers of read_author_script() to ignore\n>     fields\"\n>   t3433: improve coverage\n>\n>  Documentation/git-rebase.txt            |  27 +++-\n>  builtin/rebase.c                        |  49 ++++--\n>  sequencer.c                             | 109 ++++++++++++-\n>  sequencer.h                             |   2 +\n>  t/t3422-rebase-incompatible-options.sh  |   2 -\n>  t/t3433-rebase-options-compatibility.sh | 201 ++++++++++++++++++++++++\n>  7 files changed, 368 insertions(+), 25 deletions(-)\n>  create mode 100755 t/t3433-rebase-options-compatibility.sh\n>\n> --\n> 2.26.0\n\nThanks for working on this!  I took a look over the series and noted a\nfew minor issues and questions, but it mostly looked good to me.\n\nElijah\n"},{"id":"394984","messageId":"35d165ec-1e19-1000-c8ec-7273ed6c98ce@gmail.com","threadId":"53176","inReplyTo":"CABPp-BEnmpET=6rEdDXJWnPjzV33a2x6rKB6FQ-o8y+8ssK4jw@mail.gmail.com","subject":"Re: [PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T18:01:21Z","receivedAt":"2020-04-07T18:01:58Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Elijah\n\nOn 07/04/2020 16:16, Elijah Newren wrote:\n> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.\n>>\n>> This is being reverted to enable some fixups for\n>> ra/rebase-i-more-options to be built on this commit.\n> \n> This makes sense to me, but it will be only the second 'Revert\n> \"Revert...\"' commit in all of git.git and I'm curious if Junio will be\n> unhappy with it.\n\nI wasn't sure what to do for the best, this seemed to be reasonable\n(originally I just based the patches on top of ra/rebase-i-more-options\nbut then they would be a pain to merge into pu because of the revert)\nbut if Junio has other ideas I'm happy to re-roll\n\nThanks for taking a look at this series\n\nPhillip\n\n>> ---\n>>  Documentation/git-rebase.txt            |  27 ++++-\n>>  builtin/rebase.c                        |  49 ++++++--\n>>  sequencer.c                             | 141 ++++++++++++++++++++++--\n>>  sequencer.h                             |   2 +\n>>  t/t3422-rebase-incompatible-options.sh  |   2 -\n>>  t/t3433-rebase-options-compatibility.sh | 131 ++++++++++++++++++++++\n>>  7 files changed, 327 insertions(+), 28 deletions(-)\n>>  create mode 100755 t/t3433-rebase-options-compatibility.sh\n>>\n>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n>> index 0c4f038dd6..1d0e2d27cc 100644\n>> --- a/Documentation/git-rebase.txt\n>> +++ b/Documentation/git-rebase.txt\n>> @@ -393,16 +393,31 @@ your branch contains commits which were dropped, this option can be used\n>>  with `--keep-base` in order to drop those commits from your branch.\n>>\n>>  --ignore-whitespace::\n>> +       Behaves differently depending on which backend is selected.\n>> ++\n>> +'am' backend: When applying a patch, ignore changes in whitespace in\n>> +context lines if necessary.\n>> ++\n>> +'interactive' backend: Treat lines with only whitespace changes as\n>> +unchanged for the sake of a three-way merge.\n>> +\n>>  --whitespace=<option>::\n>> -       These flag are passed to the 'git apply' program\n>> +       This flag is passed to the 'git apply' program\n>>         (see linkgit:git-apply[1]) that applies the patch.\n>>  +\n>>  See also INCOMPATIBLE OPTIONS below.\n>>\n>>  --committer-date-is-author-date::\n>> +       Instead of recording the time the rebased commits are\n>> +       created as the committer date, reuse the author date\n>> +       as the committer date. This implies --force-rebase.\n>> +\n>>  --ignore-date::\n>> -       These flags are passed to 'git am' to easily change the dates\n>> -       of the rebased commits (see linkgit:git-am[1]).\n>> +--reset-author-date::\n>> +       By default, the author date of the original commit is used\n>> +       as the author date for the resulting commit.  This option\n>> +       tells Git to use the current timestamp instead and implies\n>> +       `--force-rebase`.\n>>  +\n>>  See also INCOMPATIBLE OPTIONS below.\n>>\n>> @@ -539,10 +554,7 @@ INCOMPATIBLE OPTIONS\n>>\n>>  The following options:\n>>\n>> - * --committer-date-is-author-date\n>> - * --ignore-date\n>>   * --whitespace\n>> - * --ignore-whitespace\n>>   * -C\n>>\n>>  are incompatible with the following options:\n>> @@ -565,6 +577,9 @@ In addition, the following pairs of options are incompatible:\n>>   * --preserve-merges and --interactive\n>>   * --preserve-merges and --signoff\n>>   * --preserve-merges and --rebase-merges\n>> + * --preserve-merges and --ignore-whitespace\n>> + * --preserve-merges and --committer-date-is-author-date\n>> + * --preserve-merges and --ignore-date\n>>   * --keep-base and --onto\n>>   * --keep-base and --root\n>>\n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index 8081741f8a..e354ec84bb 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -79,8 +79,11 @@ struct rebase_options {\n>>         int allow_rerere_autoupdate;\n>>         int keep_empty;\n>>         int autosquash;\n>> +       int ignore_whitespace;\n>>         char *gpg_sign_opt;\n>>         int autostash;\n>> +       int committer_date_is_author_date;\n>> +       int ignore_date;\n>>         char *cmd;\n>>         int allow_empty_message;\n>>         int rebase_merges, rebase_cousins;\n>> @@ -99,6 +102,7 @@ struct rebase_options {\n>>\n>>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>  {\n>> +       struct strbuf strategy_buf = STRBUF_INIT;\n>>         struct replay_opts replay = REPLAY_OPTS_INIT;\n>>\n>>         replay.action = REPLAY_INTERACTIVE_REBASE;\n>> @@ -112,10 +116,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>         replay.allow_empty_message = opts->allow_empty_message;\n>>         replay.verbose = opts->flags & REBASE_VERBOSE;\n>>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>> +       replay.committer_date_is_author_date =\n>> +                                       opts->committer_date_is_author_date;\n>> +       replay.ignore_date = opts->ignore_date;\n>>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>>         replay.strategy = opts->strategy;\n>> +\n>>         if (opts->strategy_opts)\n>> -               parse_strategy_opts(&replay, opts->strategy_opts);\n>> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);\n>> +       if (opts->ignore_whitespace)\n>> +               strbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n>> +       if (strategy_buf.len)\n>> +               parse_strategy_opts(&replay, strategy_buf.buf);\n>> +\n>> +       strbuf_release(&strategy_buf);\n>>\n>>         if (opts->squash_onto) {\n>>                 oidcpy(&replay.squash_onto, opts->squash_onto);\n>> @@ -517,6 +531,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>>         argc = parse_options(argc, argv, prefix, options,\n>>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n>>\n>> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n>> +\n>>         if (!is_null_oid(&squash_onto))\n>>                 opts.squash_onto = &squash_onto;\n>>\n>> @@ -970,6 +986,12 @@ static int run_am(struct rebase_options *opts)\n>>         am.git_cmd = 1;\n>>         argv_array_push(&am.args, \"am\");\n>>\n>> +       if (opts->ignore_whitespace)\n>> +               argv_array_push(&am.args, \"--ignore-whitespace\");\n>> +       if (opts->committer_date_is_author_date)\n>> +               argv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n>> +       if (opts->ignore_date)\n>> +               argv_array_push(&opts->git_am_opts, \"--ignore-date\");\n>>         if (opts->action && !strcmp(\"continue\", opts->action)) {\n>>                 argv_array_push(&am.args, \"--resolved\");\n>>                 argv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n>> @@ -1437,16 +1459,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>>                 OPT_BOOL(0, \"signoff\", &options.signoff,\n>>                          N_(\"add a Signed-off-by: line to each commit\")),\n>> -               OPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n>> -                                 NULL, N_(\"passed to 'git am'\"),\n>> -                                 PARSE_OPT_NOARG),\n>> -               OPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>> -                                 &options.git_am_opts, NULL,\n>> -                                 N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>> -               OPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>> -                                 N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>> +               OPT_BOOL(0, \"committer-date-is-author-date\",\n>> +                        &options.committer_date_is_author_date,\n>> +                        N_(\"make committer date match author date\")),\n>> +               OPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n>> +                        N_(\"ignore author date and use current date\")),\n>> +               OPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n>> +                               N_(\"synonym of --reset-author-date\")),\n>>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>>                                   N_(\"passed to 'git apply'\"), 0),\n>> +               OPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n>> +                        N_(\"ignore changes in whitespace\")),\n>>                 OPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>>                                   N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>>                 OPT_BIT('f', \"force-rebase\", &options.flags,\n>> @@ -1719,11 +1742,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>                     state_dir_base, cmd_live_rebase, buf.buf);\n>>         }\n>>\n>> +       if (options.committer_date_is_author_date ||\n>> +           options.ignore_date)\n>> +               options.flags |= REBASE_FORCE;\n>> +\n>>         for (i = 0; i < options.git_am_opts.argc; i++) {\n>>                 const char *option = options.git_am_opts.argv[i], *p;\n>> -               if (!strcmp(option, \"--committer-date-is-author-date\") ||\n>> -                   !strcmp(option, \"--ignore-date\") ||\n>> -                   !strcmp(option, \"--whitespace=fix\") ||\n>> +               if (!strcmp(option, \"--whitespace=fix\") ||\n>>                     !strcmp(option, \"--whitespace=strip\"))\n>>                         options.flags |= REBASE_FORCE;\n>>                 else if (skip_prefix(option, \"-C\", &p)) {\n>> diff --git a/sequencer.c b/sequencer.c\n>> index b9dbf1adb0..763ccbbc45 100644\n>> --- a/sequencer.c\n>> +++ b/sequencer.c\n>> @@ -147,6 +147,8 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>>   * command-line.\n>>   */\n>>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n>> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>> +static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n>>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n>> @@ -823,9 +825,19 @@ int read_author_script(const char *path, char **name, char **email, char **date,\n>>                 error(_(\"missing 'GIT_AUTHOR_DATE'\"));\n>>         if (date_i < 0 || email_i < 0 || date_i < 0 || err)\n>>                 goto finish;\n>> -       *name = kv.items[name_i].util;\n>> -       *email = kv.items[email_i].util;\n>> -       *date = kv.items[date_i].util;\n>> +\n>> +       if (name)\n>> +               *name = kv.items[name_i].util;\n>> +       else\n>> +               free(kv.items[name_i].util);\n>> +       if (email)\n>> +               *email = kv.items[email_i].util;\n>> +       else\n>> +               free(kv.items[email_i].util);\n>> +       if (date)\n>> +               *date = kv.items[date_i].util;\n>> +       else\n>> +               free(kv.items[date_i].util);\n>>         retval = 0;\n>>  finish:\n>>         string_list_clear(&kv, !!retval);\n>> @@ -868,6 +880,47 @@ static char *get_author(const char *message)\n>>         return NULL;\n>>  }\n>>\n>> +/* Returns a \"date\" string that needs to be free()'d by the caller */\n>> +static char *read_author_date_or_null(void)\n>> +{\n>> +       char *date;\n>> +\n>> +       if (read_author_script(rebase_path_author_script(),\n>> +                              NULL, NULL, &date, 0))\n>> +               return NULL;\n>> +       return date;\n>> +}\n>> +\n>> +/* Construct a free()able author string with current time as the author date */\n>> +static char *ignore_author_date(const char *author)\n>> +{\n>> +       int len = strlen(author);\n>> +       struct ident_split ident;\n>> +       struct strbuf new_author = STRBUF_INIT;\n>> +\n>> +       if (split_ident_line(&ident, author, len) < 0) {\n>> +               error(_(\"malformed ident line\"));\n>> +               return NULL;\n>> +       }\n>> +       len = ident.mail_end - ident.name_begin + 1;\n>> +\n>> +       strbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n>> +       datestamp(&new_author);\n>> +       return strbuf_detach(&new_author, NULL);\n>> +}\n>> +\n>> +static void push_dates(struct child_process *child, int change_committer_date)\n>> +{\n>> +       time_t now = time(NULL);\n>> +       struct strbuf date = STRBUF_INIT;\n>> +\n>> +       strbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n>> +       argv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n>> +       if (change_committer_date)\n>> +               argv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n>> +       strbuf_release(&date);\n>> +}\n>> +\n>>  static const char staged_changes_advice[] =\n>>  N_(\"you have staged changes in your working tree\\n\"\n>>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n>> @@ -927,6 +980,25 @@ static int run_git_commit(struct repository *r,\n>>\n>>         cmd.git_cmd = 1;\n>>\n>> +       if (opts->committer_date_is_author_date) {\n>> +               int res = -1;\n>> +               struct strbuf datebuf = STRBUF_INIT;\n>> +               char *date = read_author_date_or_null();\n>> +\n>> +               if (!date)\n>> +                       return -1;\n>> +\n>> +               strbuf_addf(&datebuf, \"@%s\", date);\n>> +               res = setenv(\"GIT_COMMITTER_DATE\",\n>> +                            opts->ignore_date ? \"\" : datebuf.buf, 1);\n>> +\n>> +               strbuf_release(&datebuf);\n>> +               free(date);\n>> +\n>> +               if (res)\n>> +                       return -1;\n>> +       }\n>> +\n>>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {\n>>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);\n>>\n>> @@ -942,6 +1014,8 @@ static int run_git_commit(struct repository *r,\n>>                 argv_array_push(&cmd.args, \"--amend\");\n>>         if (opts->gpg_sign)\n>>                 argv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n>> +       if (opts->ignore_date)\n>> +               push_dates(&cmd, opts->committer_date_is_author_date);\n>>         if (defmsg)\n>>                 argv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>>         else if (!(flags & EDIT_MSG))\n>> @@ -1310,14 +1384,13 @@ static int try_to_commit(struct repository *r,\n>>         struct commit_extra_header *extra = NULL;\n>>         struct strbuf err = STRBUF_INIT;\n>>         struct strbuf commit_msg = STRBUF_INIT;\n>> -       char *amend_author = NULL;\n>> +       char *author_to_free = NULL;\n>>         const char *hook_commit = NULL;\n>>         enum commit_msg_cleanup_mode cleanup;\n>>         int res = 0;\n>>\n>>         if (parse_head(r, &current_head))\n>>                 return -1;\n>> -\n>>         if (flags & AMEND_MSG) {\n>>                 const char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n>>                 const char *out_enc = get_commit_output_encoding();\n>> @@ -1332,7 +1405,7 @@ static int try_to_commit(struct repository *r,\n>>                         strbuf_addstr(msg, orig_message);\n>>                         hook_commit = \"HEAD\";\n>>                 }\n>> -               author = amend_author = get_author(message);\n>> +               author = author_to_free = get_author(message);\n>>                 unuse_commit_buffer(current_head, message);\n>>                 if (!author) {\n>>                         res = error(_(\"unable to parse commit author\"));\n>> @@ -1345,6 +1418,31 @@ static int try_to_commit(struct repository *r,\n>>                 commit_list_insert(current_head, &parents);\n>>         }\n>>\n>> +       if (opts->committer_date_is_author_date) {\n>> +               int len = strlen(author);\n>> +               struct ident_split ident;\n>> +               struct strbuf date = STRBUF_INIT;\n>> +\n>> +               if (split_ident_line(&ident, author, len) < 0) {\n>> +                       res = error(_(\"malformed ident line\"));\n>> +                       goto out;\n>> +               }\n>> +               if (!ident.date_begin) {\n>> +                       res = error(_(\"corrupted author without date information\"));\n>> +                       goto out;\n>> +               }\n>> +\n>> +               strbuf_addf(&date, \"@%.*s %.*s\",\n>> +                           (int)(ident.date_end - ident.date_begin), ident.date_begin,\n>> +                           (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n>> +               res = setenv(\"GIT_COMMITTER_DATE\",\n>> +                            opts->ignore_date ? \"\" : date.buf, 1);\n>> +               strbuf_release(&date);\n>> +\n>> +               if (res)\n>> +                       goto out;\n>> +       }\n>> +\n>>         if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>>                 res = error(_(\"git write-tree failed to write a tree\"));\n>>                 goto out;\n>> @@ -1404,6 +1502,15 @@ static int try_to_commit(struct repository *r,\n>>\n>>         reset_ident_date();\n>>\n>> +       if (opts->ignore_date) {\n>> +               author = ignore_author_date(author);\n>> +               if (!author) {\n>> +                       res = -1;\n>> +                       goto out;\n>> +               }\n>> +               free(author_to_free);\n>> +               author_to_free = (char *)author;\n>> +       }\n>>         if (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n>>                                  oid, author, opts->gpg_sign, extra)) {\n>>                 res = error(_(\"failed to write commit object\"));\n>> @@ -1424,7 +1531,7 @@ static int try_to_commit(struct repository *r,\n>>         free_commit_extra_headers(extra);\n>>         strbuf_release(&err);\n>>         strbuf_release(&commit_msg);\n>> -       free(amend_author);\n>> +       free(author_to_free);\n>>\n>>         return res;\n>>  }\n>> @@ -2492,6 +2599,16 @@ static int read_populate_opts(struct replay_opts *opts)\n>>                         opts->signoff = 1;\n>>                 }\n>>\n>> +               if (file_exists(rebase_path_cdate_is_adate())) {\n>> +                       opts->allow_ff = 0;\n>> +                       opts->committer_date_is_author_date = 1;\n>> +               }\n>> +\n>> +               if (file_exists(rebase_path_ignore_date())) {\n>> +                       opts->allow_ff = 0;\n>> +                       opts->ignore_date = 1;\n>> +               }\n>> +\n>>                 if (file_exists(rebase_path_reschedule_failed_exec()))\n>>                         opts->reschedule_failed_exec = 1;\n>>\n>> @@ -2574,6 +2691,10 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>>                 write_file(rebase_path_gpg_sign_opt(), \"-S%s\\n\", opts->gpg_sign);\n>>         if (opts->signoff)\n>>                 write_file(rebase_path_signoff(), \"--signoff\\n\");\n>> +       if (opts->committer_date_is_author_date)\n>> +               write_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>> +       if (opts->ignore_date)\n>> +               write_file(rebase_path_ignore_date(), \"%s\", \"\");\n>>         if (opts->reschedule_failed_exec)\n>>                 write_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>>\n>> @@ -3514,6 +3635,8 @@ static int do_merge(struct repository *r,\n>>                 argv_array_push(&cmd.args, git_path_merge_msg(r));\n>>                 if (opts->gpg_sign)\n>>                         argv_array_push(&cmd.args, opts->gpg_sign);\n>> +               if (opts->ignore_date)\n>> +                       push_dates(&cmd, opts->committer_date_is_author_date);\n>>\n>>                 /* Add the tips to be merged */\n>>                 for (j = to_merge; j; j = j->next)\n>> @@ -3786,7 +3909,9 @@ static int pick_commits(struct repository *r,\n>>         setenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>>         if (opts->allow_ff)\n>>                 assert(!(opts->signoff || opts->no_commit ||\n>> -                               opts->record_origin || opts->edit));\n>> +                               opts->record_origin || opts->edit ||\n>> +                               opts->committer_date_is_author_date ||\n>> +                               opts->ignore_date));\n>>         if (read_and_refresh_cache(r, opts))\n>>                 return -1;\n>>\n>> diff --git a/sequencer.h b/sequencer.h\n>> index 9f9ae291e3..e9a0e03ea2 100644\n>> --- a/sequencer.h\n>> +++ b/sequencer.h\n>> @@ -43,6 +43,8 @@ struct replay_opts {\n>>         int verbose;\n>>         int quiet;\n>>         int reschedule_failed_exec;\n>> +       int committer_date_is_author_date;\n>> +       int ignore_date;\n>>\n>>         int mainline;\n>>\n>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>> index 50e7960702..c8234062c6 100755\n>> --- a/t/t3422-rebase-incompatible-options.sh\n>> +++ b/t/t3422-rebase-incompatible-options.sh\n>> @@ -61,8 +61,6 @@ test_rebase_am_only () {\n>>  }\n>>\n>>  test_rebase_am_only --whitespace=fix\n>> -test_rebase_am_only --ignore-whitespace\n>> -test_rebase_am_only --committer-date-is-author-date\n>>  test_rebase_am_only -C4\n>>\n>>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n>> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n>> new file mode 100755\n>> index 0000000000..5166f158dd\n>> --- /dev/null\n>> +++ b/t/t3433-rebase-options-compatibility.sh\n>> @@ -0,0 +1,131 @@\n>> +#!/bin/sh\n>> +#\n>> +# Copyright (c) 2019 Rohit Ashiwal\n>> +#\n>> +\n>> +test_description='tests to ensure compatibility between am and interactive backends'\n>> +\n>> +. ./test-lib.sh\n>> +\n>> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n>> +export GIT_AUTHOR_DATE\n>> +\n>> +# This is a special case in which both am and interactive backends\n>> +# provide the same output. It was done intentionally because\n>> +# both the backends fall short of optimal behaviour.\n>> +test_expect_success 'setup' '\n>> +       git checkout -b topic &&\n>> +       q_to_tab >file <<-\\EOF &&\n>> +       line 1\n>> +       Qline 2\n>> +       line 3\n>> +       EOF\n>> +       git add file &&\n>> +       git commit -m \"add file\" &&\n>> +       cat >file <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       git commit -am \"update file\" &&\n>> +       git tag side &&\n>> +       test_commit commit1 foo foo1 &&\n>> +       test_commit commit2 foo foo2 &&\n>> +       test_commit commit3 foo foo3 &&\n>> +\n>> +       git checkout --orphan master &&\n>> +       git rm --cached foo &&\n>> +       rm foo &&\n>> +       sed -e \"s/^|//\" >file <<-\\EOF &&\n>> +       |line 1\n>> +       |        line 2\n>> +       |line 3\n>> +       EOF\n>> +       git add file &&\n>> +       git commit -m \"add file\" &&\n>> +       git tag main\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace works with am backend' '\n>> +       cat >expect <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       test_must_fail git rebase main side &&\n>> +       git rebase --abort &&\n>> +       git rebase --ignore-whitespace main side &&\n>> +       test_cmp expect file\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace works with interactive backend' '\n>> +       cat >expect <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       test_must_fail git rebase --merge main side &&\n>> +       git rebase --abort &&\n>> +       git rebase --merge --ignore-whitespace main side &&\n>> +       test_cmp expect file\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with am backend' '\n>> +       git commit --amend &&\n>> +       git rebase --committer-date-is-author-date HEAD^ &&\n>> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n>> +       git show HEAD --pretty=\"format:%ci\" >committertime &&\n>> +       test_cmp authortime committertime\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with interactive backend' '\n>> +       git commit --amend &&\n>> +       git rebase -i --committer-date-is-author-date HEAD^ &&\n>> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n>> +       git show HEAD --pretty=\"format:%ci\" >committertime &&\n>> +       test_cmp authortime committertime\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>> +       git checkout side &&\n>> +       git merge --no-ff commit3 &&\n>> +       git rebase -r --root --committer-date-is-author-date &&\n>> +       git rev-list HEAD >rev_list &&\n>> +       while read HASH\n>> +       do\n>> +               git show $HASH --pretty=\"format:%ai\" >authortime\n>> +               git show $HASH --pretty=\"format:%ci\" >committertime\n>> +               test_cmp authortime committertime\n>> +       done <rev_list\n>> +'\n>> +\n>> +# Checking for +0000 in author time is enough since default\n>> +# timezone is UTC, but the timezone used while committing\n>> +# sets to +0530.\n>> +test_expect_success '--ignore-date works with am backend' '\n>> +       git commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n>> +       git rebase --ignore-date HEAD^ &&\n>> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n>> +       grep \"+0000\" authortime\n>> +'\n>> +\n>> +test_expect_success '--ignore-date works with interactive backend' '\n>> +       git commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n>> +       git rebase --ignore-date -i HEAD^ &&\n>> +       git show HEAD --pretty=\"format:%ai\" >authortime &&\n>> +       grep \"+0000\" authortime\n>> +'\n>> +\n>> +test_expect_success '--ignore-date works with rebase -r' '\n>> +       git checkout side &&\n>> +       git merge --no-ff commit3 &&\n>> +       git rebase -r --root --ignore-date &&\n>> +       git rev-list HEAD >rev_list &&\n>> +       while read HASH\n>> +       do\n>> +               git show $HASH --pretty=\"format:%ai\" >authortime\n>> +               grep \"+0000\" authortime\n>> +       done <rev_list\n>> +'\n>> +\n>> +test_done\n>> --\n>> 2.26.0\n>>\n\n"},{"id":"394986","messageId":"33f0ee87-7b6a-d48a-fd40-9c513a626a22@gmail.com","threadId":"53176","inReplyTo":"CABPp-BFu0mgNnxcuZZ_kBJ3WWXxCNSZAFdmq9zKT4H9i47sNsA@mail.gmail.com","subject":"Re: [PATCH 4/6] rebase -i: fix --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T18:11:20Z","receivedAt":"2020-04-07T18:11:27Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Elijah\n\nOn 07/04/2020 16:05, Elijah Newren wrote:\n> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> Johanathan Nieder reported that `rebase --committer-date-is-author-date`\n>> failed with the error \"invalid date format: @@2592000 +0000\" when the\n>> backend was switched to use the sequencer [1]. This is because when we\n>> read the date from the author script file is already prefixed by '@' so\n>> we do not need to add one. This did not show up in our tests\n>> because once match_object_header_date() fails to match because of the\n>> extra '@' parse_date_basic() strips the prefix and a date with more than\n>> 8 digits is parsed as a number of seconds by match_digit().\n>>\n>> While fixing this I also noticed that we were not setting\n>> GIT_COMMITTER_DATE in the environment when forking `git merge`. This was\n>> untested. The tests we did have used commits where the author date was\n>> the same as the current value $GIT_COMMITTER_DATE in the environment so\n>> they did not test that we were actually using the author date when\n>> creating the commit.\n>>\n>> As we have already read GIT_AUTHOR_DATE into cmd.env_array we now use\n>> that rather than re-reading the author-script file. I've moved the code\n>> that handles opts->ignore date so that all the code setting the child\n>> environment is together and changed it so we no longer set\n>> GIT_COMMITTER_DATE twice when --ignore-date is combined with\n>> --committer-date-is-author-date.\n>>\n>> [1] https://lore.kernel.org/git/<20200110231436.GA24315@google.com>\n>>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> ---\n>>  sequencer.c                             | 68 ++++++++++---------------\n>>  t/t3433-rebase-options-compatibility.sh | 29 +++++++++--\n>>  2 files changed, 52 insertions(+), 45 deletions(-)\n>>\n>> diff --git a/sequencer.c b/sequencer.c\n>> index 763ccbbc45..56f6e49289 100644\n>> --- a/sequencer.c\n>> +++ b/sequencer.c\n>> @@ -880,17 +880,6 @@ static char *get_author(const char *message)\n>>         return NULL;\n>>  }\n>>\n>> -/* Returns a \"date\" string that needs to be free()'d by the caller */\n>> -static char *read_author_date_or_null(void)\n>> -{\n>> -       char *date;\n>> -\n>> -       if (read_author_script(rebase_path_author_script(),\n>> -                              NULL, NULL, &date, 0))\n>> -               return NULL;\n>> -       return date;\n>> -}\n>> -\n>>  /* Construct a free()able author string with current time as the author date */\n>>  static char *ignore_author_date(const char *author)\n>>  {\n>> @@ -909,16 +898,20 @@ static char *ignore_author_date(const char *author)\n>>         return strbuf_detach(&new_author, NULL);\n>>  }\n>>\n>> -static void push_dates(struct child_process *child, int change_committer_date)\n>> +static const char *author_date_from_env_array(const struct argv_array *env)\n>>  {\n>> -       time_t now = time(NULL);\n>> -       struct strbuf date = STRBUF_INIT;\n>> +       int i;\n>> +       const char *date;\n>>\n>> -       strbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n>> -       argv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n>> -       if (change_committer_date)\n>> -               argv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n>> -       strbuf_release(&date);\n>> +       for (i = 0; i < env->argc; i++)\n>> +               if (skip_prefix(env->argv[i],\n>> +                               \"GIT_AUTHOR_DATE=\", &date))\n>> +                       return date;\n> \n> Is there any risk that GIT_AUTHOR_DATE=<somedate> will appear twice in\n> @child->env_array ?  If there is, should we read through the whole\n> list to make sure we take the last one?\n\nread_author_script() errors out if GIT_AUTHOR_DATE is missing or given\nmore than once\n\nBest Wishes\n\nPhillip\n\n> \n>> +       /*\n>> +        * If GIT_AUTHOR_DATE is missing we should have already errored out when\n>> +        * reading the script\n>> +        */\n>> +       BUG(\"GIT_AUTHOR_DATE missing from author script\");\n>>  }\n>>\n>>  static const char staged_changes_advice[] =\n>> @@ -980,31 +973,19 @@ static int run_git_commit(struct repository *r,\n>>\n>>         cmd.git_cmd = 1;\n>>\n>> -       if (opts->committer_date_is_author_date) {\n>> -               int res = -1;\n>> -               struct strbuf datebuf = STRBUF_INIT;\n>> -               char *date = read_author_date_or_null();\n>> -\n>> -               if (!date)\n>> -                       return -1;\n>> -\n>> -               strbuf_addf(&datebuf, \"@%s\", date);\n>> -               res = setenv(\"GIT_COMMITTER_DATE\",\n>> -                            opts->ignore_date ? \"\" : datebuf.buf, 1);\n>> -\n>> -               strbuf_release(&datebuf);\n>> -               free(date);\n>> -\n>> -               if (res)\n>> -                       return -1;\n>> -       }\n>> -\n>>         if (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {\n>>                 const char *gpg_opt = gpg_sign_opt_quoted(opts);\n>>\n>>                 return error(_(staged_changes_advice),\n>>                              gpg_opt, gpg_opt);\n>>         }\n>> +       if (opts->committer_date_is_author_date)\n>> +               argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>> +                                opts->ignore_date ?\n>> +                                \"\" :\n>> +                                author_date_from_env_array(&cmd.env_array));\n>> +       if (opts->ignore_date)\n>> +               argv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>>\n>>         argv_array_push(&cmd.args, \"commit\");\n>>\n>> @@ -1014,8 +995,6 @@ static int run_git_commit(struct repository *r,\n>>                 argv_array_push(&cmd.args, \"--amend\");\n>>         if (opts->gpg_sign)\n>>                 argv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n>> -       if (opts->ignore_date)\n>> -               push_dates(&cmd, opts->committer_date_is_author_date);\n>>         if (defmsg)\n>>                 argv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>>         else if (!(flags & EDIT_MSG))\n>> @@ -3615,6 +3594,13 @@ static int do_merge(struct repository *r,\n>>                         ret = error(_(staged_changes_advice), gpg_opt, gpg_opt);\n>>                         goto leave_merge;\n>>                 }\n>> +               if (opts->committer_date_is_author_date)\n>> +                       argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>> +                                        opts->ignore_date ?\n>> +                                        \"\" :\n>> +                                        author_date_from_env_array(&cmd.env_array));\n>> +               if (opts->ignore_date)\n>> +                       argv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>>\n>>                 cmd.git_cmd = 1;\n>>                 argv_array_push(&cmd.args, \"merge\");\n>> @@ -3635,8 +3621,6 @@ static int do_merge(struct repository *r,\n>>                 argv_array_push(&cmd.args, git_path_merge_msg(r));\n>>                 if (opts->gpg_sign)\n>>                         argv_array_push(&cmd.args, opts->gpg_sign);\n>> -               if (opts->ignore_date)\n>> -                       push_dates(&cmd, opts->committer_date_is_author_date);\n>>\n>>                 /* Add the tips to be merged */\n>>                 for (j = to_merge; j; j = j->next)\n>> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n>> index 132f577fc9..8247d01442 100755\n>> --- a/t/t3433-rebase-options-compatibility.sh\n>> +++ b/t/t3433-rebase-options-compatibility.sh\n>> @@ -71,15 +71,15 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n>>  '\n>>\n>>  test_expect_success '--committer-date-is-author-date works with am backend' '\n>> -       git commit --amend &&\n>> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>>         git rebase --committer-date-is-author-date HEAD^ &&\n>>         git log -1 --pretty=\"format:%ai\" >authortime &&\n>>         git log -1 --pretty=\"format:%ci\" >committertime &&\n>>         test_cmp authortime committertime\n>>  '\n>>\n>>  test_expect_success '--committer-date-is-author-date works with interactive backend' '\n>> -       git commit --amend &&\n>> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>>         git rebase -i --committer-date-is-author-date HEAD^ &&\n>>         git log -1 --pretty=\"format:%ai\" >authortime &&\n>>         git log -1 --pretty=\"format:%ci\" >committertime &&\n>> @@ -88,13 +88,36 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n>>\n>>  test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>>         git checkout side &&\n>> -       git merge --no-ff commit3 &&\n>> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>>         git rebase -r --root --committer-date-is-author-date &&\n>>         git log --pretty=\"format:%ai\" >authortime &&\n>>         git log --pretty=\"format:%ci\" >committertime &&\n>>         test_cmp authortime committertime\n>>  '\n>>\n>> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n>> +       git checkout side &&\n>> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>> +       git rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n>> +       git log --pretty=\"format:%ai\" >authortime &&\n>> +       git log --pretty=\"format:%ci\" >committertime &&\n>> +       test_cmp authortime committertime\n>> +\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n>> +       git checkout commit2 &&\n>> +       GIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n>> +       git log -1 --format=%at HEAD >expect &&\n>> +       test_must_fail git rebase -i --committer-date-is-author-date \\\n>> +               --onto HEAD^^ HEAD^ &&\n>> +       echo resolved > foo &&\n>> +       git add foo &&\n>> +       git rebase --continue &&\n>> +       git log -1 --format=%ct HEAD >actual &&\n>> +       test_cmp expect actual\n>> +'\n>> +\n>>  # Checking for +0000 in author time is enough since default\n>>  # timezone is UTC, but the timezone used while committing\n>>  # sets to +0530.\n>> --\n>> 2.26.0\n>>\n\n"},{"id":"394987","messageId":"1094f0a2-91b8-4106-1db6-7bb49dadd267@gmail.com","threadId":"53176","inReplyTo":"CABPp-BFZknddcEcAz02T7Uej0jNWtKAUW8hwS6CdMfAa5BhGgA@mail.gmail.com","subject":"Re: [PATCH 6/6] t3433: improve coverage","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T18:16:17Z","receivedAt":"2020-04-07T18:16:22Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Elijah\n\nOn 07/04/2020 16:13, Elijah Newren wrote:\n> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> Add tests to check --ignore-whitespace and --ignore-date are remembered\n>> when running `rebase --continue` and to check\n>> --committer-date-is-author-date with --ignore-date gives the expected\n>> result.\n> \n> Thanks for adding these.\n> \n>>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> ---\n>>  t/t3433-rebase-options-compatibility.sh | 55 +++++++++++++++++++++++++\n> \n> t3433 is taken by t3433-rebase-across-mode-change.sh in upstream.\n> When you revert the reversion of Rohit's changes, perhaps you need to\n> rename his t3433 to some other file?\n\nThanks for point that out I'll rename it\n\n> Also, the name \"rebase-options-compatibility\" suggest to me that it's\n> just checking whether certain options can be used together.  Perhaps\n> the --ignore-whitespace and --ignore-date tests you add should go\n> somewhere else?\n\nI think this file is so named because it tests that the merge backend is\ncompatible with the apply backend for the new options (i.e. they both\ngive the same results) - I'll try and think of a better name\n\n>>  1 file changed, 55 insertions(+)\n>>\n>> diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n>> index 8247d01442..a13c341301 100755\n>> --- a/t/t3433-rebase-options-compatibility.sh\n>> +++ b/t/t3433-rebase-options-compatibility.sh\n>> @@ -7,6 +7,8 @@ test_description='tests to ensure compatibility between am and interactive backe\n>>\n>>  . ./test-lib.sh\n>>\n>> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n>> +\n>>  GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n>>  export GIT_AUTHOR_DATE\n>>\n>> @@ -70,6 +72,22 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n>>         test_cmp expect file\n>>  '\n>>\n>> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n>> +       cat >expect <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       (\n>> +               set_fake_editor &&\n>> +               FAKE_LINES=\"break 1\" &&\n>> +               export FAKE_LINES &&\n>> +               git rebase -i --ignore-whitespace main side\n>> +       ) &&\n>> +       git rebase --continue &&\n>> +       test_cmp expect file\n>> +'\n>> +\n>>  test_expect_success '--committer-date-is-author-date works with am backend' '\n>>         GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>>         git rebase --committer-date-is-author-date HEAD^ &&\n>> @@ -135,6 +153,16 @@ test_expect_success '--ignore-date works with interactive backend' '\n>>         grep \"+0000\" authortime\n>>  '\n>>\n>> +test_expect_success '--ignore-date works after conflict resolution' '\n>> +       test_must_fail git rebase --ignore-date -i \\\n>> +               --onto commit2^^ commit2^ commit2 &&\n> \n> I don't see any todo list here; is there a reason you are using -i\n> instead of say -m?  (Similar question applies for the subsequent tests\n> you add below too?)\n\nHabit. (also these were originally based on an older commit and I wasn't\nsure if that had your 'rebase -m' changes in it.) I'll update them to use -m\n\nBest Wishes\n\nPhillip\n\n>> +       echo resolved >foo &&\n>> +       git add foo &&\n>> +       git rebase --continue &&\n>> +       git log --pretty=%ai >authortime &&\n>> +       grep +0000 authortime\n>> +'\n>> +\n>>  test_expect_success '--ignore-date works with rebase -r' '\n>>         git checkout side &&\n>>         git merge --no-ff commit3 &&\n>> @@ -143,4 +171,31 @@ test_expect_success '--ignore-date works with rebase -r' '\n>>         ! grep -v \"+0000\" authortime\n>>  '\n>>\n>> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n>> +       test_must_fail git rebase -i --committer-date-is-author-date \\\n>> +               --ignore-date --onto commit2^^ commit2^ commit3 &&\n>> +       git checkout --theirs foo &&\n>> +       git add foo &&\n>> +       git rebase --continue &&\n>> +       git log -2 --pretty=%ai >authortime &&\n>> +       git log -2 --pretty=%ci >committertime &&\n>> +       test_cmp authortime committertime &&\n>> +       ! grep -v \"+0000\" authortime\n>> +'\n>> +\n>> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n>> +       GIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n>> +               git rebase -i --strategy=resolve --ignore-date \\\n>> +               --committer-date-is-author-date side side &&\n>> +       git log -1 --pretty=%ai >authortime &&\n>> +       git log -1 --pretty=%ci >committertime &&\n>> +       test_cmp authortime committertime &&\n>> +       grep \"+0000\" authortime\n>> + '\n>> +\n>> +# This must be the last test in this file\n>> +test_expect_success '$EDITOR and friends are unchanged' '\n>> +       test_editor_unchanged\n>> +'\n>> +\n>>  test_done\n>> --\n>> 2.26.0\n>>\n\n"},{"id":"394989","messageId":"0ad67315-21e6-48a6-0903-626c9a0e4b04@gmail.com","threadId":"53176","inReplyTo":"CABPp-BF5Z8zJLZ3e4G8bDUJjheP4D4-aLoLcpqWuJC+OqLTpDg@mail.gmail.com","subject":"Re: [PATCH 0/6] fixup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-07T18:18:17Z","receivedAt":"2020-04-07T18:18:25Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 07/04/2020 16:17, Elijah Newren wrote:\n> Hi Phillip,\n> \n> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> The tests for ra/rebase-i-more-options were not as comprehensive as\n>> they could have been and some of the tests that we did have didn't do\n>> a good job of testing what they purported to. This series cleans up\n>> the tests and fixes a couple of bugs (thanks to Jonathan Nieder for\n>> reporting one of them). The bug fix reworks the code to try and make\n>> it clearer.\n>>\n>> I've opted to add some cleanup commits on top of Rohit's work rather\n>> than reworking his patches. These are based on top of 4d924528d8\n>> (\"Revert \"Merge branch 'ra/rebase-i-more-options'\"\", 2020-01-12) there\n>> are some conflicts when merging into pu. I had a quick look at the\n>> conflicts and they appeared to be relatively straight forward to\n>> resolve. If that impression is wrong let me know and I can rebase onto\n>> master or try doing the merge myself and pushing it to github.\n>>\n>> Phillip Wood (6):\n>>   Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"\n>>   t3433: remove loops from tests\n>>   t3433: only compare commit dates\n>>   rebase -i: fix --committer-date-is-author-date\n>>   Revert \"sequencer: allow callers of read_author_script() to ignore\n>>     fields\"\n>>   t3433: improve coverage\n>>\n>>  Documentation/git-rebase.txt            |  27 +++-\n>>  builtin/rebase.c                        |  49 ++++--\n>>  sequencer.c                             | 109 ++++++++++++-\n>>  sequencer.h                             |   2 +\n>>  t/t3422-rebase-incompatible-options.sh  |   2 -\n>>  t/t3433-rebase-options-compatibility.sh | 201 ++++++++++++++++++++++++\n>>  7 files changed, 368 insertions(+), 25 deletions(-)\n>>  create mode 100755 t/t3433-rebase-options-compatibility.sh\n>>\n>> --\n>> 2.26.0\n> \n> Thanks for working on this!  I took a look over the series and noted a\n> few minor issues and questions, but it mostly looked good to me.\n\nThanks for looking at them and for your suggestions. I think I've got\nreasonable test coverage now - lets see if Stolee's coverage script agrees\n\nBest Wishes\n\nPhillip\n\n\n> Elijah\n> \n\n"},{"id":"395008","messageId":"xmqqv9mbroqw.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"CABPp-BEnmpET=6rEdDXJWnPjzV33a2x6rKB6FQ-o8y+8ssK4jw@mail.gmail.com","subject":"Re: [PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-07T21:04:55Z","receivedAt":"2020-04-07T21:05:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Elijah Newren <newren@gmail.com> writes:\n\n> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.\n>>\n>> This is being reverted to enable some fixups for\n>> ra/rebase-i-more-options to be built on this commit.\n>\n> This makes sense to me, but it will be only the second 'Revert\n> \"Revert...\"' commit in all of git.git and I'm curious if Junio will be\n> unhappy with it.\n\nNah, there isn't much to become unhappy about.  \n\nI however suspect that the alternative would certainly be much nicer\nand easier to understand, which is to rebuild the 7-patch series\nc58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this\npatch to take us back to a known buggy state and then fix the result\nwith 5 more patches.  Is that what you meant?\n"},{"id":"395009","messageId":"xmqqlfn7rnj2.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"xmqqv9mbroqw.fsf@gitster.c.googlers.com","subject":"Re: [PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-07T21:31:13Z","receivedAt":"2020-04-07T21:31:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Elijah Newren <newren@gmail.com> writes:\n>\n>> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>>\n>>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>>\n>>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.\n>>>\n>>> This is being reverted to enable some fixups for\n>>> ra/rebase-i-more-options to be built on this commit.\n>>\n>> This makes sense to me, but it will be only the second 'Revert\n>> \"Revert...\"' commit in all of git.git and I'm curious if Junio will be\n>> unhappy with it.\n>\n> Nah, there isn't much to become unhappy about.  \n>\n> I however suspect that the alternative would certainly be much nicer\n> and easier to understand, which is to rebuild the 7-patch series\n> c58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this\n> patch to take us back to a known buggy state and then fix the result\n> with 5 more patches.  Is that what you meant?\n\nAfter looking at the conflict resolution while merging the result of\napplying these patches on top of the older codebase, I would have to\nsay that the approach \"\"\"I've opted to add some cleanup commits on\ntop of Rohit's work rather than reworking his patches.\"\"\" may not\nhave been particularly a brilliant idea, not because the conflicts\narising from an older codebase are unpleasant to resolve (they seem\nto be reasonably contained), but because it resurrects other\nunwanted cruft we have cleaned up since then, and worse yet, it does\nso without triggering conflicts.  For example, we'll end up seeing\nmentions of \"'am' backend\", which have all been updated to \"'apply'\nbackend\", in the documentation, and patches [2-6/6] do not fix them.\n\n[5/6] is an example of one more \"unwanted\" thing the reversion\nresurrects that needed to be fixed, I guess?\n\nThe result of applying all these patches and merging it to 'master'\nand/or 'pu' may be more or less right, as far as the new features\nadded to the \"rebase -i\" by the series are concerned but there may\nbe many small \"unwanted cruft\" we may be resurrecting with [1/6],\nso...\n\n\n\n"},{"id":"395024","messageId":"xmqq1roysxsh.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"Re: [PATCH 0/6] fixup ra/rebase-i-more-options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-07T23:04:14Z","receivedAt":"2020-04-07T23:04:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> The tests for ra/rebase-i-more-options were not as comprehensive as\n> they could have been and some of the tests that we did have didn't do\n> a good job of testing what they purported to. This series cleans up\n> the tests and fixes a couple of bugs (thanks to Jonathan Nieder for\n> reporting one of them). The bug fix reworks the code to try and make\n> it clearer.\n\nAs t3433 is already taken, I've queued a SQUASH??? commit at the tip\nof the topic to move it to t3436 while queuing (which is another\nfallout that needs fixing while we resurrect an outdated series).\n\nThanks.\n"},{"id":"395303","messageId":"nycvar.QRO.7.76.6.2004121944590.46@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"xmqqlfn7rnj2.fsf@gitster.c.googlers.com","subject":"Re: [PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-04-12T17:47:35Z","receivedAt":"2020-04-12T17:56:16Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip, Elijah & Junio,\n\nOn Tue, 7 Apr 2020, Junio C Hamano wrote:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> > Elijah Newren <newren@gmail.com> writes:\n> >\n> >> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n> >>>\n> >>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> >>>\n> >>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.\n> >>>\n> >>> This is being reverted to enable some fixups for\n> >>> ra/rebase-i-more-options to be built on this commit.\n> >>\n> >> This makes sense to me, but it will be only the second 'Revert\n> >> \"Revert...\"' commit in all of git.git and I'm curious if Junio will be\n> >> unhappy with it.\n> >\n> > Nah, there isn't much to become unhappy about.\n> >\n> > I however suspect that the alternative would certainly be much nicer\n> > and easier to understand, which is to rebuild the 7-patch series\n> > c58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this\n> > patch to take us back to a known buggy state and then fix the result\n> > with 5 more patches.  Is that what you meant?\n>\n> After looking at the conflict resolution while merging the result of\n> applying these patches on top of the older codebase, I would have to\n> say that the approach \"\"\"I've opted to add some cleanup commits on\n> top of Rohit's work rather than reworking his patches.\"\"\" may not\n> have been particularly a brilliant idea, not because the conflicts\n> arising from an older codebase are unpleasant to resolve (they seem\n> to be reasonably contained), but because it resurrects other\n> unwanted cruft we have cleaned up since then, and worse yet, it does\n> so without triggering conflicts.  For example, we'll end up seeing\n> mentions of \"'am' backend\", which have all been updated to \"'apply'\n> backend\", in the documentation, and patches [2-6/6] do not fix them.\n>\n> [5/6] is an example of one more \"unwanted\" thing the reversion\n> resurrects that needed to be fixed, I guess?\n>\n> The result of applying all these patches and merging it to 'master'\n> and/or 'pu' may be more or less right, as far as the new features\n> added to the \"rebase -i\" by the series are concerned but there may\n> be many small \"unwanted cruft\" we may be resurrecting with [1/6],\n> so...\n\nI agree that it would make for a much nicer read if the entire patch\nseries was simply rebased on top of v2.26.0, with drops instead of\nreverts. I suspect that 4/6 will not even become a fixup, but that the\nresulting patch is really more of an `Initial-patch-by: Rohit` material\nwith Phillip as the author on record.\n\nAs to the changes, I had a brief look over them, and I have nothing to add\nto Elijah's review except to stress how excited I am about the increased\ntest coverage. From my perspective, this makes the patch series 10x\nbetter.\n\nThanks,\nDscho\n"},{"id":"395321","messageId":"43d06bc0-b2ee-0ae6-f22c-9850e4033d45@gmail.com","threadId":"53176","inReplyTo":"nycvar.QRO.7.76.6.2004121944590.46@tvgsbejvaqbjf.bet","subject":"Re: [PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-13T09:58:34Z","receivedAt":"2020-04-13T10:06:21Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi All\n\nOn 12/04/2020 18:47, Johannes Schindelin wrote:\n> Hi Phillip, Elijah & Junio,\n> \n> On Tue, 7 Apr 2020, Junio C Hamano wrote:\n> \n>> Junio C Hamano <gitster@pobox.com> writes:\n>>\n>>> Elijah Newren <newren@gmail.com> writes:\n>>>\n>>>> On Tue, Apr 7, 2020 at 7:11 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>>>>\n>>>>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>>>>\n>>>>> This reverts commit 4d924528d8bfe947abfc54ee9bd3892ab509c8cd.\n>>>>>\n>>>>> This is being reverted to enable some fixups for\n>>>>> ra/rebase-i-more-options to be built on this commit.\n>>>>\n>>>> This makes sense to me, but it will be only the second 'Revert\n>>>> \"Revert...\"' commit in all of git.git and I'm curious if Junio will be\n>>>> unhappy with it.\n>>>\n>>> Nah, there isn't much to become unhappy about.\n>>>\n>>> I however suspect that the alternative would certainly be much nicer\n>>> and easier to understand, which is to rebuild the 7-patch series\n>>> c58ae96fc4..d82dfa7f5b but bugs already fixed, instead of doing this\n>>> patch to take us back to a known buggy state and then fix the result\n>>> with 5 more patches.  Is that what you meant?\n>>\n>> After looking at the conflict resolution while merging the result of\n>> applying these patches on top of the older codebase, I would have to\n>> say that the approach \"\"\"I've opted to add some cleanup commits on\n>> top of Rohit's work rather than reworking his patches.\"\"\" may not\n>> have been particularly a brilliant idea, not because the conflicts\n>> arising from an older codebase are unpleasant to resolve (they seem\n>> to be reasonably contained), but because it resurrects other\n>> unwanted cruft we have cleaned up since then, and worse yet, it does\n>> so without triggering conflicts.  For example, we'll end up seeing\n>> mentions of \"'am' backend\", which have all been updated to \"'apply'\n>> backend\", in the documentation, and patches [2-6/6] do not fix them.\n>>\n>> [5/6] is an example of one more \"unwanted\" thing the reversion\n>> resurrects that needed to be fixed, I guess?\n>>\n>> The result of applying all these patches and merging it to 'master'\n>> and/or 'pu' may be more or less right, as far as the new features\n>> added to the \"rebase -i\" by the series are concerned but there may\n>> be many small \"unwanted cruft\" we may be resurrecting with [1/6],\n>> so...\n> \n> I agree that it would make for a much nicer read if the entire patch\n> series was simply rebased on top of v2.26.0, with drops instead of\n> reverts. I suspect that 4/6 will not even become a fixup, but that the\n> resulting patch is really more of an `Initial-patch-by: Rohit` material\n> with Phillip as the author on record.\n> \n> As to the changes, I had a brief look over them, and I have nothing to add\n> to Elijah's review except to stress how excited I am about the increased\n> test coverage. From my perspective, this makes the patch series 10x\n> better.\n\nThanks for all your feedback, I'll reroll as a new patch series based on\nmaster\n\nBest Wishes\n\nPhillip\n\n> Thanks,\n> Dscho\n> \n\n"},{"id":"395375","messageId":"xmqqy2qzavnu.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"43d06bc0-b2ee-0ae6-f22c-9850e4033d45@gmail.com","subject":"Re: [PATCH 1/6] Revert \"Revert \"Merge branch 'ra/rebase-i-more-options'\"\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-13T22:05:41Z","receivedAt":"2020-04-13T22:05:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>> I agree that it would make for a much nicer read if the entire patch\n>> series was simply rebased on top of v2.26.0, with drops instead of\n>> reverts. I suspect that 4/6 will not even become a fixup, but that the\n>> resulting patch is really more of an `Initial-patch-by: Rohit` material\n>> with Phillip as the author on record.\n>> \n>> As to the changes, I had a brief look over them, and I have nothing to add\n>> to Elijah's review except to stress how excited I am about the increased\n>> test coverage. From my perspective, this makes the patch series 10x\n>> better.\n>\n> Thanks for all your feedback, I'll reroll as a new patch series based on\n> master\n\nThanks, all.\n"},{"id":"396537","messageId":"20200429102521.47995-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-1-phillip.wood123@gmail.com","subject":"[PATCH v2 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-29T10:25:17Z","receivedAt":"2020-04-29T10:26:49Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nRebase is implemented with two different backends - 'apply' and 'merge'\neach of which support a different set of options. In particuar the apply\nbackend supports a number of options implemented by 'git am' that are\nnot available to the merge backend. As part of an on going effort to\nremove the apply backend this patch adds support for the\n--ignore-whitespace option to the merge backend. This option treats\nlines with only whitespace changes as unchanged and is implemented in\nthe merge backend by translating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 12 +++-\n builtin/rebase.c                       | 19 ++++--\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++\n 4 files changed, 111 insertions(+), 7 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f7a6033607..d060c143e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -422,8 +422,16 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tBehaves differently depending on which backend is selected.\n++\n+apply backend: When applying a patch, ignore changes in whitespace in\n+context lines.\n++\n+merge backend: Treat lines with only whitespace changes as unchanged\n+when merging.\n+\n --whitespace=<option>::\n-\tThese flags are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n \tImplies --apply.\n +\n@@ -572,7 +580,6 @@ The following options:\n  * --apply\n  * --committer-date-is-author-date\n  * --ignore-date\n- * --ignore-whitespace\n  * --whitespace\n  * -C\n \n@@ -598,6 +605,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n+ * --preserve-merges and --ignore-whitespace\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 27a07d4e78..5d8e117276 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -86,6 +86,7 @@ struct rebase_options {\n \tint signoff;\n \tint allow_rerere_autoupdate;\n \tint autosquash;\n+\tint ignore_whitespace;\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tchar *cmd;\n@@ -108,6 +109,7 @@ struct rebase_options {\n \n static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n {\n+\tstruct strbuf strategy_buf = STRBUF_INIT;\n \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n \n \treplay.action = REPLAY_INTERACTIVE_REBASE;\n@@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n-\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n+\t\tstrbuf_addstr(&strategy_buf, opts->strategy_opts);\n+\tif (opts->ignore_whitespace)\n+\t\tstrbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n+\tif (strategy_buf.len)\n+\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n \n \tif (opts->squash_onto) {\n \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n \t\treplay.have_squash_onto = 1;\n \t}\n \n+\tstrbuf_release(&strategy_buf);\n \treturn replay;\n }\n \n@@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n \n+\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n+\n \tif (!is_null_oid(&squash_onto))\n \t\topts.squash_onto = &squash_onto;\n \n@@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)\n \tam.git_cmd = 1;\n \targv_array_push(&am.args, \"am\");\n \n+\tif (opts->ignore_whitespace)\n+\t\targv_array_push(&am.args, \"--ignore-whitespace\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..55ca46786d 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nnew file mode 100755\nindex 0000000000..fb5e747e86\n--- /dev/null\n+++ b/t/t3436-rebase-more-options.sh\n@@ -0,0 +1,86 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\tq_to_tab >file <<-\\EOF &&\n+\tline 1\n+\tQline 2\n+\tline 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tcat >file <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\n+\tgit checkout --orphan master &&\n+\tsed -e \"s/^|//\" >file <<-\\EOF &&\n+\t|line 1\n+\t|        line 2\n+\t|line 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with apply backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase --apply main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --apply --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--ignore-whitespace works with merge backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n+\t) &&\n+\tgit rebase --continue &&\n+\ttest_cmp expect file\n+'\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n+test_done\n-- \n2.26.2\n\n"},{"id":"396539","messageId":"20200429102521.47995-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH v2 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-29T10:25:16Z","receivedAt":"2020-04-29T10:26:50Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nI've rebased Rohit's patches on master and reworked them with my\nfixups from v1. I've renamed the test file that was causing a\nproblem (as you'll see I wasn't feeling very inspired when I came\nup with the name) and changed some tests from using rebase -i to\nrebase -m as suggested by Elijah. I've updated the last patch to\ntest both --reset-author and --ignore-author.\n\nThere's a range-diff below between ra/rebase-i-more-options and\nthese patches though I'm not sure how useful it is in practice.\n\nPhillip Wood (2):\n  rebase -i: support --committer-date-is-author-date\n  rebase -i: support --ignore-date\n\nRohit Ashiwal (3):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: rename amend_author to author_to_free\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt           |  26 ++-\n builtin/rebase.c                       |  46 ++++--\n sequencer.c                            | 111 ++++++++++++-\n sequencer.h                            |   2 +\n t/t3422-rebase-incompatible-options.sh |   2 -\n t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++\n 6 files changed, 371 insertions(+), 25 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\n1:  ba51d2fb24 ! 1:  5ef315240a rebase -i: add --ignore-whitespace flag\n    @@ Metadata\n      ## Commit message ##\n         rebase -i: add --ignore-whitespace flag\n     \n    -    There are two backends available for rebasing, viz, the am and the\n    -    interactive. Naturally, there shall be some features that are\n    -    implemented in one but not in the other. One such flag is\n    -    --ignore-whitespace which indicates merge mechanism to treat lines\n    -    with only whitespace changes as unchanged. Wire the interactive\n    -    rebase to also understand the --ignore-whitespace flag by\n    -    translating it to -Xignore-space-change.\n    +    Rebase is implemented with two different backends - 'apply' and 'merge'\n    +    each of which support a different set of options. In particuar the apply\n    +    backend supports a number of options implemented by 'git am' that are\n    +    not available to the merge backend. As part of an on going effort to\n    +    remove the apply backend this patch adds support for the\n    +    --ignore-whitespace option to the merge backend. This option treats\n    +    lines with only whitespace changes as unchanged and is implemented in\n    +    the merge backend by translating it to -Xignore-space-change.\n     \n         Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n    +    Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n     \n      ## Documentation/git-rebase.txt ##\n    -@@ Documentation/git-rebase.txt: If either <upstream> or --root is given on the command line, then the\n    - default is `--no-fork-point`, otherwise the default is `--fork-point`.\n    +@@ Documentation/git-rebase.txt: your branch contains commits which were dropped, this option can be used\n    + with `--keep-base` in order to drop those commits from your branch.\n      \n      --ignore-whitespace::\n     +\tBehaves differently depending on which backend is selected.\n     ++\n    -+'am' backend: When applying a patch, ignore changes in whitespace in\n    -+context lines if necessary.\n    ++apply backend: When applying a patch, ignore changes in whitespace in\n    ++context lines.\n     ++\n    -+'interactive' backend: Treat lines with only whitespace changes as\n    -+unchanged for the sake of a three-way merge.\n    ++merge backend: Treat lines with only whitespace changes as unchanged\n    ++when merging.\n     +\n      --whitespace=<option>::\n    --\tThese flag are passed to the 'git apply' program\n    +-\tThese flags are passed to the 'git apply' program\n     +\tThis flag is passed to the 'git apply' program\n      \t(see linkgit:git-apply[1]) that applies the patch.\n    + \tImplies --apply.\n      +\n    - See also INCOMPATIBLE OPTIONS below.\n     @@ Documentation/git-rebase.txt: The following options:\n    +  * --apply\n       * --committer-date-is-author-date\n       * --ignore-date\n    -  * --whitespace\n     - * --ignore-whitespace\n    +  * --whitespace\n       * -C\n      \n    - are incompatible with the following options:\n     @@ Documentation/git-rebase.txt: In addition, the following pairs of options are incompatible:\n    -  * --preserve-merges and --interactive\n       * --preserve-merges and --signoff\n       * --preserve-merges and --rebase-merges\n    +  * --preserve-merges and --empty=\n     + * --preserve-merges and --ignore-whitespace\n    -  * --rebase-merges and --strategy\n    -  * --rebase-merges and --strategy-option\n    +  * --keep-base and --onto\n    +  * --keep-base and --root\n      \n     \n      ## builtin/rebase.c ##\n     @@ builtin/rebase.c: struct rebase_options {\n    + \tint signoff;\n      \tint allow_rerere_autoupdate;\n    - \tint keep_empty;\n      \tint autosquash;\n     +\tint ignore_whitespace;\n      \tchar *gpg_sign_opt;\n    @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_\n     +\tif (strategy_buf.len)\n     +\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n      \n    + \tif (opts->squash_onto) {\n    + \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n    + \t\treplay.have_squash_onto = 1;\n    + \t}\n    + \n     +\tstrbuf_release(&strategy_buf);\n      \treturn replay;\n      }\n      \n     @@ builtin/rebase.c: int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n    - \targc = parse_options(argc, argv, NULL, options,\n    + \targc = parse_options(argc, argv, prefix, options,\n      \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n      \n     +\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n    @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {\n      test_rebase_am_only -C4\n      \n     \n    - ## t/t3433-rebase-options-compatibility.sh (new) ##\n    + ## t/t3436-rebase-more-options.sh (new) ##\n     @@\n     +#!/bin/sh\n     +#\n    @@ t/t3433-rebase-options-compatibility.sh (new)\n     +\n     +. ./test-lib.sh\n     +\n    ++. \"$TEST_DIRECTORY\"/lib-rebase.sh\n    ++\n     +# This is a special case in which both am and interactive backends\n     +# provide the same output. It was done intentionally because\n     +# both the backends fall short of optimal behaviour.\n    @@ t/t3433-rebase-options-compatibility.sh (new)\n     +\tgit tag main\n     +'\n     +\n    -+test_expect_success '--ignore-whitespace works with am backend' '\n    ++test_expect_success '--ignore-whitespace works with apply backend' '\n     +\tcat >expect <<-\\EOF &&\n     +\tline 1\n     +\tnew line 2\n     +\tline 3\n     +\tEOF\n    -+\ttest_must_fail git rebase main side &&\n    ++\ttest_must_fail git rebase --apply main side &&\n     +\tgit rebase --abort &&\n    -+\tgit rebase --ignore-whitespace main side &&\n    ++\tgit rebase --apply --ignore-whitespace main side &&\n     +\ttest_cmp expect file\n     +'\n     +\n    -+test_expect_success '--ignore-whitespace works with interactive backend' '\n    ++test_expect_success '--ignore-whitespace works with merge backend' '\n     +\tcat >expect <<-\\EOF &&\n     +\tline 1\n     +\tnew line 2\n    @@ t/t3433-rebase-options-compatibility.sh (new)\n     +\ttest_cmp expect file\n     +'\n     +\n    ++test_expect_success '--ignore-whitespace is remembered when continuing' '\n    ++\tcat >expect <<-\\EOF &&\n    ++\tline 1\n    ++\tnew line 2\n    ++\tline 3\n    ++\tEOF\n    ++\t(\n    ++\t\tset_fake_editor &&\n    ++\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n    ++\t) &&\n    ++\tgit rebase --continue &&\n    ++\ttest_cmp expect file\n    ++'\n    ++\n    ++# This must be the last test in this file\n    ++test_expect_success '$EDITOR and friends are unchanged' '\n    ++\ttest_editor_unchanged\n    ++'\n    ++\n     +test_done\n2:  c068bcc59b < -:  ---------- sequencer: allow callers of read_author_script() to ignore fields\n3:  cbd8db17ac ! 2:  55eb3a7efc rebase -i: support --committer-date-is-author-date\n    @@\n      ## Metadata ##\n    -Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    +Author: Phillip Wood <phillip.wood@dunelm.org.uk>\n     \n      ## Commit message ##\n         rebase -i: support --committer-date-is-author-date\n     \n    -    rebase am already has this flag to \"lie\" about the committer date\n    -    by changing it to the author date. Let's add the same for\n    -    interactive machinery.\n    +    As part of the on-going effort to retire the apply rebase backend teach\n    +    the merge backend how to handle --committer-date-is-author-date.\n     \n    -    Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n    +    Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    +    Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n     \n      ## Documentation/git-rebase.txt ##\n    -@@ Documentation/git-rebase.txt: unchanged for the sake of a three-way merge.\n    +@@ Documentation/git-rebase.txt: when merging.\n      See also INCOMPATIBLE OPTIONS below.\n      \n      --committer-date-is-author-date::\n    -+\tInstead of recording the time the rebased commits are\n    -+\tcreated as the committer date, reuse the author date\n    -+\tas the committer date. This implies --force-rebase.\n    ++\tInstead of using the current time as the committer date, use\n    ++\tthe author date of the commit being rebased as the committer\n    ++\tdate. This option implies --force-rebase.\n     +\n      --ignore-date::\n     -\tThese flags are passed to 'git am' to easily change the dates\n    @@ Documentation/git-rebase.txt: unchanged for the sake of a three-way merge.\n      See also INCOMPATIBLE OPTIONS below.\n      \n     @@ Documentation/git-rebase.txt: INCOMPATIBLE OPTIONS\n    - \n      The following options:\n      \n    +  * --apply\n     - * --committer-date-is-author-date\n       * --ignore-date\n       * --whitespace\n       * -C\n     @@ Documentation/git-rebase.txt: In addition, the following pairs of options are incompatible:\n    -  * --preserve-merges and --signoff\n       * --preserve-merges and --rebase-merges\n    +  * --preserve-merges and --empty=\n       * --preserve-merges and --ignore-whitespace\n     + * --preserve-merges and --committer-date-is-author-date\n    -  * --rebase-merges and --strategy\n    -  * --rebase-merges and --strategy-option\n    +  * --keep-base and --onto\n    +  * --keep-base and --root\n      \n     \n      ## builtin/rebase.c ##\n    @@ builtin/rebase.c: struct rebase_options {\n      \tint allow_empty_message;\n      \tint rebase_merges, rebase_cousins;\n     @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n    - \treplay.allow_empty_message = opts->allow_empty_message;\n    + \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n      \treplay.verbose = opts->flags & REBASE_VERBOSE;\n      \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n     +\treplay.committer_date_is_author_date =\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n      \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n    - \t\t    state_dir_base, cmd_live_rebase, buf.buf);\n    + \t    options.autosquash) {\n    + \t\tallow_preemptive_ff = 0;\n      \t}\n    - \n     +\tif (options.committer_date_is_author_date)\n     +\t\toptions.flags |= REBASE_FORCE;\n    -+\n    + \n      \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n      \t\tconst char *option = options.git_am_opts.argv[i], *p;\n     -\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n     -\t\t    !strcmp(option, \"--ignore-date\") ||\n     +\t\tif (!strcmp(option, \"--ignore-date\") ||\n      \t\t    !strcmp(option, \"--whitespace=fix\") ||\n      \t\t    !strcmp(option, \"--whitespace=strip\"))\n    - \t\t\toptions.flags |= REBASE_FORCE;\n    + \t\t\tallow_preemptive_ff = 0;\n     \n      ## sequencer.c ##\n     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n    @@ sequencer.c: static char *get_author(const char *message)\n      \treturn NULL;\n      }\n      \n    -+/* Returns a \"date\" string that needs to be free()'d by the caller */\n    -+static char *read_author_date_or_null(void)\n    ++static const char *author_date_from_env_array(const struct argv_array *env)\n     +{\n    -+\tchar *date;\n    ++\tint i;\n    ++\tconst char *date;\n     +\n    -+\tif (read_author_script(rebase_path_author_script(),\n    -+\t\t\t       NULL, NULL, &date, 0))\n    -+\t\treturn NULL;\n    -+\treturn date;\n    ++\tfor (i = 0; i < env->argc; i++)\n    ++\t\tif (skip_prefix(env->argv[i],\n    ++\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n    ++\t\t\treturn date;\n    ++\t/*\n    ++\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n    ++\t * reading the script\n    ++\t */\n    ++\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n     +}\n     +\n      static const char staged_changes_advice[] =\n      N_(\"you have staged changes in your working tree\\n\"\n      \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n     @@ sequencer.c: static int run_git_commit(struct repository *r,\n    + \t\t\t     gpg_opt, gpg_opt);\n    + \t}\n      \n    - \tcmd.git_cmd = 1;\n    - \n    -+\tif (opts->committer_date_is_author_date) {\n    -+\t\tint res = -1;\n    -+\t\tstruct strbuf datebuf = STRBUF_INIT;\n    -+\t\tchar *date = read_author_date_or_null();\n    -+\n    -+\t\tif (!date)\n    -+\t\t\treturn -1;\n    -+\n    -+\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n    -+\t\tres = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf, 1);\n    -+\n    -+\t\tstrbuf_release(&datebuf);\n    -+\t\tfree(date);\n    -+\n    -+\t\tif (res)\n    -+\t\t\treturn -1;\n    -+\t}\n    ++\tif (opts->committer_date_is_author_date)\n    ++\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n    ++\t\t\t\t author_date_from_env_array(&cmd.env_array));\n     +\n    - \tif (is_rebase_i(opts) && read_env_script(&cmd.env_array)) {\n    - \t\tconst char *gpg_opt = gpg_sign_opt_quoted(opts);\n    + \targv_array_push(&cmd.args, \"commit\");\n      \n    + \tif (!(flags & VERIFY_MSG))\n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n      \n      \tif (parse_head(r, &current_head))\n      \t\treturn -1;\n     -\n      \tif (flags & AMEND_MSG) {\n    - \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n    + \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n      \t\tconst char *out_enc = get_commit_output_encoding();\n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n      \t\tcommit_list_insert(current_head, &parents);\n    @@ sequencer.c: static int try_to_commit(struct repository *r,\n     +\t\tstruct strbuf date = STRBUF_INIT;\n     +\n     +\t\tif (split_ident_line(&ident, author, len) < 0) {\n    -+\t\t\tres = error(_(\"malformed ident line\"));\n    ++\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n     +\t\t\tgoto out;\n     +\t\t}\n     +\t\tif (!ident.date_begin) {\n    @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)\n      \t\t\topts->reschedule_failed_exec = 1;\n      \n     @@ sequencer.c: int write_basic_state(struct replay_opts *opts, const char *head_name,\n    - \t\twrite_file(rebase_path_gpg_sign_opt(), \"-S%s\\n\", opts->gpg_sign);\n    - \tif (opts->signoff)\n    - \t\twrite_file(rebase_path_signoff(), \"--signoff\\n\");\n    + \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n    + \tif (opts->keep_redundant_commits)\n    + \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n     +\tif (opts->committer_date_is_author_date)\n     +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n      \tif (opts->reschedule_failed_exec)\n      \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n      \n    +@@ sequencer.c: static int do_merge(struct repository *r,\n    + \t\t\tgoto leave_merge;\n    + \t\t}\n    + \n    ++\t\tif (opts->committer_date_is_author_date)\n    ++\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n    ++\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n    ++\n    + \t\tcmd.git_cmd = 1;\n    + \t\targv_array_push(&cmd.args, \"merge\");\n    + \t\targv_array_push(&cmd.args, \"-s\");\n     @@ sequencer.c: static int pick_commits(struct repository *r,\n      \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n      \tif (opts->allow_ff)\n    @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {\n      \n      test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n     \n    - ## t/t3433-rebase-options-compatibility.sh ##\n    -@@ t/t3433-rebase-options-compatibility.sh: test_description='tests to ensure compatibility between am and interactive backe\n    + ## t/t3436-rebase-more-options.sh ##\n    +@@ t/t3436-rebase-more-options.sh: test_description='tests to ensure compatibility between am and interactive backe\n      \n    - . ./test-lib.sh\n    + . \"$TEST_DIRECTORY\"/lib-rebase.sh\n      \n     +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n     +export GIT_AUTHOR_DATE\n     +\n      # This is a special case in which both am and interactive backends\n      # provide the same output. It was done intentionally because\n      # both the backends fall short of optimal behaviour.\n    -@@ t/t3433-rebase-options-compatibility.sh: test_expect_success 'setup' '\n    +@@ t/t3436-rebase-more-options.sh: test_expect_success 'setup' '\n      \tEOF\n      \tgit commit -am \"update file\" &&\n      \tgit tag side &&\n    @@ t/t3433-rebase-options-compatibility.sh: test_expect_success 'setup' '\n      \tsed -e \"s/^|//\" >file <<-\\EOF &&\n      \t|line 1\n      \t|        line 2\n    -@@ t/t3433-rebase-options-compatibility.sh: test_expect_success '--ignore-whitespace works with interactive backend' '\n    +@@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-whitespace is remembered when continuing' '\n      \ttest_cmp expect file\n      '\n      \n    -+test_expect_success '--committer-date-is-author-date works with am backend' '\n    -+\tgit commit --amend &&\n    -+\tgit rebase --committer-date-is-author-date HEAD^ &&\n    -+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n    -+\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n    ++test_expect_success '--committer-date-is-author-date works with apply backend' '\n    ++\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n    ++\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n    ++\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    ++\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n     +\ttest_cmp authortime committertime\n     +'\n     +\n    -+test_expect_success '--committer-date-is-author-date works with interactive backend' '\n    -+\tgit commit --amend &&\n    -+\tgit rebase -i --committer-date-is-author-date HEAD^ &&\n    -+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n    -+\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n    ++test_expect_success '--committer-date-is-author-date works with merge backend' '\n    ++\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n    ++\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n    ++\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    ++\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n     +\ttest_cmp authortime committertime\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n     +\tgit checkout side &&\n    -+\tgit merge --no-ff commit3 &&\n    ++\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n     +\tgit rebase -r --root --committer-date-is-author-date &&\n    -+\tgit rev-list HEAD >rev_list &&\n    -+\twhile read HASH\n    -+\tdo\n    -+\t\tgit show $HASH --pretty=\"format:%ai\" >authortime\n    -+\t\tgit show $HASH --pretty=\"format:%ci\" >committertime\n    -+\t\ttest_cmp authortime committertime\n    -+\tdone <rev_list\n    ++\tgit log --pretty=\"format:%ai\" >authortime &&\n    ++\tgit log --pretty=\"format:%ci\" >committertime &&\n    ++\ttest_cmp authortime committertime\n     +'\n     +\n    - test_done\n    ++test_expect_success '--committer-date-is-author-date works when forking merge' '\n    ++\tgit checkout side &&\n    ++\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n    ++\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n    ++\tgit log --pretty=\"format:%ai\" >authortime &&\n    ++\tgit log --pretty=\"format:%ci\" >committertime &&\n    ++\ttest_cmp authortime committertime\n    ++\n    ++'\n    ++\n    ++test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n    ++\tgit checkout commit2 &&\n    ++\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n    ++\tgit log -1 --format=%at HEAD >expect &&\n    ++\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n    ++\t\t--onto HEAD^^ HEAD^ &&\n    ++\techo resolved > foo &&\n    ++\tgit add foo &&\n    ++\tgit rebase --continue &&\n    ++\tgit log -1 --format=%ct HEAD >actual &&\n    ++\ttest_cmp expect actual\n    ++'\n    ++\n    + # This must be the last test in this file\n    + test_expect_success '$EDITOR and friends are unchanged' '\n    + \ttest_editor_unchanged\n4:  0185c683c9 ! 3:  19352fdc22 sequencer: rename amend_author to author_to_rename\n    @@ Metadata\n     Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n     \n      ## Commit message ##\n    -    sequencer: rename amend_author to author_to_rename\n    +    sequencer: rename amend_author to author_to_free\n     \n         The purpose of amend_author was to free() the malloc()'d string\n    -    obtained from get_author() while amending a commit. But we can\n    +    obtained from get_author() when amending a commit. But we can\n         also use the variable to free() the author at our convenience.\n         Rename it to convey this meaning.\n     \n         Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n     \n      ## sequencer.c ##\n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n5:  08187b4cba ! 4:  5e971abb74 rebase -i: support --ignore-date\n    @@\n      ## Metadata ##\n    -Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    +Author: Phillip Wood <phillip.wood@dunelm.org.uk>\n     \n      ## Commit message ##\n         rebase -i: support --ignore-date\n     \n    -    rebase am already has this flag to \"lie\" about the author date\n    -    by changing it to the committer (current) date. Let's add the same\n    -    for interactive machinery.\n    +    As part of the on-going effort to retire the apply rebase backend\n    +    teach the merge backend how to handle --ignore-date. We take care to\n    +    handle the combination of --ignore-date and\n    +    --committer-date-is-author-date in the same way as the apply backend.\n     \n    -    Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    -    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n    +    Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n    +    Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n     \n      ## Documentation/git-rebase.txt ##\n     @@ Documentation/git-rebase.txt: See also INCOMPATIBLE OPTIONS below.\n    - \tas the committer date. This implies --force-rebase.\n    + \tdate. This option implies --force-rebase.\n      \n      --ignore-date::\n     -\tThis flag is passed to 'git am' to change the author date\n     -\tof each rebased commit (see linkgit:git-am[1]).\n    -+\tInstead of using the given author date, reset it to the\n    -+\tcurrent time. This implies --force-rebase.\n    ++\tInstead of using the author date of the original commit, use\n    ++\tthe current time as the\tauthor date of the rebased commit.  This\n    ++\toption implies `--force-rebase`.\n      +\n      See also INCOMPATIBLE OPTIONS below.\n      \n     @@ Documentation/git-rebase.txt: INCOMPATIBLE OPTIONS\n    - \n      The following options:\n      \n    +  * --apply\n     - * --ignore-date\n       * --whitespace\n       * -C\n      \n     @@ Documentation/git-rebase.txt: In addition, the following pairs of options are incompatible:\n    -  * --preserve-merges and --rebase-merges\n    +  * --preserve-merges and --empty=\n       * --preserve-merges and --ignore-whitespace\n       * --preserve-merges and --committer-date-is-author-date\n     + * --preserve-merges and --ignore-date\n    -  * --rebase-merges and --strategy\n    -  * --rebase-merges and --strategy-option\n    +  * --keep-base and --onto\n    +  * --keep-base and --root\n      \n     \n      ## builtin/rebase.c ##\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n      \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n    - \t\t    state_dir_base, cmd_live_rebase, buf.buf);\n    + \t    options.autosquash) {\n    + \t\tallow_preemptive_ff = 0;\n      \t}\n    - \n     -\tif (options.committer_date_is_author_date)\n    -+\tif (options.committer_date_is_author_date ||\n    -+\t    options.ignore_date)\n    ++\tif (options.committer_date_is_author_date || options.ignore_date)\n      \t\toptions.flags |= REBASE_FORCE;\n      \n      \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n     -\t\t    !strcmp(option, \"--whitespace=fix\") ||\n     +\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n      \t\t    !strcmp(option, \"--whitespace=strip\"))\n    - \t\t\toptions.flags |= REBASE_FORCE;\n    + \t\t\tallow_preemptive_ff = 0;\n      \t\telse if (skip_prefix(option, \"-C\", &p)) {\n     \n      ## sequencer.c ##\n    @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs\n      static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n      static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n      static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n    -@@ sequencer.c: static char *read_author_date_or_null(void)\n    - \treturn date;\n    +@@ sequencer.c: static const char *author_date_from_env_array(const struct argv_array *env)\n    + \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n      }\n      \n     +/* Construct a free()able author string with current time as the author date */\n    @@ sequencer.c: static char *read_author_date_or_null(void)\n     +\tstruct strbuf new_author = STRBUF_INIT;\n     +\n     +\tif (split_ident_line(&ident, author, len) < 0) {\n    -+\t\terror(_(\"malformed ident line\"));\n    ++\t\terror(_(\"malformed ident line '%s'\"), author);\n     +\t\treturn NULL;\n     +\t}\n     +\tlen = ident.mail_end - ident.name_begin + 1;\n    @@ sequencer.c: static char *read_author_date_or_null(void)\n     +\tdatestamp(&new_author);\n     +\treturn strbuf_detach(&new_author, NULL);\n     +}\n    -+\n    -+static void push_dates(struct child_process *child, int change_committer_date)\n    -+{\n    -+\ttime_t now = time(NULL);\n    -+\tstruct strbuf date = STRBUF_INIT;\n    -+\n    -+\tstrbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n    -+\targv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n    -+\tif (change_committer_date)\n    -+\t\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n    -+\tstrbuf_release(&date);\n    -+}\n     +\n      static const char staged_changes_advice[] =\n      N_(\"you have staged changes in your working tree\\n\"\n      \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n     @@ sequencer.c: static int run_git_commit(struct repository *r,\n    - \t\t\treturn -1;\n      \n    - \t\tstrbuf_addf(&datebuf, \"@%s\", date);\n    --\t\tres = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf, 1);\n    -+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n    -+\t\t\t     opts->ignore_date ? \"\" : datebuf.buf, 1);\n    - \n    - \t\tstrbuf_release(&datebuf);\n    - \t\tfree(date);\n    -@@ sequencer.c: static int run_git_commit(struct repository *r,\n    - \t\targv_array_push(&cmd.args, \"--amend\");\n    - \tif (opts->gpg_sign)\n    - \t\targv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n    + \tif (opts->committer_date_is_author_date)\n    + \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n    ++\t\t\t\t opts->ignore_date ?\n    ++\t\t\t\t \"\" :\n    + \t\t\t\t author_date_from_env_array(&cmd.env_array));\n     +\tif (opts->ignore_date)\n    -+\t\tpush_dates(&cmd, opts->committer_date_is_author_date);\n    - \tif (defmsg)\n    - \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n    - \telse if (!(flags & EDIT_MSG))\n    ++\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n    + \n    + \targv_array_push(&cmd.args, \"commit\");\n    + \n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n      \t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n      \t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n    @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)\n      \t\t\topts->reschedule_failed_exec = 1;\n      \n     @@ sequencer.c: int write_basic_state(struct replay_opts *opts, const char *head_name,\n    - \t\twrite_file(rebase_path_signoff(), \"--signoff\\n\");\n    + \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n      \tif (opts->committer_date_is_author_date)\n      \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n     +\tif (opts->ignore_date)\n    @@ sequencer.c: int write_basic_state(struct replay_opts *opts, const char *head_na\n      \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n      \n     @@ sequencer.c: static int do_merge(struct repository *r,\n    - \t\targv_array_push(&cmd.args, git_path_merge_msg(r));\n    - \t\tif (opts->gpg_sign)\n    - \t\t\targv_array_push(&cmd.args, opts->gpg_sign);\n    + \n    + \t\tif (opts->committer_date_is_author_date)\n    + \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n    ++\t\t\t\t\t opts->ignore_date ?\n    ++\t\t\t\t\t \"\" :\n    + \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n     +\t\tif (opts->ignore_date)\n    -+\t\t\tpush_dates(&cmd, opts->committer_date_is_author_date);\n    ++\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n      \n    - \t\t/* Add the tips to be merged */\n    - \t\tfor (j = to_merge; j; j = j->next)\n    + \t\tcmd.git_cmd = 1;\n    + \t\targv_array_push(&cmd.args, \"merge\");\n     @@ sequencer.c: static int pick_commits(struct repository *r,\n      \tif (opts->allow_ff)\n      \t\tassert(!(opts->signoff || opts->no_commit ||\n    @@ sequencer.h: struct replay_opts {\n      \tint mainline;\n      \n     \n    - ## t/t3433-rebase-options-compatibility.sh ##\n    -@@ t/t3433-rebase-options-compatibility.sh: test_expect_success '--committer-date-is-author-date works with rebase -r' '\n    - \tdone <rev_list\n    + ## t/t3436-rebase-more-options.sh ##\n    +@@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-date works when committing confl\n    + \ttest_cmp expect actual\n      '\n      \n     +# Checking for +0000 in author time is enough since default\n     +# timezone is UTC, but the timezone used while committing\n     +# sets to +0530.\n    -+test_expect_success '--ignore-date works with am backend' '\n    ++test_expect_success '--ignore-date works with apply backend' '\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n    -+\tgit rebase --ignore-date HEAD^ &&\n    -+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n    ++\tgit rebase --apply --ignore-date HEAD^ &&\n    ++\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n     +\tgrep \"+0000\" authortime\n     +'\n     +\n    -+test_expect_success '--ignore-date works with interactive backend' '\n    ++test_expect_success '--ignore-date works with merge backend' '\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n    -+\tgit rebase --ignore-date -i HEAD^ &&\n    -+\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n    ++\tgit rebase --ignore-date -m HEAD^ &&\n    ++\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n     +\tgrep \"+0000\" authortime\n     +'\n     +\n    ++test_expect_success '--ignore-date works after conflict resolution' '\n    ++\ttest_must_fail git rebase --ignore-date -m \\\n    ++\t\t--onto commit2^^ commit2^ commit2 &&\n    ++\techo resolved >foo &&\n    ++\tgit add foo &&\n    ++\tgit rebase --continue &&\n    ++\tgit log --pretty=%ai >authortime &&\n    ++\tgrep +0000 authortime\n    ++'\n    ++\n     +test_expect_success '--ignore-date works with rebase -r' '\n     +\tgit checkout side &&\n     +\tgit merge --no-ff commit3 &&\n     +\tgit rebase -r --root --ignore-date &&\n    -+\tgit rev-list HEAD >rev_list &&\n    -+\twhile read HASH\n    -+\tdo\n    -+\t\tgit show $HASH --pretty=\"format:%ai\" >authortime\n    -+\t\tgrep \"+0000\" authortime\n    -+\tdone <rev_list\n    ++\tgit log --pretty=%ai >authortime &&\n    ++\t! grep -v \"+0000\" authortime\n     +'\n     +\n    - test_done\n    ++test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n    ++\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n    ++\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n    ++\tgit checkout --theirs foo &&\n    ++\tgit add foo &&\n    ++\tgit rebase --continue &&\n    ++\tgit log -2 --pretty=%ai >authortime &&\n    ++\tgit log -2 --pretty=%ci >committertime &&\n    ++\ttest_cmp authortime committertime &&\n    ++\t! grep -v \"+0000\" authortime\n    ++'\n    ++\n    ++test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n    ++\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n    ++\t\tgit rebase -i --strategy=resolve --ignore-date \\\n    ++\t\t--committer-date-is-author-date side side &&\n    ++\tgit log -1 --pretty=%ai >authortime &&\n    ++\tgit log -1 --pretty=%ci >committertime &&\n    ++\ttest_cmp authortime committertime &&\n    ++\tgrep \"+0000\" authortime\n    ++ '\n    ++\n    + # This must be the last test in this file\n    + test_expect_success '$EDITOR and friends are unchanged' '\n    + \ttest_editor_unchanged\n6:  fe28ad8520 < -:  ---------- rebase: add --reset-author-date\n7:  d82dfa7f5b < -:  ---------- rebase -i: finishing touches to --reset-author-date\n-:  ---------- > 5:  43a097c583 rebase: add --reset-author-date\n-- \n2.26.2\n\n"},{"id":"396538","messageId":"20200429102521.47995-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-1-phillip.wood123@gmail.com","subject":"[PATCH v2 3/5] sequencer: rename amend_author to author_to_free","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-29T10:25:19Z","receivedAt":"2020-04-29T10:26:51Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() when amending a commit. But we can\nalso use the variable to free() the author at our convenience.\nRename it to convey this meaning.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 3bb80d7414..8dff8b9b95 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n-\tchar *amend_author = NULL;\n+\tchar *author_to_free = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n@@ -1356,7 +1356,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tstrbuf_addstr(msg, orig_message);\n \t\t\thook_commit = \"HEAD\";\n \t\t}\n-\t\tauthor = amend_author = get_author(message);\n+\t\tauthor = author_to_free = get_author(message);\n \t\tunuse_commit_buffer(current_head, message);\n \t\tif (!author) {\n \t\t\tres = error(_(\"unable to parse commit author\"));\n@@ -1472,7 +1472,7 @@ static int try_to_commit(struct repository *r,\n \tfree_commit_extra_headers(extra);\n \tstrbuf_release(&err);\n \tstrbuf_release(&commit_msg);\n-\tfree(amend_author);\n+\tfree(author_to_free);\n \n \treturn res;\n }\n-- \n2.26.2\n\n"},{"id":"396540","messageId":"20200429102521.47995-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-1-phillip.wood123@gmail.com","subject":"[PATCH v2 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-29T10:25:18Z","receivedAt":"2020-04-29T10:26:52Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nAs part of the on-going effort to retire the apply rebase backend teach\nthe merge backend how to handle --committer-date-is-author-date.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 10 +++--\n builtin/rebase.c                       | 16 ++++---\n sequencer.c                            | 60 +++++++++++++++++++++++++-\n sequencer.h                            |  1 +\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++\n 6 files changed, 133 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex d060c143e6..8c62645b8c 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -438,9 +438,13 @@ when merging.\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of using the current time as the committer date, use\n+\tthe author date of the commit being rebased as the committer\n+\tdate. This option implies --force-rebase.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tThis flag is passed to 'git am' to change the author date\n+\tof each rebased commit (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -578,7 +582,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -606,6 +609,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 5d8e117276..357cd6acf3 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -89,6 +89,7 @@ struct rebase_options {\n \tint ignore_whitespace;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)\n \n \tif (opts->ignore_whitespace)\n \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n@@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n+\tif (options.committer_date_is_author_date)\n+\t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n+\t\tif (!strcmp(option, \"--ignore-date\") ||\n \t\t    !strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\ndiff --git a/sequencer.c b/sequencer.c\nindex 6fd2674632..3bb80d7414 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -872,6 +873,22 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+static const char *author_date_from_env_array(const struct argv_array *env)\n+{\n+\tint i;\n+\tconst char *date;\n+\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n \n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \targv_array_push(&cmd.args, \"commit\");\n \n \tif (!(flags & VERIFY_MSG))\n@@ -1321,7 +1342,6 @@ static int try_to_commit(struct repository *r,\n \n \tif (parse_head(r, &current_head))\n \t\treturn -1;\n-\n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n \t\tconst char *out_enc = get_commit_output_encoding();\n@@ -1349,6 +1369,30 @@ static int try_to_commit(struct repository *r,\n \t\tcommit_list_insert(current_head, &parents);\n \t}\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tint len = strlen(author);\n+\t\tstruct ident_split ident;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!ident.date_begin) {\n+\t\t\tres = error(_(\"corrupted author without date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n+\t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&date);\n+\n+\t\tif (res)\n+\t\t\tgoto out;\n+\t}\n+\n \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n \t\tres = error(_(\"git write-tree failed to write a tree\"));\n \t\tgoto out;\n@@ -2532,6 +2576,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2622,6 +2671,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n \tif (opts->keep_redundant_commits)\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3542,6 +3593,10 @@ static int do_merge(struct repository *r,\n \t\t\tgoto leave_merge;\n \t\t}\n \n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n \t\targv_array_push(&cmd.args, \"-s\");\n@@ -3819,7 +3874,8 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t\topts->record_origin || opts->edit ||\n+\t\t\t\topts->committer_date_is_author_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 0bee85093e..4ab94119ae 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -45,6 +45,7 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n \n \tint mainline;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 55ca46786d..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex fb5e747e86..84b9d5d37f 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n # This is a special case in which both am and interactive backends\n # provide the same output. It was done intentionally because\n # both the backends fall short of optimal behaviour.\n@@ -28,8 +31,13 @@ test_expect_success 'setup' '\n \tEOF\n \tgit commit -am \"update file\" &&\n \tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n \n \tgit checkout --orphan master &&\n+\tgit rm --cached foo &&\n+\trm foo &&\n \tsed -e \"s/^|//\" >file <<-\\EOF &&\n \t|line 1\n \t|        line 2\n@@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n \ttest_cmp expect file\n '\n \n+test_expect_success '--committer-date-is-author-date works with apply backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with merge backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\tgit log --pretty=\"format:%ai\" >authortime &&\n+\tgit log --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n+\tgit log --pretty=\"format:%ai\" >authortime &&\n+\tgit log --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\tgit log -1 --format=%at HEAD >expect &&\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -1 --format=%ct HEAD >actual &&\n+\ttest_cmp expect actual\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"396541","messageId":"20200429102521.47995-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-1-phillip.wood123@gmail.com","subject":"[PATCH v2 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-29T10:25:21Z","receivedAt":"2020-04-29T10:26:57Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe previous commit introduced --ignore-date flag to rebase -i, but the\nname is rather vague as it does not say whether the author date or the\ncommitter date is ignored. Add an alias to convey the precise purpose.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt   |  1 +\n builtin/rebase.c               |  6 ++++--\n t/t3436-rebase-more-options.sh | 34 ++++++++++++++++++++++------------\n 3 files changed, 27 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 96c7125791..0020b97110 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -443,6 +443,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the author date of the original commit, use\n \tthe current time as the\tauthor date of the rebased commit.  This\n \toption implies `--force-rebase`.\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex cf86240bc8..911587690b 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1519,8 +1519,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n-\t\t\t \"ignore author date and use current date\"),\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 6cd3848689..2ee7346562 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -137,22 +137,22 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n # Checking for +0000 in author time is enough since default\n # timezone is UTC, but the timezone used while committing\n # sets to +0530.\n-test_expect_success '--ignore-date works with apply backend' '\n+test_expect_success '--reset-author-date works with apply backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit rebase --apply --reset-author-date HEAD^ &&\n \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date works with merge backend' '\n+test_expect_success '--reset-author-date works with merge backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit rebase --reset-author-date -m HEAD^ &&\n \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date works after conflict resolution' '\n-\ttest_must_fail git rebase --ignore-date -m \\\n+test_expect_success '--reset-author-date works after conflict resolution' '\n+\ttest_must_fail git rebase --reset-author-date -m \\\n \t\t--onto commit2^^ commit2^ commit2 &&\n \techo resolved >foo &&\n \tgit add foo &&\n@@ -161,17 +161,17 @@ test_expect_success '--ignore-date works after conflict resolution' '\n \tgrep +0000 authortime\n '\n \n-test_expect_success '--ignore-date works with rebase -r' '\n+test_expect_success '--reset-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n-\tgit rebase -r --root --ignore-date &&\n+\tgit rebase -r --root --reset-author-date &&\n \tgit log --pretty=%ai >authortime &&\n \t! grep -v \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '\n \ttest_must_fail git rebase -m --committer-date-is-author-date \\\n-\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\t\t--reset-author-date --onto commit2^^ commit2^ commit3 &&\n \tgit checkout --theirs foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n@@ -181,16 +181,26 @@ test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n \t! grep -v \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n-\t\tgit rebase -i --strategy=resolve --ignore-date \\\n+\t\tgit rebase -i --strategy=resolve --reset-author-date \\\n \t\t--committer-date-is-author-date side side &&\n \tgit log -1 --pretty=%ai >authortime &&\n \tgit log -1 --pretty=%ci >committertime &&\n \ttest_cmp authortime committertime &&\n \tgrep \"+0000\" authortime\n  '\n \n+test_expect_success '--ignore-date is an alias for --reset-author-date' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase -m --ignore-date HEAD^ &&\n+\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime >output &&\n+\ttest_line_count = 2 output\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"396542","messageId":"20200429102521.47995-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-1-phillip.wood123@gmail.com","subject":"[PATCH v2 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-04-29T10:25:20Z","receivedAt":"2020-04-29T10:27:02Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nAs part of the on-going effort to retire the apply rebase backend\nteach the merge backend how to handle --ignore-date. We take care to\nhandle the combination of --ignore-date and\n--committer-date-is-author-date in the same way as the apply backend.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt   |  7 +++--\n builtin/rebase.c               | 13 +++++---\n sequencer.c                    | 49 +++++++++++++++++++++++++++--\n sequencer.h                    |  1 +\n t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++\n 5 files changed, 117 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 8c62645b8c..96c7125791 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -443,8 +443,9 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof each rebased commit (see linkgit:git-am[1]).\n+\tInstead of using the author date of the original commit, use\n+\tthe current time as the\tauthor date of the rebased commit.  This\n+\toption implies `--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -582,7 +583,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -610,6 +610,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n  * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 357cd6acf3..cf86240bc8 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -90,6 +90,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.committer_date_is_author_date =\n \t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)\n \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n \tif (opts->committer_date_is_author_date)\n \t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--ignore-date\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current date\"),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n@@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n-\tif (options.committer_date_is_author_date)\n+\tif (options.committer_date_is_author_date || options.ignore_date)\n \t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 8dff8b9b95..339dbf4a59 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n }\n \n+/* Construct a free()able author string with current time as the author date */\n+static char *ignore_author_date(const char *author)\n+{\n+\tint len = strlen(author);\n+\tstruct ident_split ident;\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\n+\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\terror(_(\"malformed ident line '%s'\"), author);\n+\t\treturn NULL;\n+\t}\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\n+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n \n \tif (opts->committer_date_is_author_date)\n \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n \t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,\n \t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n \t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n \t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n-\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n \t\tstrbuf_release(&date);\n \n \t\tif (res)\n@@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tauthor = ignore_author_date(author);\n+\t\tif (!author) {\n+\t\t\tres = -1;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tfree(author_to_free);\n+\t\tauthor_to_free = (char *)author;\n+\t}\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -2581,6 +2614,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->committer_date_is_author_date = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2673,6 +2711,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n \tif (opts->committer_date_is_author_date)\n \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3595,7 +3635,11 @@ static int do_merge(struct repository *r,\n \n \t\tif (opts->committer_date_is_author_date)\n \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3875,7 +3919,8 @@ static int pick_commits(struct repository *r,\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n \t\t\t\topts->record_origin || opts->edit ||\n-\t\t\t\topts->committer_date_is_author_date));\n+\t\t\t\topts->committer_date_is_author_date ||\n+\t\t\t\topts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 4ab94119ae..3587878e3b 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -46,6 +46,7 @@ struct replay_opts {\n \tint quiet;\n \tint reschedule_failed_exec;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 84b9d5d37f..6cd3848689 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n \ttest_cmp expect actual\n '\n \n+# Checking for +0000 in author time is enough since default\n+# timezone is UTC, but the timezone used while committing\n+# sets to +0530.\n+test_expect_success '--ignore-date works with apply backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works with merge backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -m \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log --pretty=%ai >authortime &&\n+\tgrep +0000 authortime\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\tgit log --pretty=%ai >authortime &&\n+\t! grep -v \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -2 --pretty=%ai >authortime &&\n+\tgit log -2 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\t! grep -v \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tgit rebase -i --strategy=resolve --ignore-date \\\n+\t\t--committer-date-is-author-date side side &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgit log -1 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\tgrep \"+0000\" authortime\n+ '\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"396597","messageId":"xmqqees6vzag.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200429102521.47995-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v2 0/5] cleanup ra/rebase-i-more-options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-29T19:59:19Z","receivedAt":"2020-04-29T19:59:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> I've rebased Rohit's patches on master and reworked them with my\n\nOK, it took a bit of time for me to figure it out, but this does\ncleanly apply on top of 048abe17 (Sync with 2.26.2, 2020-04-19).\n\nQueued, but haven't taken any deep look at it.\n\nThanks.\n"},{"id":"397493","messageId":"83643a7f-ad5c-b1a0-0936-e32340cf259f@gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-3-phillip.wood123@gmail.com","subject":"Re: [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Alban Gruin","fromEmail":"alban.gruin@gmail.com","sentAt":"2020-05-10T11:14:22Z","receivedAt":"2020-05-10T11:14:35Z","isPatch":true,"sender":{"key":"alban.gruin@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6310153?v=4"},"body":"Hi Phillip,\n\nThank you for continuing this work.\n\nLe 29/04/2020 à 12:25, Phillip Wood a écrit :\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> As part of the on-going effort to retire the apply rebase backend teach\n> the merge backend how to handle --committer-date-is-author-date.\n> \n> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt           | 10 +++--\n>  builtin/rebase.c                       | 16 ++++---\n>  sequencer.c                            | 60 +++++++++++++++++++++++++-\n>  sequencer.h                            |  1 +\n>  t/t3422-rebase-incompatible-options.sh |  1 -\n>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++\n>  6 files changed, 133 insertions(+), 11 deletions(-)\n> \n> -%<-\n>\n> diff --git a/sequencer.c b/sequencer.c\n> index 6fd2674632..3bb80d7414 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   * command-line.\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -872,6 +873,22 @@ static char *get_author(const char *message)\n>  \treturn NULL;\n>  }\n>  \n> +static const char *author_date_from_env_array(const struct argv_array *env)\n> +{\n> +\tint i;\n> +\tconst char *date;\n> +\n> +\tfor (i = 0; i < env->argc; i++)\n> +\t\tif (skip_prefix(env->argv[i],\n> +\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n> +\t\t\treturn date;\n> +\t/*\n> +\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n> +\t * reading the script\n> +\t */\n> +\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n> +}\n> +\n\nSince `GIT_AUTHOR_DATE' is set in read_env_script(), why not set\n`GIT_COMMITTER_DATE' in this function too, instead of looping in the env\narray just after setting it to get the value back?\n\n>  static const char staged_changes_advice[] =\n>  N_(\"you have staged changes in your working tree\\n\"\n>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n>  \t\t\t     gpg_opt, gpg_opt);\n>  \t}\n>  \n> +\tif (opts->committer_date_is_author_date)\n> +\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\n>  \targv_array_push(&cmd.args, \"commit\");\n>  \n>  \tif (!(flags & VERIFY_MSG))\n> @@ -1321,7 +1342,6 @@ static int try_to_commit(struct repository *r,\n>  \n>  \tif (parse_head(r, &current_head))\n>  \t\treturn -1;\n> -\n\nNit: don't remove this empty line?\n\n>  \tif (flags & AMEND_MSG) {\n>  \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n>  \t\tconst char *out_enc = get_commit_output_encoding();\n\nCheers,\nAlban\n\n"},{"id":"397494","messageId":"7d72953e-83d2-b60e-1a61-f40fde841957@gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-5-phillip.wood123@gmail.com","subject":"Re: [PATCH v2 4/5] rebase -i: support --ignore-date","fromName":"Alban Gruin","fromEmail":"alban.gruin@gmail.com","sentAt":"2020-05-10T11:14:39Z","receivedAt":"2020-05-10T11:14:45Z","isPatch":true,"sender":{"key":"alban.gruin@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6310153?v=4"},"body":"Hi Phillip,\n\nLe 29/04/2020 à 12:25, Phillip Wood a écrit :\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> As part of the on-going effort to retire the apply rebase backend\n> teach the merge backend how to handle --ignore-date. We take care to\n> handle the combination of --ignore-date and\n> --committer-date-is-author-date in the same way as the apply backend.\n> \n> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt   |  7 +++--\n>  builtin/rebase.c               | 13 +++++---\n>  sequencer.c                    | 49 +++++++++++++++++++++++++++--\n>  sequencer.h                    |  1 +\n>  t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++\n>  5 files changed, 117 insertions(+), 10 deletions(-)\n> \n> -%<-\n>\n> diff --git a/sequencer.c b/sequencer.c\n> index 8dff8b9b95..339dbf4a59 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n>  static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n> +static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n>  \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n>  }\n>  \n> +/* Construct a free()able author string with current time as the author date */\n> +static char *ignore_author_date(const char *author)\n> +{\n> +\tint len = strlen(author);\n> +\tstruct ident_split ident;\n> +\tstruct strbuf new_author = STRBUF_INIT;\n> +\n> +\tif (split_ident_line(&ident, author, len) < 0) {\n> +\t\terror(_(\"malformed ident line '%s'\"), author);\n> +\t\treturn NULL;\n> +\t}\n\nNit: add an empty line here?\n\n> +\tlen = ident.mail_end - ident.name_begin + 1;\n> +\n> +\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n> +\tdatestamp(&new_author);\n> +\treturn strbuf_detach(&new_author, NULL);\n> +}\n> +\n>  static const char staged_changes_advice[] =\n>  N_(\"you have staged changes in your working tree\\n\"\n>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n>  \n>  \tif (opts->committer_date_is_author_date)\n>  \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t opts->ignore_date ?\n> +\t\t\t\t \"\" :\n>  \t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\tif (opts->ignore_date)\n> +\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>  \n\nPerhaps this could be done in read_env_script(), too, instead of fixing\nup what this function did right after calling it, twice?  Something like\nthis:\n\n---- snip ----\nindex 339dbf4a59..3a7a80bab7 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -840,11 +840,12 @@ int read_author_script(const char *path, char\n**name, char **email, char **date,\n }\n\n /*\n- * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL AND GIT_AUTHOR_DATE from a\n- * file with shell quoting into struct argv_array. Returns -1 on\n- * error, 0 otherwise.\n+ * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL and GIT_AUTHOR_DATE from a\n+ * file with shell quoting into struct argv_array, and set\n+ * GIT_COMMITTER_DATE if needed. Returns -1 on error, 0 otherwise.\n  */\n-static int read_env_script(struct argv_array *env)\n+static int read_env_script(struct replay_opts *opts,\n+                          struct argv_array *env)\n {\n        char *name, *email, *date;\n\n@@ -854,7 +855,17 @@ static int read_env_script(struct argv_array *env)\n\n        argv_array_pushf(env, \"GIT_AUTHOR_NAME=%s\", name);\n        argv_array_pushf(env, \"GIT_AUTHOR_EMAIL=%s\", email);\n-       argv_array_pushf(env, \"GIT_AUTHOR_DATE=%s\", date);\n+\n+       if (opts->ignore_date) {\n+               argv_array_push(env, \"GIT_AUTHOR_DATE=\");\n+               argv_array_push(env, \"GIT_COMMITTER_DATE=\");\n+       } else {\n+               argv_array_pushf(env, \"GIT_AUTHOR_DATE=%s\", date);\n+\n+               if (opts->committer_date_is_author_date)\n+                       argv_array_pushf(env, \"GIT_COMMITTER_DATE=%s\",\ndate);\n+       }\n+\n        free(name);\n        free(email);\n        free(date);\n---- snap ----\n\n>  \targv_array_push(&cmd.args, \"commit\");\n>  \n> @@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,\n>  \t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n>  \t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n>  \t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n> -\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n> +\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n>  \t\tstrbuf_release(&date);\n>  \n>  \t\tif (res)\n> @@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,\n>  \n>  \treset_ident_date();\n>  \n> +\tif (opts->ignore_date) {\n> +\t\tauthor = ignore_author_date(author);\n> +\t\tif (!author) {\n> +\t\t\tres = -1;\n> +\t\t\tgoto out;\n> +\t\t}\n> +\t\tfree(author_to_free);\n> +\t\tauthor_to_free = (char *)author;\n> +\t}\n\nNit: add an empty line here?\n\nCheers,\nAlban\n\n"},{"id":"397602","messageId":"c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com","threadId":"53176","inReplyTo":"7d72953e-83d2-b60e-1a61-f40fde841957@gmail.com","subject":"Re: [PATCH v2 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-12T14:47:33Z","receivedAt":"2020-05-12T14:47:39Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Alban\n\nThanks for looking at this series\n\nOn 10/05/2020 12:14, Alban Gruin wrote:\n> Hi Phillip,\n> \n> Le 29/04/2020 à 12:25, Phillip Wood a écrit :\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> As part of the on-going effort to retire the apply rebase backend\n>> teach the merge backend how to handle --ignore-date. We take care to\n>> handle the combination of --ignore-date and\n>> --committer-date-is-author-date in the same way as the apply backend.\n>>\n>> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> ---\n>>   Documentation/git-rebase.txt   |  7 +++--\n>>   builtin/rebase.c               | 13 +++++---\n>>   sequencer.c                    | 49 +++++++++++++++++++++++++++--\n>>   sequencer.h                    |  1 +\n>>   t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++\n>>   5 files changed, 117 insertions(+), 10 deletions(-)\n>>\n>> -%<-\n>>\n>> diff --git a/sequencer.c b/sequencer.c\n>> index 8dff8b9b95..339dbf4a59 100644\n>> --- a/sequencer.c\n>> +++ b/sequencer.c\n>> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>>    */\n>>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n>>   static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>> +static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n>>   static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>>   static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>>   static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n>> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n>>   \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n>>   }\n>>   \n>> +/* Construct a free()able author string with current time as the author date */\n>> +static char *ignore_author_date(const char *author)\n>> +{\n>> +\tint len = strlen(author);\n>> +\tstruct ident_split ident;\n>> +\tstruct strbuf new_author = STRBUF_INIT;\n>> +\n>> +\tif (split_ident_line(&ident, author, len) < 0) {\n>> +\t\terror(_(\"malformed ident line '%s'\"), author);\n>> +\t\treturn NULL;\n>> +\t}\n> \n> Nit: add an empty line here?\n\nand delete the one below?\n\n>> +\tlen = ident.mail_end - ident.name_begin + 1;\n>> +\n>> +\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n>> +\tdatestamp(&new_author);\n>> +\treturn strbuf_detach(&new_author, NULL);\n>> +}\n>> +\n>>   static const char staged_changes_advice[] =\n>>   N_(\"you have staged changes in your working tree\\n\"\n>>   \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n>> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n>>   \n>>   \tif (opts->committer_date_is_author_date)\n>>   \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>> +\t\t\t\t opts->ignore_date ?\n>> +\t\t\t\t \"\" :\n>>   \t\t\t\t author_date_from_env_array(&cmd.env_array));\n>> +\tif (opts->ignore_date)\n>> +\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>>   \n> \n> Perhaps this could be done in read_env_script(), too, instead of fixing\n> up what this function did right after calling it, twice?  Something like\n> this:\n\nLong term I'd like to stop writing the author-script file unless we're \nstopping for a conflict resolution or edit so I'm reluctant to add more \nfunctionality to it at the moment. Also I tend to view read_env_script() \nit as loading the author details from a file rather than setting up the \nenvironment for the commit.\n\n> ---- snip ----\n> index 339dbf4a59..3a7a80bab7 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -840,11 +840,12 @@ int read_author_script(const char *path, char\n> **name, char **email, char **date,\n>   }\n> \n>   /*\n> - * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL AND GIT_AUTHOR_DATE from a\n> - * file with shell quoting into struct argv_array. Returns -1 on\n> - * error, 0 otherwise.\n> + * Read a GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL and GIT_AUTHOR_DATE from a\n> + * file with shell quoting into struct argv_array, and set\n> + * GIT_COMMITTER_DATE if needed. Returns -1 on error, 0 otherwise.\n>    */\n> -static int read_env_script(struct argv_array *env)\n> +static int read_env_script(struct replay_opts *opts,\n> +                          struct argv_array *env)\n>   {\n>          char *name, *email, *date;\n> \n> @@ -854,7 +855,17 @@ static int read_env_script(struct argv_array *env)\n> \n>          argv_array_pushf(env, \"GIT_AUTHOR_NAME=%s\", name);\n>          argv_array_pushf(env, \"GIT_AUTHOR_EMAIL=%s\", email);\n> -       argv_array_pushf(env, \"GIT_AUTHOR_DATE=%s\", date);\n> +\n> +       if (opts->ignore_date) {\n> +               argv_array_push(env, \"GIT_AUTHOR_DATE=\");\n> +               argv_array_push(env, \"GIT_COMMITTER_DATE=\");\n> +       } else {\n> +               argv_array_pushf(env, \"GIT_AUTHOR_DATE=%s\", date);\n> +\n> +               if (opts->committer_date_is_author_date)\n> +                       argv_array_pushf(env, \"GIT_COMMITTER_DATE=%s\",\n> date);\n> +       }\n> +\n>          free(name);\n>          free(email);\n>          free(date);\n> ---- snap ----\n> \n>>   \targv_array_push(&cmd.args, \"commit\");\n>>   \n>> @@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,\n>>   \t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n>>   \t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n>>   \t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n>> -\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n>> +\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n>> +\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n>>   \t\tstrbuf_release(&date);\n>>   \n>>   \t\tif (res)\n>> @@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,\n>>   \n>>   \treset_ident_date();\n>>   \n>> +\tif (opts->ignore_date) {\n>> +\t\tauthor = ignore_author_date(author);\n>> +\t\tif (!author) {\n>> +\t\t\tres = -1;\n>> +\t\t\tgoto out;\n>> +\t\t}\n>> +\t\tfree(author_to_free);\n>> +\t\tauthor_to_free = (char *)author;\n>> +\t}\n> \n> Nit: add an empty line here?\n\nYes that would fit the style in the rest of the function\n\nBest Wishes\n\nPhillip\n\n> \n> Cheers,\n> Alban\n> \n"},{"id":"397694","messageId":"CABPp-BFo2pmF-tiTc8QMO52jFdLFLi_Eye+-bmNXp0FsDgbHOA@mail.gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-5-phillip.wood123@gmail.com","subject":"Re: [PATCH v2 4/5] rebase -i: support --ignore-date","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-05-13T03:54:30Z","receivedAt":"2020-05-13T03:54:45Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> As part of the on-going effort to retire the apply rebase backend\n> teach the merge backend how to handle --ignore-date. We take care to\n> handle the combination of --ignore-date and\n> --committer-date-is-author-date in the same way as the apply backend.\n>\n> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt   |  7 +++--\n>  builtin/rebase.c               | 13 +++++---\n>  sequencer.c                    | 49 +++++++++++++++++++++++++++--\n>  sequencer.h                    |  1 +\n>  t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++\n>  5 files changed, 117 insertions(+), 10 deletions(-)\n>\n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 8c62645b8c..96c7125791 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -443,8 +443,9 @@ See also INCOMPATIBLE OPTIONS below.\n>         date. This option implies --force-rebase.\n>\n>  --ignore-date::\n> -       This flag is passed to 'git am' to change the author date\n> -       of each rebased commit (see linkgit:git-am[1]).\n> +       Instead of using the author date of the original commit, use\n> +       the current time as the author date of the rebased commit.  This\n> +       option implies `--force-rebase`.\n>  +\n>  See also INCOMPATIBLE OPTIONS below.\n>\n> @@ -582,7 +583,6 @@ INCOMPATIBLE OPTIONS\n>  The following options:\n>\n>   * --apply\n> - * --ignore-date\n>   * --whitespace\n>   * -C\n>\n> @@ -610,6 +610,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --empty=\n>   * --preserve-merges and --ignore-whitespace\n>   * --preserve-merges and --committer-date-is-author-date\n> + * --preserve-merges and --ignore-date\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 357cd6acf3..cf86240bc8 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -90,6 +90,7 @@ struct rebase_options {\n>         char *gpg_sign_opt;\n>         int autostash;\n>         int committer_date_is_author_date;\n> +       int ignore_date;\n>         char *cmd;\n>         int allow_empty_message;\n>         int rebase_merges, rebase_cousins;\n> @@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>         replay.committer_date_is_author_date =\n>                                         opts->committer_date_is_author_date;\n> +       replay.ignore_date = opts->ignore_date;\n>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>         replay.strategy = opts->strategy;\n>\n> @@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)\n>                 argv_array_push(&am.args, \"--ignore-whitespace\");\n>         if (opts->committer_date_is_author_date)\n>                 argv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n> +       if (opts->ignore_date)\n> +               argv_array_push(&opts->git_am_opts, \"--ignore-date\");\n>         if (opts->action && !strcmp(\"continue\", opts->action)) {\n>                 argv_array_push(&am.args, \"--resolved\");\n>                 argv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n> @@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>                 OPT_BOOL(0, \"committer-date-is-author-date\",\n>                          &options.committer_date_is_author_date,\n>                          N_(\"make committer date match author date\")),\n> -               OPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n> -                                 N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> +               OPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n> +                        \"ignore author date and use current date\"),\n>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>                                   N_(\"passed to 'git apply'\"), 0),\n>                 OPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n> @@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>             options.autosquash) {\n>                 allow_preemptive_ff = 0;\n>         }\n> -       if (options.committer_date_is_author_date)\n> +       if (options.committer_date_is_author_date || options.ignore_date)\n>                 options.flags |= REBASE_FORCE;\n>\n>         for (i = 0; i < options.git_am_opts.argc; i++) {\n>                 const char *option = options.git_am_opts.argv[i], *p;\n> -               if (!strcmp(option, \"--ignore-date\") ||\n> -                   !strcmp(option, \"--whitespace=fix\") ||\n> +               if (!strcmp(option, \"--whitespace=fix\") ||\n>                     !strcmp(option, \"--whitespace=strip\"))\n>                         allow_preemptive_ff = 0;\n>                 else if (skip_prefix(option, \"-C\", &p)) {\n> diff --git a/sequencer.c b/sequencer.c\n> index 8dff8b9b95..339dbf4a59 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n>  static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n> +static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n>         BUG(\"GIT_AUTHOR_DATE missing from author script\");\n>  }\n>\n> +/* Construct a free()able author string with current time as the author date */\n> +static char *ignore_author_date(const char *author)\n> +{\n> +       int len = strlen(author);\n> +       struct ident_split ident;\n> +       struct strbuf new_author = STRBUF_INIT;\n> +\n> +       if (split_ident_line(&ident, author, len) < 0) {\n> +               error(_(\"malformed ident line '%s'\"), author);\n> +               return NULL;\n> +       }\n> +       len = ident.mail_end - ident.name_begin + 1;\n> +\n> +       strbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n> +       datestamp(&new_author);\n> +       return strbuf_detach(&new_author, NULL);\n> +}\n> +\n>  static const char staged_changes_advice[] =\n>  N_(\"you have staged changes in your working tree\\n\"\n>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n>\n>         if (opts->committer_date_is_author_date)\n>                 argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +                                opts->ignore_date ?\n> +                                \"\" :\n>                                  author_date_from_env_array(&cmd.env_array));\n> +       if (opts->ignore_date)\n> +               argv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>\n>         argv_array_push(&cmd.args, \"commit\");\n>\n> @@ -1386,7 +1409,8 @@ static int try_to_commit(struct repository *r,\n>                 strbuf_addf(&date, \"@%.*s %.*s\",\n>                             (int)(ident.date_end - ident.date_begin), ident.date_begin,\n>                             (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n> -               res = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +               res = setenv(\"GIT_COMMITTER_DATE\",\n> +                            opts->ignore_date ? \"\" : date.buf, 1);\n>                 strbuf_release(&date);\n>\n>                 if (res)\n> @@ -1452,6 +1476,15 @@ static int try_to_commit(struct repository *r,\n>\n>         reset_ident_date();\n>\n> +       if (opts->ignore_date) {\n> +               author = ignore_author_date(author);\n> +               if (!author) {\n> +                       res = -1;\n> +                       goto out;\n> +               }\n> +               free(author_to_free);\n> +               author_to_free = (char *)author;\n> +       }\n>         if (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n>                                  oid, author, opts->gpg_sign, extra)) {\n>                 res = error(_(\"failed to write commit object\"));\n> @@ -2581,6 +2614,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>                         opts->committer_date_is_author_date = 1;\n>                 }\n>\n> +               if (file_exists(rebase_path_ignore_date())) {\n> +                       opts->allow_ff = 0;\n> +                       opts->ignore_date = 1;\n> +               }\n> +\n>                 if (file_exists(rebase_path_reschedule_failed_exec()))\n>                         opts->reschedule_failed_exec = 1;\n>\n> @@ -2673,6 +2711,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>                 write_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n>         if (opts->committer_date_is_author_date)\n>                 write_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n> +       if (opts->ignore_date)\n> +               write_file(rebase_path_ignore_date(), \"%s\", \"\");\n>         if (opts->reschedule_failed_exec)\n>                 write_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>\n> @@ -3595,7 +3635,11 @@ static int do_merge(struct repository *r,\n>\n>                 if (opts->committer_date_is_author_date)\n>                         argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +                                        opts->ignore_date ?\n> +                                        \"\" :\n>                                          author_date_from_env_array(&cmd.env_array));\n> +               if (opts->ignore_date)\n> +                       argv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>\n>                 cmd.git_cmd = 1;\n>                 argv_array_push(&cmd.args, \"merge\");\n> @@ -3875,7 +3919,8 @@ static int pick_commits(struct repository *r,\n>         if (opts->allow_ff)\n>                 assert(!(opts->signoff || opts->no_commit ||\n>                                 opts->record_origin || opts->edit ||\n> -                               opts->committer_date_is_author_date));\n> +                               opts->committer_date_is_author_date ||\n> +                               opts->ignore_date));\n>         if (read_and_refresh_cache(r, opts))\n>                 return -1;\n>\n> diff --git a/sequencer.h b/sequencer.h\n> index 4ab94119ae..3587878e3b 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -46,6 +46,7 @@ struct replay_opts {\n>         int quiet;\n>         int reschedule_failed_exec;\n>         int committer_date_is_author_date;\n> +       int ignore_date;\n>\n>         int mainline;\n>\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 84b9d5d37f..6cd3848689 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n>         test_cmp expect actual\n>  '\n>\n> +# Checking for +0000 in author time is enough since default\n> +# timezone is UTC, but the timezone used while committing\n> +# sets to +0530.\n> +test_expect_success '--ignore-date works with apply backend' '\n> +       git commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +       git rebase --apply --ignore-date HEAD^ &&\n> +       git log -1 --pretty=\"format:%ai\" >authortime &&\n> +       grep \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date works with merge backend' '\n> +       git commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +       git rebase --ignore-date -m HEAD^ &&\n> +       git log -1 --pretty=\"format:%ai\" >authortime &&\n> +       grep \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date works after conflict resolution' '\n> +       test_must_fail git rebase --ignore-date -m \\\n> +               --onto commit2^^ commit2^ commit2 &&\n> +       echo resolved >foo &&\n> +       git add foo &&\n> +       git rebase --continue &&\n> +       git log --pretty=%ai >authortime &&\n> +       grep +0000 authortime\n> +'\n> +\n> +test_expect_success '--ignore-date works with rebase -r' '\n> +       git checkout side &&\n> +       git merge --no-ff commit3 &&\n> +       git rebase -r --root --ignore-date &&\n> +       git log --pretty=%ai >authortime &&\n> +       ! grep -v \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n> +       test_must_fail git rebase -m --committer-date-is-author-date \\\n> +               --ignore-date --onto commit2^^ commit2^ commit3 &&\n> +       git checkout --theirs foo &&\n> +       git add foo &&\n> +       git rebase --continue &&\n> +       git log -2 --pretty=%ai >authortime &&\n> +       git log -2 --pretty=%ci >committertime &&\n> +       test_cmp authortime committertime &&\n> +       ! grep -v \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n> +       GIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n> +               git rebase -i --strategy=resolve --ignore-date \\\n> +               --committer-date-is-author-date side side &&\n> +       git log -1 --pretty=%ai >authortime &&\n> +       git log -1 --pretty=%ci >committertime &&\n> +       test_cmp authortime committertime &&\n> +       grep \"+0000\" authortime\n> + '\n> +\n>  # This must be the last test in this file\n>  test_expect_success '$EDITOR and friends are unchanged' '\n>         test_editor_unchanged\n> --\n> 2.26.2\n\nSame question here as for patch 2 -- does it rely on us forking a \"git\ncommit\" subprocess which reads from the environment variable, or does\nour try_to_commit() (which I'd rather we used in all cases) also work\nwith the environment variable?\n\nDidn't notice any other problems or questions while reading over the patch.\n"},{"id":"397695","messageId":"CABPp-BG+nWR9S9fw=_0XV8GA5JRAKaL2TZUU578PQkW8f_z7ew@mail.gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-2-phillip.wood123@gmail.com","subject":"Re: [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-05-13T03:54:43Z","receivedAt":"2020-05-13T03:55:11Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Sorry for taking so long to get back to you, and thanks for pushing\nthis forward.\n\nOn Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>\n> Rebase is implemented with two different backends - 'apply' and 'merge'\n> each of which support a different set of options. In particuar the apply\n> backend supports a number of options implemented by 'git am' that are\n> not available to the merge backend. As part of an on going effort to\n> remove the apply backend this patch adds support for the\n> --ignore-whitespace option to the merge backend. This option treats\n> lines with only whitespace changes as unchanged and is implemented in\n> the merge backend by translating it to -Xignore-space-change.\n>\n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt           | 12 +++-\n>  builtin/rebase.c                       | 19 ++++--\n>  t/t3422-rebase-incompatible-options.sh |  1 -\n>  t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++\n>  4 files changed, 111 insertions(+), 7 deletions(-)\n>  create mode 100755 t/t3436-rebase-more-options.sh\n>\n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index f7a6033607..d060c143e6 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -422,8 +422,16 @@ your branch contains commits which were dropped, this option can be used\n>  with `--keep-base` in order to drop those commits from your branch.\n>\n>  --ignore-whitespace::\n> +       Behaves differently depending on which backend is selected.\n\nI still don't like this wording; it defers answering the question,\nimplies that the difference is intentional, and most importantly\nprovides no context about *intended* behavior.  I tried to communicate\nthis to Rohit multiple times, but he seemed to fixate on and highlight\nthe differences in a way that made them sound like they were by\ndesign, rather than highlighting the intent we want to move towards\nand mentioning that this patch gets us most the way there.\n\nAs far as I can tell, the --ignore-whitespace and\n-Xignore-space-change were always meant to do the same thing: ignore\ndifferences in whitespace when doing so can avoid conflicts.\n\nIn case anyone isn't sure about my assertion that these were always\nmeant to do the same thing:\n  * apply aliases --ignore-whitespace and --ignore-space-change; they\nmeant the same thing\n  * commit f008cef4ab (\"Merge branch 'jc/apply-ignore-whitespace'\",\n2014-06-03) says that apply's --ignore-space-change wasn't behaving\nconsistently with diff's --ignore-space-change\n  * diff's --ignore-space-change goes through xdiff's XDL opts, much\nlike merge-recursive does.\nFurther, the original commit that introduced these xdiff options to\nmerge-recursive, 4e5dd044c6 (\"merge-recursive: options to ignore\nwhitespace changes\", 2010-08-26), it is clear that:\n  * he only cared about ignore-space-at-eol and implemented\nignore-space-change at the same time only for completeness\n  * it wouldn't matter to his usecase if whitespace-only changes were\nstripped, thus he wouldn't have spotted the bug it has\n  * the wording also suggests these options were picked to match\noptions of the same name elsewhere in git\n\nI would rather we said something like:\n    Ignore whitespace differences when trying to reconcile\ndifferences.  Currently, each backend implements an approximation of\nthis behavior:\n\n> ++\n> +apply backend: When applying a patch, ignore changes in whitespace in\n> +context lines.\n\nMaybe add something like:\n    (Unfortunately, this means that if the \"old\" lines being replaced\nby the patch differ only in whitespace from the existing file, you\nwill get a merge conflict instead of a successful patch application.)\n\n> ++\n> +merge backend: Treat lines with only whitespace changes as unchanged\n> +when merging.\n\nMaybe add something like:\n   (Unfortunately, this means that any patch hunks that were intended\nto modify whitespace and nothing else will be dropped, even if the\nother side had no changes that conflicted.)\n\n> +\n>  --whitespace=<option>::\n> -       These flags are passed to the 'git apply' program\n> +       This flag is passed to the 'git apply' program\n>         (see linkgit:git-apply[1]) that applies the patch.\n>         Implies --apply.\n>  +\n> @@ -572,7 +580,6 @@ The following options:\n>   * --apply\n>   * --committer-date-is-author-date\n>   * --ignore-date\n> - * --ignore-whitespace\n>   * --whitespace\n>   * -C\n>\n> @@ -598,6 +605,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --signoff\n>   * --preserve-merges and --rebase-merges\n>   * --preserve-merges and --empty=\n> + * --preserve-merges and --ignore-whitespace\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 27a07d4e78..5d8e117276 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -86,6 +86,7 @@ struct rebase_options {\n>         int signoff;\n>         int allow_rerere_autoupdate;\n>         int autosquash;\n> +       int ignore_whitespace;\n>         char *gpg_sign_opt;\n>         int autostash;\n>         char *cmd;\n> @@ -108,6 +109,7 @@ struct rebase_options {\n>\n>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  {\n> +       struct strbuf strategy_buf = STRBUF_INIT;\n>         struct replay_opts replay = REPLAY_OPTS_INIT;\n>\n>         replay.action = REPLAY_INTERACTIVE_REBASE;\n> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>         replay.strategy = opts->strategy;\n> +\n>         if (opts->strategy_opts)\n> -               parse_strategy_opts(&replay, opts->strategy_opts);\n> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);\n> +       if (opts->ignore_whitespace)\n> +               strbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n> +       if (strategy_buf.len)\n> +               parse_strategy_opts(&replay, strategy_buf.buf);\n>\n>         if (opts->squash_onto) {\n>                 oidcpy(&replay.squash_onto, opts->squash_onto);\n>                 replay.have_squash_onto = 1;\n>         }\n>\n> +       strbuf_release(&strategy_buf);\n>         return replay;\n>  }\n>\n> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>         argc = parse_options(argc, argv, prefix, options,\n>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n>\n> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n> +\n>         if (!is_null_oid(&squash_onto))\n>                 opts.squash_onto = &squash_onto;\n>\n> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)\n>         am.git_cmd = 1;\n>         argv_array_push(&am.args, \"am\");\n>\n> +       if (opts->ignore_whitespace)\n> +               argv_array_push(&am.args, \"--ignore-whitespace\");\n>         if (opts->action && !strcmp(\"continue\", opts->action)) {\n>                 argv_array_push(&am.args, \"--resolved\");\n>                 argv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>                 OPT_BOOL(0, \"signoff\", &options.signoff,\n>                          N_(\"add a Signed-off-by: line to each commit\")),\n> -               OPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n> -                                 NULL, N_(\"passed to 'git am'\"),\n> -                                 PARSE_OPT_NOARG),\n>                 OPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>                                   &options.git_am_opts, NULL,\n>                                   N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>                 OPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>                                   N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>                                   N_(\"passed to 'git apply'\"), 0),\n> +               OPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n> +                        N_(\"ignore changes in whitespace\")),\n>                 OPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>                                   N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>                 OPT_BIT('f', \"force-rebase\", &options.flags,\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 50e7960702..55ca46786d 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>\n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --ignore-whitespace\n>  test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> new file mode 100755\n> index 0000000000..fb5e747e86\n> --- /dev/null\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -0,0 +1,86 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2019 Rohit Ashiwal\n> +#\n> +\n> +test_description='tests to ensure compatibility between am and interactive backends'\n> +\n> +. ./test-lib.sh\n> +\n> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n> +\n> +# This is a special case in which both am and interactive backends\n> +# provide the same output. It was done intentionally because\n> +# both the backends fall short of optimal behaviour.\n> +test_expect_success 'setup' '\n> +       git checkout -b topic &&\n> +       q_to_tab >file <<-\\EOF &&\n> +       line 1\n> +       Qline 2\n> +       line 3\n> +       EOF\n> +       git add file &&\n> +       git commit -m \"add file\" &&\n> +       cat >file <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       git commit -am \"update file\" &&\n> +       git tag side &&\n> +\n> +       git checkout --orphan master &&\n> +       sed -e \"s/^|//\" >file <<-\\EOF &&\n> +       |line 1\n> +       |        line 2\n> +       |line 3\n> +       EOF\n> +       git add file &&\n> +       git commit -m \"add file\" &&\n> +       git tag main\n> +'\n> +\n> +test_expect_success '--ignore-whitespace works with apply backend' '\n> +       cat >expect <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       test_must_fail git rebase --apply main side &&\n> +       git rebase --abort &&\n> +       git rebase --apply --ignore-whitespace main side &&\n> +       test_cmp expect file\n> +'\n> +\n> +test_expect_success '--ignore-whitespace works with merge backend' '\n> +       cat >expect <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       test_must_fail git rebase --merge main side &&\n> +       git rebase --abort &&\n> +       git rebase --merge --ignore-whitespace main side &&\n> +       test_cmp expect file\n> +'\n> +\n> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n> +       cat >expect <<-\\EOF &&\n> +       line 1\n> +       new line 2\n> +       line 3\n> +       EOF\n> +       (\n> +               set_fake_editor &&\n> +               FAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n> +       ) &&\n> +       git rebase --continue &&\n> +       test_cmp expect file\n> +'\n> +\n> +# This must be the last test in this file\n> +test_expect_success '$EDITOR and friends are unchanged' '\n> +       test_editor_unchanged\n> +'\n> +\n> +test_done\n> --\n> 2.26.2\n\nThe rest looks good to me.\n"},{"id":"397696","messageId":"CABPp-BG2tmwTLcU1d-qgZ4fK9Rrd5wo0QjO685tpfzHjQj1n3A@mail.gmail.com","threadId":"53176","inReplyTo":"xmqqees6vzag.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v2 0/5] cleanup ra/rebase-i-more-options","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-05-13T03:57:01Z","receivedAt":"2020-05-13T03:57:14Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Wed, Apr 29, 2020 at 12:59 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n>\n> > From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> >\n> > I've rebased Rohit's patches on master and reworked them with my\n>\n> OK, it took a bit of time for me to figure it out, but this does\n> cleanly apply on top of 048abe17 (Sync with 2.26.2, 2020-04-19).\n>\n> Queued, but haven't taken any deep look at it.\n>\n> Thanks.\n\nSorry for the long delay in reviewing.  I looked through all five\npatches; I had the same simple question about patches 2 & 4, and had\nsome comments about the wording of the documentation in patch 1, but\nall small stuff.  I didn't notice anything outside of those few small\ncomments.\n"},{"id":"397697","messageId":"CABPp-BEFA_-dp8i8HaZO8mQ7de5rNaYQzKfU6tP3QW2+jHRx3w@mail.gmail.com","threadId":"53176","inReplyTo":"20200429102521.47995-3-phillip.wood123@gmail.com","subject":"Re: [PATCH v2 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-05-13T04:08:24Z","receivedAt":"2020-05-13T04:08:37Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> As part of the on-going effort to retire the apply rebase backend teach\n> the merge backend how to handle --committer-date-is-author-date.\n>\n> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt           | 10 +++--\n>  builtin/rebase.c                       | 16 ++++---\n>  sequencer.c                            | 60 +++++++++++++++++++++++++-\n>  sequencer.h                            |  1 +\n>  t/t3422-rebase-incompatible-options.sh |  1 -\n>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++\n>  6 files changed, 133 insertions(+), 11 deletions(-)\n>\n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index d060c143e6..8c62645b8c 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -438,9 +438,13 @@ when merging.\n>  See also INCOMPATIBLE OPTIONS below.\n>\n>  --committer-date-is-author-date::\n> +       Instead of using the current time as the committer date, use\n> +       the author date of the commit being rebased as the committer\n> +       date. This option implies --force-rebase.\n> +\n>  --ignore-date::\n> -       These flags are passed to 'git am' to easily change the dates\n> -       of the rebased commits (see linkgit:git-am[1]).\n> +       This flag is passed to 'git am' to change the author date\n> +       of each rebased commit (see linkgit:git-am[1]).\n>  +\n>  See also INCOMPATIBLE OPTIONS below.\n>\n> @@ -578,7 +582,6 @@ INCOMPATIBLE OPTIONS\n>  The following options:\n>\n>   * --apply\n> - * --committer-date-is-author-date\n>   * --ignore-date\n>   * --whitespace\n>   * -C\n> @@ -606,6 +609,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --rebase-merges\n>   * --preserve-merges and --empty=\n>   * --preserve-merges and --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 5d8e117276..357cd6acf3 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -89,6 +89,7 @@ struct rebase_options {\n>         int ignore_whitespace;\n>         char *gpg_sign_opt;\n>         int autostash;\n> +       int committer_date_is_author_date;\n>         char *cmd;\n>         int allow_empty_message;\n>         int rebase_merges, rebase_cousins;\n> @@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>         replay.quiet = !(opts->flags & REBASE_NO_QUIET);\n>         replay.verbose = opts->flags & REBASE_VERBOSE;\n>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;\n> +       replay.committer_date_is_author_date =\n> +                                       opts->committer_date_is_author_date;\n>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>         replay.strategy = opts->strategy;\n>\n> @@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)\n>\n>         if (opts->ignore_whitespace)\n>                 argv_array_push(&am.args, \"--ignore-whitespace\");\n> +       if (opts->committer_date_is_author_date)\n> +               argv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n>         if (opts->action && !strcmp(\"continue\", opts->action)) {\n>                 argv_array_push(&am.args, \"--resolved\");\n>                 argv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n> @@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>                 OPT_BOOL(0, \"signoff\", &options.signoff,\n>                          N_(\"add a Signed-off-by: line to each commit\")),\n> -               OPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n> -                                 &options.git_am_opts, NULL,\n> -                                 N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> +               OPT_BOOL(0, \"committer-date-is-author-date\",\n> +                        &options.committer_date_is_author_date,\n> +                        N_(\"make committer date match author date\")),\n>                 OPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>                                   N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n> @@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>             options.autosquash) {\n>                 allow_preemptive_ff = 0;\n>         }\n> +       if (options.committer_date_is_author_date)\n> +               options.flags |= REBASE_FORCE;\n>\n>         for (i = 0; i < options.git_am_opts.argc; i++) {\n>                 const char *option = options.git_am_opts.argv[i], *p;\n> -               if (!strcmp(option, \"--committer-date-is-author-date\") ||\n> -                   !strcmp(option, \"--ignore-date\") ||\n> +               if (!strcmp(option, \"--ignore-date\") ||\n>                     !strcmp(option, \"--whitespace=fix\") ||\n>                     !strcmp(option, \"--whitespace=strip\"))\n>                         allow_preemptive_ff = 0;\n> diff --git a/sequencer.c b/sequencer.c\n> index 6fd2674632..3bb80d7414 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   * command-line.\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -872,6 +873,22 @@ static char *get_author(const char *message)\n>         return NULL;\n>  }\n>\n> +static const char *author_date_from_env_array(const struct argv_array *env)\n> +{\n> +       int i;\n> +       const char *date;\n> +\n> +       for (i = 0; i < env->argc; i++)\n> +               if (skip_prefix(env->argv[i],\n> +                               \"GIT_AUTHOR_DATE=\", &date))\n> +                       return date;\n> +       /*\n> +        * If GIT_AUTHOR_DATE is missing we should have already errored out when\n> +        * reading the script\n> +        */\n> +       BUG(\"GIT_AUTHOR_DATE missing from author script\");\n> +}\n> +\n>  static const char staged_changes_advice[] =\n>  N_(\"you have staged changes in your working tree\\n\"\n>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n>                              gpg_opt, gpg_opt);\n>         }\n>\n> +       if (opts->committer_date_is_author_date)\n> +               argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +                                author_date_from_env_array(&cmd.env_array));\n> +\n>         argv_array_push(&cmd.args, \"commit\");\n>\n>         if (!(flags & VERIFY_MSG))\n> @@ -1321,7 +1342,6 @@ static int try_to_commit(struct repository *r,\n>\n>         if (parse_head(r, &current_head))\n>                 return -1;\n> -\n>         if (flags & AMEND_MSG) {\n>                 const char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n>                 const char *out_enc = get_commit_output_encoding();\n> @@ -1349,6 +1369,30 @@ static int try_to_commit(struct repository *r,\n>                 commit_list_insert(current_head, &parents);\n>         }\n>\n> +       if (opts->committer_date_is_author_date) {\n> +               int len = strlen(author);\n> +               struct ident_split ident;\n> +               struct strbuf date = STRBUF_INIT;\n> +\n> +               if (split_ident_line(&ident, author, len) < 0) {\n> +                       res = error(_(\"malformed ident line '%s'\"), author);\n> +                       goto out;\n> +               }\n> +               if (!ident.date_begin) {\n> +                       res = error(_(\"corrupted author without date information\"));\n> +                       goto out;\n> +               }\n> +\n> +               strbuf_addf(&date, \"@%.*s %.*s\",\n> +                           (int)(ident.date_end - ident.date_begin), ident.date_begin,\n> +                           (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n> +               res = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +               strbuf_release(&date);\n> +\n> +               if (res)\n> +                       goto out;\n> +       }\n> +\n>         if (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>                 res = error(_(\"git write-tree failed to write a tree\"));\n>                 goto out;\n> @@ -2532,6 +2576,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>                         opts->signoff = 1;\n>                 }\n>\n> +               if (file_exists(rebase_path_cdate_is_adate())) {\n> +                       opts->allow_ff = 0;\n> +                       opts->committer_date_is_author_date = 1;\n> +               }\n> +\n>                 if (file_exists(rebase_path_reschedule_failed_exec()))\n>                         opts->reschedule_failed_exec = 1;\n>\n> @@ -2622,6 +2671,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>                 write_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>         if (opts->keep_redundant_commits)\n>                 write_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n> +       if (opts->committer_date_is_author_date)\n> +               write_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>         if (opts->reschedule_failed_exec)\n>                 write_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>\n> @@ -3542,6 +3593,10 @@ static int do_merge(struct repository *r,\n>                         goto leave_merge;\n>                 }\n>\n> +               if (opts->committer_date_is_author_date)\n> +                       argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +                                        author_date_from_env_array(&cmd.env_array));\n> +\n>                 cmd.git_cmd = 1;\n>                 argv_array_push(&cmd.args, \"merge\");\n>                 argv_array_push(&cmd.args, \"-s\");\n> @@ -3819,7 +3874,8 @@ static int pick_commits(struct repository *r,\n>         setenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>         if (opts->allow_ff)\n>                 assert(!(opts->signoff || opts->no_commit ||\n> -                               opts->record_origin || opts->edit));\n> +                               opts->record_origin || opts->edit ||\n> +                               opts->committer_date_is_author_date));\n>         if (read_and_refresh_cache(r, opts))\n>                 return -1;\n>\n> diff --git a/sequencer.h b/sequencer.h\n> index 0bee85093e..4ab94119ae 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -45,6 +45,7 @@ struct replay_opts {\n>         int verbose;\n>         int quiet;\n>         int reschedule_failed_exec;\n> +       int committer_date_is_author_date;\n>\n>         int mainline;\n>\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 55ca46786d..c8234062c6 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>\n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>\n>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index fb5e747e86..84b9d5d37f 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>\n>  . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>\n> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> +export GIT_AUTHOR_DATE\n> +\n>  # This is a special case in which both am and interactive backends\n>  # provide the same output. It was done intentionally because\n>  # both the backends fall short of optimal behaviour.\n> @@ -28,8 +31,13 @@ test_expect_success 'setup' '\n>         EOF\n>         git commit -am \"update file\" &&\n>         git tag side &&\n> +       test_commit commit1 foo foo1 &&\n> +       test_commit commit2 foo foo2 &&\n> +       test_commit commit3 foo foo3 &&\n>\n>         git checkout --orphan master &&\n> +       git rm --cached foo &&\n> +       rm foo &&\n>         sed -e \"s/^|//\" >file <<-\\EOF &&\n>         |line 1\n>         |        line 2\n> @@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n>         test_cmp expect file\n>  '\n>\n> +test_expect_success '--committer-date-is-author-date works with apply backend' '\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +       git rebase --apply --committer-date-is-author-date HEAD^ &&\n> +       git log -1 --pretty=\"format:%ai\" >authortime &&\n> +       git log -1 --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with merge backend' '\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +       git rebase -m --committer-date-is-author-date HEAD^ &&\n> +       git log -1 --pretty=\"format:%ai\" >authortime &&\n> +       git log -1 --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n> +       git checkout side &&\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +       git rebase -r --root --committer-date-is-author-date &&\n> +       git log --pretty=\"format:%ai\" >authortime &&\n> +       git log --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n> +       git checkout side &&\n> +       GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +       git rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n> +       git log --pretty=\"format:%ai\" >authortime &&\n> +       git log --pretty=\"format:%ci\" >committertime &&\n> +       test_cmp authortime committertime\n> +\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n> +       git checkout commit2 &&\n> +       GIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n> +       git log -1 --format=%at HEAD >expect &&\n> +       test_must_fail git rebase -m --committer-date-is-author-date \\\n> +               --onto HEAD^^ HEAD^ &&\n> +       echo resolved > foo &&\n> +       git add foo &&\n> +       git rebase --continue &&\n> +       git log -1 --format=%ct HEAD >actual &&\n> +       test_cmp expect actual\n> +'\n> +\n>  # This must be the last test in this file\n>  test_expect_success '$EDITOR and friends are unchanged' '\n>         test_editor_unchanged\n> --\n> 2.26.2\n\nDoes this implementation rely on the run_git_commit() path, i.e. is it\nanother place we'll need to fix up to avoid forking a subprocess, or\ndoes it work with the try_to_commit() codepath as well?\n"},{"id":"397715","messageId":"xmqq1rnnx31c.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com","subject":"Re: [PATCH v2 4/5] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-05-13T15:33:51Z","receivedAt":"2020-05-13T15:33:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>>> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n>>>     \tif (opts->committer_date_is_author_date)\n>>>   \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>>> +\t\t\t\t opts->ignore_date ?\n>>> +\t\t\t\t \"\" :\n>>>   \t\t\t\t author_date_from_env_array(&cmd.env_array));\n>>> +\tif (opts->ignore_date)\n>>> +\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>>>   \n>>\n>> Perhaps this could be done in read_env_script(), too, instead of fixing\n>> up what this function did right after calling it, twice?  Something like\n>> this:\n>\n> Long term I'd like to stop writing the author-script file unless we're\n> stopping for a conflict resolution or edit so I'm reluctant to add\n> more functionality to it at the moment. Also I tend to view\n> read_env_script() it as loading the author details from a file rather\n> than setting up the environment for the commit.\n\nYeah, the author-script, once the program halts and returns the\ncontrol to the human-user sitting on the terminal, can be peeked at,\nand it should record what the program learned from the commit; it\nsmells like a premature optimization to rewrite it to what the\nprogram plans to use to replay the commit and lose the information\ntaken from the original.\n"},{"id":"397803","messageId":"c3dad0e2-e381-499a-af02-ef3f49207c49@gmail.com","threadId":"53176","inReplyTo":"CABPp-BG+nWR9S9fw=_0XV8GA5JRAKaL2TZUU578PQkW8f_z7ew@mail.gmail.com","subject":"Re: [PATCH v2 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-14T09:47:47Z","receivedAt":"2020-05-14T09:47:52Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/05/2020 04:54, Elijah Newren wrote:\n> Sorry for taking so long to get back to you, and thanks for pushing\n> this forward.\n\nThanks for taking a look at this series\n\n> \n> On Wed, Apr 29, 2020 at 3:26 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>>\n>> Rebase is implemented with two different backends - 'apply' and 'merge'\n>> each of which support a different set of options. In particuar the apply\n>> backend supports a number of options implemented by 'git am' that are\n>> not available to the merge backend. As part of an on going effort to\n>> remove the apply backend this patch adds support for the\n>> --ignore-whitespace option to the merge backend. This option treats\n>> lines with only whitespace changes as unchanged and is implemented in\n>> the merge backend by translating it to -Xignore-space-change.\n>>\n>> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> [...]\n\n>> ---\n>>  Documentation/git-rebase.txt           | 12 +++-\n>>  builtin/rebase.c                       | 19 ++++--\n>>  t/t3422-rebase-incompatible-options.sh |  1 -\n>>  t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++\n>>  4 files changed, 111 insertions(+), 7 deletions(-)\n>>  create mode 100755 t/t3436-rebase-more-options.sh\n>>\n>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n>> index f7a6033607..d060c143e6 100644\n>> --- a/Documentation/git-rebase.txt\n>> +++ b/Documentation/git-rebase.txt\n>> @@ -422,8 +422,16 @@ your branch contains commits which were dropped, this option can be used\n>>  with `--keep-base` in order to drop those commits from your branch.\n>>\n>>  --ignore-whitespace::\n>> +       Behaves differently depending on which backend is selected.\n> \n> I still don't like this wording; it defers answering the question,\n> implies that the difference is intentional, and most importantly\n> provides no context about *intended* behavior.  I tried to communicate\n> this to Rohit multiple times, but he seemed to fixate on and highlight\n> the differences in a way that made them sound like they were by\n> design, rather than highlighting the intent we want to move towards\n> and mentioning that this patch gets us most the way there.\n> \n> As far as I can tell, the --ignore-whitespace and\n> -Xignore-space-change were always meant to do the same thing: ignore\n> differences in whitespace when doing so can avoid conflicts.\n> \n> In case anyone isn't sure about my assertion that these were always\n> meant to do the same thing:\n>   * apply aliases --ignore-whitespace and --ignore-space-change; they\n> meant the same thing\n>   * commit f008cef4ab (\"Merge branch 'jc/apply-ignore-whitespace'\",\n> 2014-06-03) says that apply's --ignore-space-change wasn't behaving\n> consistently with diff's --ignore-space-change\n>   * diff's --ignore-space-change goes through xdiff's XDL opts, much\n> like merge-recursive does.\n> Further, the original commit that introduced these xdiff options to\n> merge-recursive, 4e5dd044c6 (\"merge-recursive: options to ignore\n> whitespace changes\", 2010-08-26), it is clear that:\n>   * he only cared about ignore-space-at-eol and implemented\n> ignore-space-change at the same time only for completeness\n>   * it wouldn't matter to his usecase if whitespace-only changes were\n> stripped, thus he wouldn't have spotted the bug it has\n>   * the wording also suggests these options were picked to match\n> options of the same name elsewhere in git\n> \n> I would rather we said something like:\n>     Ignore whitespace differences when trying to reconcile\n> differences.  Currently, each backend implements an approximation of\n> this behavior:\n> \n>> ++\n>> +apply backend: When applying a patch, ignore changes in whitespace in\n>> +context lines.\n> \n> Maybe add something like:\n>     (Unfortunately, this means that if the \"old\" lines being replaced\n> by the patch differ only in whitespace from the existing file, you\n> will get a merge conflict instead of a successful patch application.)\n> \n>> ++\n>> +merge backend: Treat lines with only whitespace changes as unchanged\n>> +when merging.\n> \n> Maybe add something like:\n>    (Unfortunately, this means that any patch hunks that were intended\n> to modify whitespace and nothing else will be dropped, even if the\n> other side had no changes that conflicted.)\n\nThanks for the suggestions, I'll incorporate them into the re-roll.\n\nBest Wishes\n\nPhillip\n\n>> +\n>>  --whitespace=<option>::\n>> -       These flags are passed to the 'git apply' program\n>> +       This flag is passed to the 'git apply' program\n>>         (see linkgit:git-apply[1]) that applies the patch.\n>>         Implies --apply.\n>>  +\n>> @@ -572,7 +580,6 @@ The following options:\n>>   * --apply\n>>   * --committer-date-is-author-date\n>>   * --ignore-date\n>> - * --ignore-whitespace\n>>   * --whitespace\n>>   * -C\n>>\n>> @@ -598,6 +605,7 @@ In addition, the following pairs of options are incompatible:\n>>   * --preserve-merges and --signoff\n>>   * --preserve-merges and --rebase-merges\n>>   * --preserve-merges and --empty=\n>> + * --preserve-merges and --ignore-whitespace\n>>   * --keep-base and --onto\n>>   * --keep-base and --root\n>>\n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index 27a07d4e78..5d8e117276 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -86,6 +86,7 @@ struct rebase_options {\n>>         int signoff;\n>>         int allow_rerere_autoupdate;\n>>         int autosquash;\n>> +       int ignore_whitespace;\n>>         char *gpg_sign_opt;\n>>         int autostash;\n>>         char *cmd;\n>> @@ -108,6 +109,7 @@ struct rebase_options {\n>>\n>>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>  {\n>> +       struct strbuf strategy_buf = STRBUF_INIT;\n>>         struct replay_opts replay = REPLAY_OPTS_INIT;\n>>\n>>         replay.action = REPLAY_INTERACTIVE_REBASE;\n>> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>         replay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>>         replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>>         replay.strategy = opts->strategy;\n>> +\n>>         if (opts->strategy_opts)\n>> -               parse_strategy_opts(&replay, opts->strategy_opts);\n>> +               strbuf_addstr(&strategy_buf, opts->strategy_opts);\n>> +       if (opts->ignore_whitespace)\n>> +               strbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n>> +       if (strategy_buf.len)\n>> +               parse_strategy_opts(&replay, strategy_buf.buf);\n>>\n>>         if (opts->squash_onto) {\n>>                 oidcpy(&replay.squash_onto, opts->squash_onto);\n>>                 replay.have_squash_onto = 1;\n>>         }\n>>\n>> +       strbuf_release(&strategy_buf);\n>>         return replay;\n>>  }\n>>\n>> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>>         argc = parse_options(argc, argv, prefix, options,\n>>                         builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n>>\n>> +       opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n>> +\n>>         if (!is_null_oid(&squash_onto))\n>>                 opts.squash_onto = &squash_onto;\n>>\n>> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)\n>>         am.git_cmd = 1;\n>>         argv_array_push(&am.args, \"am\");\n>>\n>> +       if (opts->ignore_whitespace)\n>> +               argv_array_push(&am.args, \"--ignore-whitespace\");\n>>         if (opts->action && !strcmp(\"continue\", opts->action)) {\n>>                 argv_array_push(&am.args, \"--resolved\");\n>>                 argv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n>> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>                         PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>>                 OPT_BOOL(0, \"signoff\", &options.signoff,\n>>                          N_(\"add a Signed-off-by: line to each commit\")),\n>> -               OPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n>> -                                 NULL, N_(\"passed to 'git am'\"),\n>> -                                 PARSE_OPT_NOARG),\n>>                 OPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>>                                   &options.git_am_opts, NULL,\n>>                                   N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>>                 OPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>>                                   N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>>                 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>>                                   N_(\"passed to 'git apply'\"), 0),\n>> +               OPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n>> +                        N_(\"ignore changes in whitespace\")),\n>>                 OPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>>                                   N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>>                 OPT_BIT('f', \"force-rebase\", &options.flags,\n>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>> index 50e7960702..55ca46786d 100755\n>> --- a/t/t3422-rebase-incompatible-options.sh\n>> +++ b/t/t3422-rebase-incompatible-options.sh\n>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>  }\n>>\n>>  test_rebase_am_only --whitespace=fix\n>> -test_rebase_am_only --ignore-whitespace\n>>  test_rebase_am_only --committer-date-is-author-date\n>>  test_rebase_am_only -C4\n>>\n>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>> new file mode 100755\n>> index 0000000000..fb5e747e86\n>> --- /dev/null\n>> +++ b/t/t3436-rebase-more-options.sh\n>> @@ -0,0 +1,86 @@\n>> +#!/bin/sh\n>> +#\n>> +# Copyright (c) 2019 Rohit Ashiwal\n>> +#\n>> +\n>> +test_description='tests to ensure compatibility between am and interactive backends'\n>> +\n>> +. ./test-lib.sh\n>> +\n>> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n>> +\n>> +# This is a special case in which both am and interactive backends\n>> +# provide the same output. It was done intentionally because\n>> +# both the backends fall short of optimal behaviour.\n>> +test_expect_success 'setup' '\n>> +       git checkout -b topic &&\n>> +       q_to_tab >file <<-\\EOF &&\n>> +       line 1\n>> +       Qline 2\n>> +       line 3\n>> +       EOF\n>> +       git add file &&\n>> +       git commit -m \"add file\" &&\n>> +       cat >file <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       git commit -am \"update file\" &&\n>> +       git tag side &&\n>> +\n>> +       git checkout --orphan master &&\n>> +       sed -e \"s/^|//\" >file <<-\\EOF &&\n>> +       |line 1\n>> +       |        line 2\n>> +       |line 3\n>> +       EOF\n>> +       git add file &&\n>> +       git commit -m \"add file\" &&\n>> +       git tag main\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace works with apply backend' '\n>> +       cat >expect <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       test_must_fail git rebase --apply main side &&\n>> +       git rebase --abort &&\n>> +       git rebase --apply --ignore-whitespace main side &&\n>> +       test_cmp expect file\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace works with merge backend' '\n>> +       cat >expect <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       test_must_fail git rebase --merge main side &&\n>> +       git rebase --abort &&\n>> +       git rebase --merge --ignore-whitespace main side &&\n>> +       test_cmp expect file\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n>> +       cat >expect <<-\\EOF &&\n>> +       line 1\n>> +       new line 2\n>> +       line 3\n>> +       EOF\n>> +       (\n>> +               set_fake_editor &&\n>> +               FAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n>> +       ) &&\n>> +       git rebase --continue &&\n>> +       test_cmp expect file\n>> +'\n>> +\n>> +# This must be the last test in this file\n>> +test_expect_success '$EDITOR and friends are unchanged' '\n>> +       test_editor_unchanged\n>> +'\n>> +\n>> +test_done\n>> --\n>> 2.26.2\n> \n> The rest looks good to me.\n> \n\n"},{"id":"398341","messageId":"20200521101455.63484-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH v3 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-21T10:14:50Z","receivedAt":"2020-05-21T10:15:20Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThanks for the feedback on v2, I've updated the documentation as\nsuggested by Elijah and made the style fixes suggested by Alban but\nI've not changed read_author_script() for the reasons explained in\nhttps://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com\n\nThese patches are based on 9fadedd637 (\"Merge branch\n'ds/default-pack-use-sparse-to-true'\", 2020-03-29)\n\nPhillip Wood (2):\n  rebase -i: support --committer-date-is-author-date\n  rebase -i: support --ignore-date\n\nRohit Ashiwal (3):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: rename amend_author to author_to_free\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt           |  33 +++-\n builtin/rebase.c                       |  46 ++++--\n sequencer.c                            | 111 ++++++++++++-\n sequencer.h                            |   2 +\n t/t3422-rebase-incompatible-options.sh |   2 -\n t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++\n 6 files changed, 379 insertions(+), 24 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\nRange-diff against v2:\n1:  5ef315240a ! 1:  df8c4ed2e9 rebase -i: add --ignore-whitespace flag\n    @@ Documentation/git-rebase.txt: your branch contains commits which were dropped, t\n      with `--keep-base` in order to drop those commits from your branch.\n      \n      --ignore-whitespace::\n    -+\tBehaves differently depending on which backend is selected.\n    ++\tIgnore whitespace differences when trying to reconcile\n    ++differences. Currently, each backend implements an approximation of\n    ++this behavior:\n     ++\n     +apply backend: When applying a patch, ignore changes in whitespace in\n    -+context lines.\n    ++context lines. Unfortunately, this means that if the \"old\" lines being\n    ++replaced by the patch differ only in whitespace from the existing\n    ++file, you will get a merge conflict instead of a successful patch\n    ++application.\n     ++\n     +merge backend: Treat lines with only whitespace changes as unchanged\n    -+when merging.\n    ++when merging. Unfortunately, this means that any patch hunks that were\n    ++intended to modify whitespace and nothing else will be dropped, even\n    ++if the other side had no changes that conflicted.\n     +\n      --whitespace=<option>::\n     -\tThese flags are passed to the 'git apply' program\n2:  55eb3a7efc ! 2:  df44a0bde6 rebase -i: support --committer-date-is-author-date\n    @@ Commit message\n         Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n     \n      ## Documentation/git-rebase.txt ##\n    -@@ Documentation/git-rebase.txt: when merging.\n    +@@ Documentation/git-rebase.txt: if the other side had no changes that conflicted.\n      See also INCOMPATIBLE OPTIONS below.\n      \n      --committer-date-is-author-date::\n    @@ sequencer.c: static int run_git_commit(struct repository *r,\n      \n      \tif (!(flags & VERIFY_MSG))\n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n    - \n    - \tif (parse_head(r, &current_head))\n    - \t\treturn -1;\n    --\n    - \tif (flags & AMEND_MSG) {\n    - \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n    - \t\tconst char *out_enc = get_commit_output_encoding();\n    -@@ sequencer.c: static int try_to_commit(struct repository *r,\n      \t\tcommit_list_insert(current_head, &parents);\n      \t}\n      \n3:  19352fdc22 = 3:  fa3d4856b4 sequencer: rename amend_author to author_to_free\n4:  5e971abb74 ! 4:  96657233d4 rebase -i: support --ignore-date\n    @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr\n     +\t\terror(_(\"malformed ident line '%s'\"), author);\n     +\t\treturn NULL;\n     +\t}\n    ++\n     +\tlen = ident.mail_end - ident.name_begin + 1;\n    -+\n     +\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n     +\tdatestamp(&new_author);\n     +\treturn strbuf_detach(&new_author, NULL);\n    @@ sequencer.c: static int try_to_commit(struct repository *r,\n     +\t\tfree(author_to_free);\n     +\t\tauthor_to_free = (char *)author;\n     +\t}\n    ++\n      \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n      \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n      \t\tres = error(_(\"failed to write commit object\"));\n5:  43a097c583 = 5:  828155baba rebase: add --reset-author-date\n\n-- \n2.26.2\n"},{"id":"398342","messageId":"20200521101455.63484-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200521101455.63484-1-phillip.wood123@gmail.com","subject":"[PATCH v3 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-21T10:14:51Z","receivedAt":"2020-05-21T10:15:24Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nRebase is implemented with two different backends - 'apply' and 'merge'\neach of which support a different set of options. In particuar the apply\nbackend supports a number of options implemented by 'git am' that are\nnot available to the merge backend. As part of an on going effort to\nremove the apply backend this patch adds support for the\n--ignore-whitespace option to the merge backend. This option treats\nlines with only whitespace changes as unchanged and is implemented in\nthe merge backend by translating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 19 +++++-\n builtin/rebase.c                       | 19 ++++--\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++\n 4 files changed, 118 insertions(+), 7 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f7a6033607..b003784f01 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tIgnore whitespace differences when trying to reconcile\n+differences. Currently, each backend implements an approximation of\n+this behavior:\n++\n+apply backend: When applying a patch, ignore changes in whitespace in\n+context lines. Unfortunately, this means that if the \"old\" lines being\n+replaced by the patch differ only in whitespace from the existing\n+file, you will get a merge conflict instead of a successful patch\n+application.\n++\n+merge backend: Treat lines with only whitespace changes as unchanged\n+when merging. Unfortunately, this means that any patch hunks that were\n+intended to modify whitespace and nothing else will be dropped, even\n+if the other side had no changes that conflicted.\n+\n --whitespace=<option>::\n-\tThese flags are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n \tImplies --apply.\n +\n@@ -572,7 +587,6 @@ The following options:\n  * --apply\n  * --committer-date-is-author-date\n  * --ignore-date\n- * --ignore-whitespace\n  * --whitespace\n  * -C\n \n@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n+ * --preserve-merges and --ignore-whitespace\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 27a07d4e78..5d8e117276 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -86,6 +86,7 @@ struct rebase_options {\n \tint signoff;\n \tint allow_rerere_autoupdate;\n \tint autosquash;\n+\tint ignore_whitespace;\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tchar *cmd;\n@@ -108,6 +109,7 @@ struct rebase_options {\n \n static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n {\n+\tstruct strbuf strategy_buf = STRBUF_INIT;\n \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n \n \treplay.action = REPLAY_INTERACTIVE_REBASE;\n@@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n-\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n+\t\tstrbuf_addstr(&strategy_buf, opts->strategy_opts);\n+\tif (opts->ignore_whitespace)\n+\t\tstrbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n+\tif (strategy_buf.len)\n+\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n \n \tif (opts->squash_onto) {\n \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n \t\treplay.have_squash_onto = 1;\n \t}\n \n+\tstrbuf_release(&strategy_buf);\n \treturn replay;\n }\n \n@@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n \n+\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n+\n \tif (!is_null_oid(&squash_onto))\n \t\topts.squash_onto = &squash_onto;\n \n@@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)\n \tam.git_cmd = 1;\n \targv_array_push(&am.args, \"am\");\n \n+\tif (opts->ignore_whitespace)\n+\t\targv_array_push(&am.args, \"--ignore-whitespace\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..55ca46786d 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nnew file mode 100755\nindex 0000000000..fb5e747e86\n--- /dev/null\n+++ b/t/t3436-rebase-more-options.sh\n@@ -0,0 +1,86 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\tq_to_tab >file <<-\\EOF &&\n+\tline 1\n+\tQline 2\n+\tline 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tcat >file <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\n+\tgit checkout --orphan master &&\n+\tsed -e \"s/^|//\" >file <<-\\EOF &&\n+\t|line 1\n+\t|        line 2\n+\t|line 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with apply backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase --apply main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --apply --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--ignore-whitespace works with merge backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n+\t) &&\n+\tgit rebase --continue &&\n+\ttest_cmp expect file\n+'\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n+test_done\n-- \n2.26.2\n\n"},{"id":"398343","messageId":"20200521101455.63484-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200521101455.63484-1-phillip.wood123@gmail.com","subject":"[PATCH v3 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-21T10:14:52Z","receivedAt":"2020-05-21T10:15:24Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nAs part of the on-going effort to retire the apply rebase backend teach\nthe merge backend how to handle --committer-date-is-author-date.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 10 +++--\n builtin/rebase.c                       | 16 ++++---\n sequencer.c                            | 59 +++++++++++++++++++++++++-\n sequencer.h                            |  1 +\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++\n 6 files changed, 133 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex b003784f01..dfa70263e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of using the current time as the committer date, use\n+\tthe author date of the commit being rebased as the committer\n+\tdate. This option implies --force-rebase.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tThis flag is passed to 'git am' to change the author date\n+\tof each rebased commit (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 5d8e117276..357cd6acf3 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -89,6 +89,7 @@ struct rebase_options {\n \tint ignore_whitespace;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)\n \n \tif (opts->ignore_whitespace)\n \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n@@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n+\tif (options.committer_date_is_author_date)\n+\t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n+\t\tif (!strcmp(option, \"--ignore-date\") ||\n \t\t    !strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\ndiff --git a/sequencer.c b/sequencer.c\nindex 6fd2674632..8826c6325b 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -872,6 +873,22 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+static const char *author_date_from_env_array(const struct argv_array *env)\n+{\n+\tint i;\n+\tconst char *date;\n+\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n \n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \targv_array_push(&cmd.args, \"commit\");\n \n \tif (!(flags & VERIFY_MSG))\n@@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,\n \t\tcommit_list_insert(current_head, &parents);\n \t}\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tint len = strlen(author);\n+\t\tstruct ident_split ident;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!ident.date_begin) {\n+\t\t\tres = error(_(\"corrupted author without date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n+\t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&date);\n+\n+\t\tif (res)\n+\t\t\tgoto out;\n+\t}\n+\n \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n \t\tres = error(_(\"git write-tree failed to write a tree\"));\n \t\tgoto out;\n@@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n \tif (opts->keep_redundant_commits)\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,\n \t\t\tgoto leave_merge;\n \t\t}\n \n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n \t\targv_array_push(&cmd.args, \"-s\");\n@@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t\topts->record_origin || opts->edit ||\n+\t\t\t\topts->committer_date_is_author_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 0bee85093e..4ab94119ae 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -45,6 +45,7 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n \n \tint mainline;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 55ca46786d..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex fb5e747e86..84b9d5d37f 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n # This is a special case in which both am and interactive backends\n # provide the same output. It was done intentionally because\n # both the backends fall short of optimal behaviour.\n@@ -28,8 +31,13 @@ test_expect_success 'setup' '\n \tEOF\n \tgit commit -am \"update file\" &&\n \tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n \n \tgit checkout --orphan master &&\n+\tgit rm --cached foo &&\n+\trm foo &&\n \tsed -e \"s/^|//\" >file <<-\\EOF &&\n \t|line 1\n \t|        line 2\n@@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n \ttest_cmp expect file\n '\n \n+test_expect_success '--committer-date-is-author-date works with apply backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with merge backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\tgit log --pretty=\"format:%ai\" >authortime &&\n+\tgit log --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n+\tgit log --pretty=\"format:%ai\" >authortime &&\n+\tgit log --pretty=\"format:%ci\" >committertime &&\n+\ttest_cmp authortime committertime\n+\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\tgit log -1 --format=%at HEAD >expect &&\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -1 --format=%ct HEAD >actual &&\n+\ttest_cmp expect actual\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"398344","messageId":"20200521101455.63484-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200521101455.63484-1-phillip.wood123@gmail.com","subject":"[PATCH v3 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-21T10:14:55Z","receivedAt":"2020-05-21T10:15:27Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe previous commit introduced --ignore-date flag to rebase -i, but the\nname is rather vague as it does not say whether the author date or the\ncommitter date is ignored. Add an alias to convey the precise purpose.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt   |  1 +\n builtin/rebase.c               |  6 ++++--\n t/t3436-rebase-more-options.sh | 34 ++++++++++++++++++++++------------\n 3 files changed, 27 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e2717e20e6..a5f82913fb 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the author date of the original commit, use\n \tthe current time as the\tauthor date of the rebased commit.  This\n \toption implies `--force-rebase`.\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex cf86240bc8..911587690b 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1519,8 +1519,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n-\t\t\t \"ignore author date and use current date\"),\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 6cd3848689..2ee7346562 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -137,22 +137,22 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n # Checking for +0000 in author time is enough since default\n # timezone is UTC, but the timezone used while committing\n # sets to +0530.\n-test_expect_success '--ignore-date works with apply backend' '\n+test_expect_success '--reset-author-date works with apply backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit rebase --apply --reset-author-date HEAD^ &&\n \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date works with merge backend' '\n+test_expect_success '--reset-author-date works with merge backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit rebase --reset-author-date -m HEAD^ &&\n \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date works after conflict resolution' '\n-\ttest_must_fail git rebase --ignore-date -m \\\n+test_expect_success '--reset-author-date works after conflict resolution' '\n+\ttest_must_fail git rebase --reset-author-date -m \\\n \t\t--onto commit2^^ commit2^ commit2 &&\n \techo resolved >foo &&\n \tgit add foo &&\n@@ -161,17 +161,17 @@ test_expect_success '--ignore-date works after conflict resolution' '\n \tgrep +0000 authortime\n '\n \n-test_expect_success '--ignore-date works with rebase -r' '\n+test_expect_success '--reset-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n-\tgit rebase -r --root --ignore-date &&\n+\tgit rebase -r --root --reset-author-date &&\n \tgit log --pretty=%ai >authortime &&\n \t! grep -v \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '\n \ttest_must_fail git rebase -m --committer-date-is-author-date \\\n-\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\t\t--reset-author-date --onto commit2^^ commit2^ commit3 &&\n \tgit checkout --theirs foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n@@ -181,16 +181,26 @@ test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n \t! grep -v \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n-\t\tgit rebase -i --strategy=resolve --ignore-date \\\n+\t\tgit rebase -i --strategy=resolve --reset-author-date \\\n \t\t--committer-date-is-author-date side side &&\n \tgit log -1 --pretty=%ai >authortime &&\n \tgit log -1 --pretty=%ci >committertime &&\n \ttest_cmp authortime committertime &&\n \tgrep \"+0000\" authortime\n  '\n \n+test_expect_success '--ignore-date is an alias for --reset-author-date' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase -m --ignore-date HEAD^ &&\n+\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime >output &&\n+\ttest_line_count = 2 output\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"398345","messageId":"20200521101455.63484-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200521101455.63484-1-phillip.wood123@gmail.com","subject":"[PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-21T10:14:54Z","receivedAt":"2020-05-21T10:15:27Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nAs part of the on-going effort to retire the apply rebase backend\nteach the merge backend how to handle --ignore-date. We take care to\nhandle the combination of --ignore-date and\n--committer-date-is-author-date in the same way as the apply backend.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt   |  7 +++--\n builtin/rebase.c               | 13 +++++---\n sequencer.c                    | 50 +++++++++++++++++++++++++++--\n sequencer.h                    |  1 +\n t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++\n 5 files changed, 118 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex dfa70263e6..e2717e20e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof each rebased commit (see linkgit:git-am[1]).\n+\tInstead of using the author date of the original commit, use\n+\tthe current time as the\tauthor date of the rebased commit.  This\n+\toption implies `--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n  * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 357cd6acf3..cf86240bc8 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -90,6 +90,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.committer_date_is_author_date =\n \t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)\n \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n \tif (opts->committer_date_is_author_date)\n \t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--ignore-date\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current date\"),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n@@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n-\tif (options.committer_date_is_author_date)\n+\tif (options.committer_date_is_author_date || options.ignore_date)\n \t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 44e0b45e53..a21364c3be 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n }\n \n+/* Construct a free()able author string with current time as the author date */\n+static char *ignore_author_date(const char *author)\n+{\n+\tint len = strlen(author);\n+\tstruct ident_split ident;\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\n+\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\terror(_(\"malformed ident line '%s'\"), author);\n+\t\treturn NULL;\n+\t}\n+\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n \n \tif (opts->committer_date_is_author_date)\n \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n \t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1387,7 +1410,8 @@ static int try_to_commit(struct repository *r,\n \t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n \t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n \t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n-\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n \t\tstrbuf_release(&date);\n \n \t\tif (res)\n@@ -1453,6 +1477,16 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tauthor = ignore_author_date(author);\n+\t\tif (!author) {\n+\t\t\tres = -1;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tfree(author_to_free);\n+\t\tauthor_to_free = (char *)author;\n+\t}\n+\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -2582,6 +2616,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->committer_date_is_author_date = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2674,6 +2713,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n \tif (opts->committer_date_is_author_date)\n \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3596,7 +3637,11 @@ static int do_merge(struct repository *r,\n \n \t\tif (opts->committer_date_is_author_date)\n \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3876,7 +3921,8 @@ static int pick_commits(struct repository *r,\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n \t\t\t\topts->record_origin || opts->edit ||\n-\t\t\t\topts->committer_date_is_author_date));\n+\t\t\t\topts->committer_date_is_author_date ||\n+\t\t\t\topts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 4ab94119ae..3587878e3b 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -46,6 +46,7 @@ struct replay_opts {\n \tint quiet;\n \tint reschedule_failed_exec;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 84b9d5d37f..6cd3848689 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n \ttest_cmp expect actual\n '\n \n+# Checking for +0000 in author time is enough since default\n+# timezone is UTC, but the timezone used while committing\n+# sets to +0530.\n+test_expect_success '--ignore-date works with apply backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works with merge backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -m \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log --pretty=%ai >authortime &&\n+\tgrep +0000 authortime\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\tgit log --pretty=%ai >authortime &&\n+\t! grep -v \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -2 --pretty=%ai >authortime &&\n+\tgit log -2 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\t! grep -v \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tgit rebase -i --strategy=resolve --ignore-date \\\n+\t\t--committer-date-is-author-date side side &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgit log -1 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\tgrep \"+0000\" authortime\n+ '\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"398346","messageId":"20200521101455.63484-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200521101455.63484-1-phillip.wood123@gmail.com","subject":"[PATCH v3 3/5] sequencer: rename amend_author to author_to_free","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-21T10:14:53Z","receivedAt":"2020-05-21T10:15:28Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() when amending a commit. But we can\nalso use the variable to free() the author at our convenience.\nRename it to convey this meaning.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 8826c6325b..44e0b45e53 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n-\tchar *amend_author = NULL;\n+\tchar *author_to_free = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tstrbuf_addstr(msg, orig_message);\n \t\t\thook_commit = \"HEAD\";\n \t\t}\n-\t\tauthor = amend_author = get_author(message);\n+\t\tauthor = author_to_free = get_author(message);\n \t\tunuse_commit_buffer(current_head, message);\n \t\tif (!author) {\n \t\t\tres = error(_(\"unable to parse commit author\"));\n@@ -1473,7 +1473,7 @@ static int try_to_commit(struct repository *r,\n \tfree_commit_extra_headers(extra);\n \tstrbuf_release(&err);\n \tstrbuf_release(&commit_msg);\n-\tfree(amend_author);\n+\tfree(author_to_free);\n \n \treturn res;\n }\n-- \n2.26.2\n\n"},{"id":"398429","messageId":"CABPp-BFaexpFo-n-vPxZ2e4dF9aT45NXK8rnmJ6gi+qvLN+P+Q@mail.gmail.com","threadId":"53176","inReplyTo":"20200521101455.63484-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v3 0/5] cleanup ra/rebase-i-more-options","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2020-05-22T15:54:43Z","receivedAt":"2020-05-22T15:54:57Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Thu, May 21, 2020 at 3:15 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> Thanks for the feedback on v2, I've updated the documentation as\n> suggested by Elijah and made the style fixes suggested by Alban but\n> I've not changed read_author_script() for the reasons explained in\n> https://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com\n\nAll my questions were answered earlier; this round addressed my\nremaining feedback and I see no new issues.\n\nReviewed-by: Elijah Newren <newren@gmail.com>\n"},{"id":"398450","messageId":"7bf6d78c-89b1-48c2-aeba-e674058be23e@gmail.com","threadId":"53176","inReplyTo":"CABPp-BFaexpFo-n-vPxZ2e4dF9aT45NXK8rnmJ6gi+qvLN+P+Q@mail.gmail.com","subject":"Re: [PATCH v3 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-23T08:55:29Z","receivedAt":"2020-05-23T08:55:35Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 22/05/2020 16:54, Elijah Newren wrote:\n> On Thu, May 21, 2020 at 3:15 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> Thanks for the feedback on v2, I've updated the documentation as\n>> suggested by Elijah and made the style fixes suggested by Alban but\n>> I've not changed read_author_script() for the reasons explained in\n>> https://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com\n> \n> All my questions were answered earlier; this round addressed my\n> remaining feedback and I see no new issues.\n> \n> Reviewed-by: Elijah Newren <newren@gmail.com>\n\nThanks Elijah\n"},{"id":"398452","messageId":"20200523123025.GA20683@danh.dev","threadId":"53176","inReplyTo":"20200521101455.63484-5-phillip.wood123@gmail.com","subject":"Re: [PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-05-23T12:30:25Z","receivedAt":"2020-05-23T12:30:31Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"Hi Phillip,\n\nOn 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> +# Checking for +0000 in author time is enough since default\n> +# timezone is UTC, but the timezone used while committing\n> +# sets to +0530.\n> +test_expect_success '--ignore-date works with apply backend' '\n> +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +\tgit rebase --apply --ignore-date HEAD^ &&\n> +\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n\nThose --pretty=\"format:%ai\" won't print the newline character in my\ntest environment.\nIt looks like it won't print the newline if stdout isn't a tty.\n\n\tgit log -1 --pretty=%ai\n\ndoesn't have that issue.\n\nI think there're some grep out there considers file doesn't end with\nnewline as non-text files.\n\n> +\tgrep \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date works with merge backend' '\n> +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +\tgit rebase --ignore-date -m HEAD^ &&\n> +\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n> +\tgrep \"+0000\" authortime\n> +'\n> +\n> +test_expect_success '--ignore-date works after conflict resolution' '\n> +\ttest_must_fail git rebase --ignore-date -m \\\n> +\t\t--onto commit2^^ commit2^ commit2 &&\n> +\techo resolved >foo &&\n> +\tgit add foo &&\n> +\tgit rebase --continue &&\n> +\tgit log --pretty=%ai >authortime &&\n> +\tgrep +0000 authortime\n> +'\n\nFrom the test's name, I guess git-rebase is supposed to continue\nrespect --ignore-date after conflict resolution.\n\nBut the content of authortime read:\n\n\t2020-05-23 12:13:58 +0000\n\t1999-04-02 08:03:20 +0530\n\t1999-04-02 08:03:20 +0530\n\nIt's still pass \"grep +0000 authortime\" because of first line,\nI'm not sure if I missed anything.\n\n\n-- \nDanh\n"},{"id":"398453","messageId":"nycvar.QRO.7.76.6.2005230857120.56@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"20200521101455.63484-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v3 0/5] cleanup ra/rebase-i-more-options","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-05-23T06:59:31Z","receivedAt":"2020-05-23T14:17:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Thu, 21 May 2020, Phillip Wood wrote:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> Thanks for the feedback on v2, I've updated the documentation as\n> suggested by Elijah and made the style fixes suggested by Alban but\n> I've not changed read_author_script() for the reasons explained in\n> https://lore.kernel.org/git/c6a2711a-96c1-d7ac-9678-20c581408ef5@gmail.com\n>\n> These patches are based on 9fadedd637 (\"Merge branch\n> 'ds/default-pack-use-sparse-to-true'\", 2020-03-29)\n\nThank you for working on these patches! TBH what I was looking to most in\nthat GSoC project was the ability to combine `--interactive` with Sverre's\n`--whitespace=fix` option, but it never came even close to that. So I had\nplanned to help this patch series as much as I can.\n\nTurns out that I do not really have any time to help this patch series,\ntherefore I am very happy to see Danh and Elijah jump in and review the\npatch series, and that makes me think that between the three of you, it is\nin good hands now.\n\nThanks,\nDscho\n\n>\n> Phillip Wood (2):\n>   rebase -i: support --committer-date-is-author-date\n>   rebase -i: support --ignore-date\n>\n> Rohit Ashiwal (3):\n>   rebase -i: add --ignore-whitespace flag\n>   sequencer: rename amend_author to author_to_free\n>   rebase: add --reset-author-date\n>\n>  Documentation/git-rebase.txt           |  33 +++-\n>  builtin/rebase.c                       |  46 ++++--\n>  sequencer.c                            | 111 ++++++++++++-\n>  sequencer.h                            |   2 +\n>  t/t3422-rebase-incompatible-options.sh |   2 -\n>  t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++\n>  6 files changed, 379 insertions(+), 24 deletions(-)\n>  create mode 100755 t/t3436-rebase-more-options.sh\n>\n> Range-diff against v2:\n> 1:  5ef315240a ! 1:  df8c4ed2e9 rebase -i: add --ignore-whitespace flag\n>     @@ Documentation/git-rebase.txt: your branch contains commits which were dropped, t\n>       with `--keep-base` in order to drop those commits from your branch.\n>\n>       --ignore-whitespace::\n>     -+\tBehaves differently depending on which backend is selected.\n>     ++\tIgnore whitespace differences when trying to reconcile\n>     ++differences. Currently, each backend implements an approximation of\n>     ++this behavior:\n>      ++\n>      +apply backend: When applying a patch, ignore changes in whitespace in\n>     -+context lines.\n>     ++context lines. Unfortunately, this means that if the \"old\" lines being\n>     ++replaced by the patch differ only in whitespace from the existing\n>     ++file, you will get a merge conflict instead of a successful patch\n>     ++application.\n>      ++\n>      +merge backend: Treat lines with only whitespace changes as unchanged\n>     -+when merging.\n>     ++when merging. Unfortunately, this means that any patch hunks that were\n>     ++intended to modify whitespace and nothing else will be dropped, even\n>     ++if the other side had no changes that conflicted.\n>      +\n>       --whitespace=<option>::\n>      -\tThese flags are passed to the 'git apply' program\n> 2:  55eb3a7efc ! 2:  df44a0bde6 rebase -i: support --committer-date-is-author-date\n>     @@ Commit message\n>          Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n>       ## Documentation/git-rebase.txt ##\n>     -@@ Documentation/git-rebase.txt: when merging.\n>     +@@ Documentation/git-rebase.txt: if the other side had no changes that conflicted.\n>       See also INCOMPATIBLE OPTIONS below.\n>\n>       --committer-date-is-author-date::\n>     @@ sequencer.c: static int run_git_commit(struct repository *r,\n>\n>       \tif (!(flags & VERIFY_MSG))\n>      @@ sequencer.c: static int try_to_commit(struct repository *r,\n>     -\n>     - \tif (parse_head(r, &current_head))\n>     - \t\treturn -1;\n>     --\n>     - \tif (flags & AMEND_MSG) {\n>     - \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n>     - \t\tconst char *out_enc = get_commit_output_encoding();\n>     -@@ sequencer.c: static int try_to_commit(struct repository *r,\n>       \t\tcommit_list_insert(current_head, &parents);\n>       \t}\n>\n> 3:  19352fdc22 = 3:  fa3d4856b4 sequencer: rename amend_author to author_to_free\n> 4:  5e971abb74 ! 4:  96657233d4 rebase -i: support --ignore-date\n>     @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr\n>      +\t\terror(_(\"malformed ident line '%s'\"), author);\n>      +\t\treturn NULL;\n>      +\t}\n>     ++\n>      +\tlen = ident.mail_end - ident.name_begin + 1;\n>     -+\n>      +\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n>      +\tdatestamp(&new_author);\n>      +\treturn strbuf_detach(&new_author, NULL);\n>     @@ sequencer.c: static int try_to_commit(struct repository *r,\n>      +\t\tfree(author_to_free);\n>      +\t\tauthor_to_free = (char *)author;\n>      +\t}\n>     ++\n>       \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n>       \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n>       \t\tres = error(_(\"failed to write commit object\"));\n> 5:  43a097c583 = 5:  828155baba rebase: add --reset-author-date\n>\n> --\n> 2.26.2\n>\n"},{"id":"398454","messageId":"bc6bc4d4-79cb-f788-deca-41a3735fcaae@gmail.com","threadId":"53176","inReplyTo":"20200523123025.GA20683@danh.dev","subject":"Re: [PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-23T15:43:39Z","receivedAt":"2020-05-23T15:43:46Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 23/05/2020 13:30, Đoàn Trần Công Danh wrote:\n> Hi Phillip,\n> \n> On 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>> +# Checking for +0000 in author time is enough since default\n>> +# timezone is UTC, but the timezone used while committing\n>> +# sets to +0530.\n>> +test_expect_success '--ignore-date works with apply backend' '\n>> +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n>> +\tgit rebase --apply --ignore-date HEAD^ &&\n>> +\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n> \n> Those --pretty=\"format:%ai\" won't print the newline character in my\n> test environment.\n> It looks like it won't print the newline if stdout isn't a tty.\n> \n> \tgit log -1 --pretty=%ai\n> \n> doesn't have that issue.\n> \n> I think there're some grep out there considers file doesn't end with\n> newline as non-text files.\n\nYes it would be better to print the newline, thanks\n\n>> +\tgrep \"+0000\" authortime\n>> +'\n>> +\n>> +test_expect_success '--ignore-date works with merge backend' '\n>> +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n>> +\tgit rebase --ignore-date -m HEAD^ &&\n>> +\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n>> +\tgrep \"+0000\" authortime\n>> +'\n>> +\n>> +test_expect_success '--ignore-date works after conflict resolution' '\n>> +\ttest_must_fail git rebase --ignore-date -m \\\n>> +\t\t--onto commit2^^ commit2^ commit2 &&\n>> +\techo resolved >foo &&\n>> +\tgit add foo &&\n>> +\tgit rebase --continue &&\n>> +\tgit log --pretty=%ai >authortime &&\n>> +\tgrep +0000 authortime\n>> +'\n> \n>  From the test's name, I guess git-rebase is supposed to continue\n> respect --ignore-date after conflict resolution.\n> \n> But the content of authortime read:\n> \n> \t2020-05-23 12:13:58 +0000\n> \t1999-04-02 08:03:20 +0530\n> \t1999-04-02 08:03:20 +0530\n> \n> It's still pass \"grep +0000 authortime\" because of first line,\n> I'm not sure if I missed anything.\n\nIt's only rebasing one commit - the log command is missing -1. I've \nchecked the log invocations in the other tests and I think they're all OK.\n\nJunio - are you happy to fix this up (assuming there are no other \nissues) or do you want a re-roll?\n\nThanks\n\nPhillip\n"},{"id":"398455","messageId":"20200523155203.GA10163@danh.dev","threadId":"53176","inReplyTo":"bc6bc4d4-79cb-f788-deca-41a3735fcaae@gmail.com","subject":"Re: [PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-05-23T15:52:03Z","receivedAt":"2020-05-23T15:52:08Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"Hi Phillip\n\nOn 2020-05-23 16:43:39+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> > On 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> > > +# Checking for +0000 in author time is enough since default\n> > > +# timezone is UTC, but the timezone used while committing\n> > > +# sets to +0530.\n> > > +test_expect_success '--ignore-date works with apply backend' '\n> > > +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> > > +\tgit rebase --apply --ignore-date HEAD^ &&\n> > > +\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n> > \n> > Those --pretty=\"format:%ai\" won't print the newline character in my\n> > test environment.\n> > It looks like it won't print the newline if stdout isn't a tty.\n> > \n> > \tgit log -1 --pretty=%ai\n> > \n> > doesn't have that issue.\n> > \n> > I think there're some grep out there considers file doesn't end with\n> > newline as non-text files.\n> \n> Yes it would be better to print the newline, thanks\n>\n> Junio - are you happy to fix this up (assuming there are no other issues) or\n> do you want a re-roll?\n\nThere're 11 invocation of git-log with \"--pretty=format\",\nin 2/5 and 4/5\n\nI think it's worth to have a re-roll to avoid mistake.\n\n-- \nDanh\n"},{"id":"398459","messageId":"0cf07e92-25f2-ae0f-6f44-c2cd9e9f4851@gmail.com","threadId":"53176","inReplyTo":"20200523155203.GA10163@danh.dev","subject":"Re: [PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-23T18:50:40Z","receivedAt":"2020-05-23T18:50:45Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 23/05/2020 16:52, Đoàn Trần Công Danh wrote:\n> Hi Phillip\n> \n> On 2020-05-23 16:43:39+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>> On 2020-05-21 11:14:54+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>>> +# Checking for +0000 in author time is enough since default\n>>>> +# timezone is UTC, but the timezone used while committing\n>>>> +# sets to +0530.\n>>>> +test_expect_success '--ignore-date works with apply backend' '\n>>>> +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n>>>> +\tgit rebase --apply --ignore-date HEAD^ &&\n>>>> +\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n>>>\n>>> Those --pretty=\"format:%ai\" won't print the newline character in my\n>>> test environment.\n>>> It looks like it won't print the newline if stdout isn't a tty.\n>>>\n>>> \tgit log -1 --pretty=%ai\n>>>\n>>> doesn't have that issue.\n>>>\n>>> I think there're some grep out there considers file doesn't end with\n>>> newline as non-text files.\n>>\n>> Yes it would be better to print the newline, thanks\n>>\n>> Junio - are you happy to fix this up (assuming there are no other issues) or\n>> do you want a re-roll?\n> \n> There're 11 invocation of git-log with \"--pretty=format\",\n> in 2/5 and 4/5\n> \n> I think it's worth to have a re-roll to avoid mistake.\n\nThe part of my reply you've cut said \"I've checked the log invocations \nin the other tests and I think they're all OK.\" So it is just the one \nthat you pointed out that needs to be fixed up (the others without -1 \nare all checking the result of rebase --root). I'm happy to re-roll if \nJunio wants - lets wait and see what he says.\n\nBest Wishes\n\nPhillip\nPhillip\n"},{"id":"398462","messageId":"20200523230526.GA1981@danh.dev","threadId":"53176","inReplyTo":"0cf07e92-25f2-ae0f-6f44-c2cd9e9f4851@gmail.com","subject":"Re: [PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-05-23T23:05:26Z","receivedAt":"2020-05-23T23:05:32Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"Hi Phillip,\n\nOn 2020-05-23 19:50:40+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> \n> The part of my reply you've cut said \"I've checked the log invocations in\n> the other tests and I think they're all OK.\" So it is just the one that you\n> pointed out that needs to be fixed up (the others without -1 are all\n> checking the result of rebase --root). I'm happy to re-roll if Junio wants -\n> lets wait and see what he says.\n\nAh, I was thinking \"they're all OK\" meant that part can be left as-is,\nand the only part need to change is the --pretty=format.\n\nSorry for the noise, (and my bad in reading).\n\n-- \nDanh\n"},{"id":"398474","messageId":"xmqqy2phpa37.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200523155203.GA10163@danh.dev","subject":"Re: [PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-05-24T16:32:44Z","receivedAt":"2020-05-24T16:32:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Đoàn Trần Công Danh  <congdanhqx@gmail.com> writes:\n\n>> > I think there're some grep out there considers file doesn't end with\n>> > newline as non-text files.\n>> \n>> Yes it would be better to print the newline, thanks\n>>\n>> Junio - are you happy to fix this up (assuming there are no other issues) or\n>> do you want a re-roll?\n>\n> There're 11 invocation of git-log with \"--pretty=format\",\n> in 2/5 and 4/5\n>\n> I think it's worth to have a re-roll to avoid mistake.\n\nIt would be appropriate to send \"[PATCH v3 6/5] fixup! ...\" if the\nfix needs to be made only to a single step.  It would be the least\nerror-prone approach.\n\nThanks.\n\n\n"},{"id":"398620","messageId":"489037af-0a59-9cbf-6ba1-92dc48b24a45@gmail.com","threadId":"53176","inReplyTo":"20200523230526.GA1981@danh.dev","subject":"Re: [PATCH v3 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T09:55:58Z","receivedAt":"2020-05-27T09:56:04Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 24/05/2020 00:05, Đoàn Trần Công Danh wrote:\n> Hi Phillip,\n> \n> On 2020-05-23 19:50:40+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> The part of my reply you've cut said \"I've checked the log invocations in\n>> the other tests and I think they're all OK.\" So it is just the one that you\n>> pointed out that needs to be fixed up (the others without -1 are all\n>> checking the result of rebase --root). I'm happy to re-roll if Junio wants -\n>> lets wait and see what he says.\n> \n> Ah, I was thinking \"they're all OK\" meant that part can be left as-is,\n> and the only part need to change is the --pretty=format.\n> \n> Sorry for the noise, (and my bad in reading).\n\nLooking at the patches again I think I misunderstood what you were \nsaying - I had not twigged that I needed to remove the 'format:' from \nall the git log invocations. I'll send a reroll later.\n\nSorry for the confusion\n\nPhillip\n"},{"id":"398667","messageId":"20200527173356.47364-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH v4 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T17:33:51Z","receivedAt":"2020-05-27T17:34:09Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThanks to Danh for the review, I've updated the tests accordingly.\n\nPhillip Wood (2):\n  rebase -i: support --committer-date-is-author-date\n  rebase -i: support --ignore-date\n\nRohit Ashiwal (3):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: rename amend_author to author_to_free\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt           |  33 +++-\n builtin/rebase.c                       |  46 ++++--\n sequencer.c                            | 111 ++++++++++++-\n sequencer.h                            |   2 +\n t/t3422-rebase-incompatible-options.sh |   2 -\n t/t3436-rebase-more-options.sh         | 209 +++++++++++++++++++++++++\n 6 files changed, 379 insertions(+), 24 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\nRange-diff against v3:\n1:  df8c4ed2e9 = 1:  df8c4ed2e9 rebase -i: add --ignore-whitespace flag\n2:  df44a0bde6 ! 2:  ad21e5d8fb rebase -i: support --committer-date-is-author-date\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-whitespace is reme\n     +test_expect_success '--committer-date-is-author-date works with apply backend' '\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n     +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n    -+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    -+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n    ++\tgit log -1 --pretty=%ai >authortime &&\n    ++\tgit log -1 --pretty=%ci >committertime &&\n     +\ttest_cmp authortime committertime\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works with merge backend' '\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n     +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n    -+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    -+\tgit log -1 --pretty=\"format:%ci\" >committertime &&\n    ++\tgit log -1 --pretty=%ai >authortime &&\n    ++\tgit log -1 --pretty=%ci >committertime &&\n     +\ttest_cmp authortime committertime\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n     +\tgit checkout side &&\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n     +\tgit rebase -r --root --committer-date-is-author-date &&\n    -+\tgit log --pretty=\"format:%ai\" >authortime &&\n    -+\tgit log --pretty=\"format:%ci\" >committertime &&\n    ++\tgit log --pretty=%ai >authortime &&\n    ++\tgit log --pretty=%ci >committertime &&\n     +\ttest_cmp authortime committertime\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works when forking merge' '\n     +\tgit checkout side &&\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n     +\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n    -+\tgit log --pretty=\"format:%ai\" >authortime &&\n    -+\tgit log --pretty=\"format:%ci\" >committertime &&\n    ++\tgit log --pretty=%ai >authortime &&\n    ++\tgit log --pretty=%ci >committertime &&\n     +\ttest_cmp authortime committertime\n     +\n     +'\n3:  fa3d4856b4 = 3:  af92e29cf9 sequencer: rename amend_author to author_to_free\n4:  96657233d4 ! 4:  4399dc19b6 rebase -i: support --ignore-date\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-\n     +test_expect_success '--ignore-date works with apply backend' '\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     +\tgit rebase --apply --ignore-date HEAD^ &&\n    -+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    ++\tgit log -1 --pretty=%ai >authortime &&\n     +\tgrep \"+0000\" authortime\n     +'\n     +\n     +test_expect_success '--ignore-date works with merge backend' '\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     +\tgit rebase --ignore-date -m HEAD^ &&\n    -+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    ++\tgit log -1 --pretty=%ai >authortime &&\n     +\tgrep \"+0000\" authortime\n     +'\n     +\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-\n     +\techo resolved >foo &&\n     +\tgit add foo &&\n     +\tgit rebase --continue &&\n    -+\tgit log --pretty=%ai >authortime &&\n    ++\tgit log -1 --pretty=%ai >authortime &&\n     +\tgrep +0000 authortime\n     +'\n     +\n5:  828155baba ! 5:  a11db78eb4 rebase: add --reset-author-date\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-\n      \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     -\tgit rebase --apply --ignore-date HEAD^ &&\n     +\tgit rebase --apply --reset-author-date HEAD^ &&\n    - \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    + \tgit log -1 --pretty=%ai >authortime &&\n      \tgrep \"+0000\" authortime\n      '\n      \n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-\n      \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     -\tgit rebase --ignore-date -m HEAD^ &&\n     +\tgit rebase --reset-author-date -m HEAD^ &&\n    - \tgit log -1 --pretty=\"format:%ai\" >authortime &&\n    + \tgit log -1 --pretty=%ai >authortime &&\n      \tgrep \"+0000\" authortime\n      '\n      \n\n-- \n2.25.1.551.gd3318bf0d3.dirty\n\n"},{"id":"398668","messageId":"20200527173356.47364-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200527173356.47364-1-phillip.wood123@gmail.com","subject":"[PATCH v4 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T17:33:52Z","receivedAt":"2020-05-27T17:34:11Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nRebase is implemented with two different backends - 'apply' and 'merge'\neach of which support a different set of options. In particuar the apply\nbackend supports a number of options implemented by 'git am' that are\nnot available to the merge backend. As part of an on going effort to\nremove the apply backend this patch adds support for the\n--ignore-whitespace option to the merge backend. This option treats\nlines with only whitespace changes as unchanged and is implemented in\nthe merge backend by translating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 19 +++++-\n builtin/rebase.c                       | 19 ++++--\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++\n 4 files changed, 118 insertions(+), 7 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f7a6033607..b003784f01 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tIgnore whitespace differences when trying to reconcile\n+differences. Currently, each backend implements an approximation of\n+this behavior:\n++\n+apply backend: When applying a patch, ignore changes in whitespace in\n+context lines. Unfortunately, this means that if the \"old\" lines being\n+replaced by the patch differ only in whitespace from the existing\n+file, you will get a merge conflict instead of a successful patch\n+application.\n++\n+merge backend: Treat lines with only whitespace changes as unchanged\n+when merging. Unfortunately, this means that any patch hunks that were\n+intended to modify whitespace and nothing else will be dropped, even\n+if the other side had no changes that conflicted.\n+\n --whitespace=<option>::\n-\tThese flags are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n \tImplies --apply.\n +\n@@ -572,7 +587,6 @@ The following options:\n  * --apply\n  * --committer-date-is-author-date\n  * --ignore-date\n- * --ignore-whitespace\n  * --whitespace\n  * -C\n \n@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n+ * --preserve-merges and --ignore-whitespace\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 27a07d4e78..5d8e117276 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -86,6 +86,7 @@ struct rebase_options {\n \tint signoff;\n \tint allow_rerere_autoupdate;\n \tint autosquash;\n+\tint ignore_whitespace;\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tchar *cmd;\n@@ -108,6 +109,7 @@ struct rebase_options {\n \n static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n {\n+\tstruct strbuf strategy_buf = STRBUF_INIT;\n \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n \n \treplay.action = REPLAY_INTERACTIVE_REBASE;\n@@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n-\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n+\t\tstrbuf_addstr(&strategy_buf, opts->strategy_opts);\n+\tif (opts->ignore_whitespace)\n+\t\tstrbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n+\tif (strategy_buf.len)\n+\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n \n \tif (opts->squash_onto) {\n \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n \t\treplay.have_squash_onto = 1;\n \t}\n \n+\tstrbuf_release(&strategy_buf);\n \treturn replay;\n }\n \n@@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n \n+\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n+\n \tif (!is_null_oid(&squash_onto))\n \t\topts.squash_onto = &squash_onto;\n \n@@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)\n \tam.git_cmd = 1;\n \targv_array_push(&am.args, \"am\");\n \n+\tif (opts->ignore_whitespace)\n+\t\targv_array_push(&am.args, \"--ignore-whitespace\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..55ca46786d 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nnew file mode 100755\nindex 0000000000..fb5e747e86\n--- /dev/null\n+++ b/t/t3436-rebase-more-options.sh\n@@ -0,0 +1,86 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\tq_to_tab >file <<-\\EOF &&\n+\tline 1\n+\tQline 2\n+\tline 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tcat >file <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\n+\tgit checkout --orphan master &&\n+\tsed -e \"s/^|//\" >file <<-\\EOF &&\n+\t|line 1\n+\t|        line 2\n+\t|line 3\n+\tEOF\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with apply backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase --apply main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --apply --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--ignore-whitespace works with merge backend' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\ttest_cmp expect file\n+'\n+\n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\tcat >expect <<-\\EOF &&\n+\tline 1\n+\tnew line 2\n+\tline 3\n+\tEOF\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n+\t) &&\n+\tgit rebase --continue &&\n+\ttest_cmp expect file\n+'\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n+test_done\n-- \n2.26.2\n\n"},{"id":"398669","messageId":"20200527173356.47364-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200527173356.47364-1-phillip.wood123@gmail.com","subject":"[PATCH v4 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T17:33:53Z","receivedAt":"2020-05-27T17:34:12Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nAs part of the on-going effort to retire the apply rebase backend teach\nthe merge backend how to handle --committer-date-is-author-date.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 10 +++--\n builtin/rebase.c                       | 16 ++++---\n sequencer.c                            | 59 +++++++++++++++++++++++++-\n sequencer.h                            |  1 +\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++\n 6 files changed, 133 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex b003784f01..dfa70263e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of using the current time as the committer date, use\n+\tthe author date of the commit being rebased as the committer\n+\tdate. This option implies --force-rebase.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tThis flag is passed to 'git am' to change the author date\n+\tof each rebased commit (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 5d8e117276..357cd6acf3 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -89,6 +89,7 @@ struct rebase_options {\n \tint ignore_whitespace;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)\n \n \tif (opts->ignore_whitespace)\n \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n@@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n+\tif (options.committer_date_is_author_date)\n+\t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n+\t\tif (!strcmp(option, \"--ignore-date\") ||\n \t\t    !strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\ndiff --git a/sequencer.c b/sequencer.c\nindex 6fd2674632..8826c6325b 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -872,6 +873,22 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+static const char *author_date_from_env_array(const struct argv_array *env)\n+{\n+\tint i;\n+\tconst char *date;\n+\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n \n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \targv_array_push(&cmd.args, \"commit\");\n \n \tif (!(flags & VERIFY_MSG))\n@@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,\n \t\tcommit_list_insert(current_head, &parents);\n \t}\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tint len = strlen(author);\n+\t\tstruct ident_split ident;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!ident.date_begin) {\n+\t\t\tres = error(_(\"corrupted author without date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n+\t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&date);\n+\n+\t\tif (res)\n+\t\t\tgoto out;\n+\t}\n+\n \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n \t\tres = error(_(\"git write-tree failed to write a tree\"));\n \t\tgoto out;\n@@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n \tif (opts->keep_redundant_commits)\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,\n \t\t\tgoto leave_merge;\n \t\t}\n \n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n \t\targv_array_push(&cmd.args, \"-s\");\n@@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t\topts->record_origin || opts->edit ||\n+\t\t\t\topts->committer_date_is_author_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 0bee85093e..4ab94119ae 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -45,6 +45,7 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n \n \tint mainline;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 55ca46786d..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex fb5e747e86..7e68fb9753 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n # This is a special case in which both am and interactive backends\n # provide the same output. It was done intentionally because\n # both the backends fall short of optimal behaviour.\n@@ -28,8 +31,13 @@ test_expect_success 'setup' '\n \tEOF\n \tgit commit -am \"update file\" &&\n \tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n \n \tgit checkout --orphan master &&\n+\tgit rm --cached foo &&\n+\trm foo &&\n \tsed -e \"s/^|//\" >file <<-\\EOF &&\n \t|line 1\n \t|        line 2\n@@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n \ttest_cmp expect file\n '\n \n+test_expect_success '--committer-date-is-author-date works with apply backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgit log -1 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with merge backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgit log -1 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\tgit log --pretty=%ai >authortime &&\n+\tgit log --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n+\tgit log --pretty=%ai >authortime &&\n+\tgit log --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\tgit log -1 --format=%at HEAD >expect &&\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -1 --format=%ct HEAD >actual &&\n+\ttest_cmp expect actual\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"398670","messageId":"20200527173356.47364-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200527173356.47364-1-phillip.wood123@gmail.com","subject":"[PATCH v4 3/5] sequencer: rename amend_author to author_to_free","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T17:33:54Z","receivedAt":"2020-05-27T17:34:14Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() when amending a commit. But we can\nalso use the variable to free() the author at our convenience.\nRename it to convey this meaning.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 8826c6325b..44e0b45e53 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n-\tchar *amend_author = NULL;\n+\tchar *author_to_free = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tstrbuf_addstr(msg, orig_message);\n \t\t\thook_commit = \"HEAD\";\n \t\t}\n-\t\tauthor = amend_author = get_author(message);\n+\t\tauthor = author_to_free = get_author(message);\n \t\tunuse_commit_buffer(current_head, message);\n \t\tif (!author) {\n \t\t\tres = error(_(\"unable to parse commit author\"));\n@@ -1473,7 +1473,7 @@ static int try_to_commit(struct repository *r,\n \tfree_commit_extra_headers(extra);\n \tstrbuf_release(&err);\n \tstrbuf_release(&commit_msg);\n-\tfree(amend_author);\n+\tfree(author_to_free);\n \n \treturn res;\n }\n-- \n2.26.2\n\n"},{"id":"398671","messageId":"20200527173356.47364-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200527173356.47364-1-phillip.wood123@gmail.com","subject":"[PATCH v4 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T17:33:55Z","receivedAt":"2020-05-27T17:34:15Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nAs part of the on-going effort to retire the apply rebase backend\nteach the merge backend how to handle --ignore-date. We take care to\nhandle the combination of --ignore-date and\n--committer-date-is-author-date in the same way as the apply backend.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt   |  7 +++--\n builtin/rebase.c               | 13 +++++---\n sequencer.c                    | 50 +++++++++++++++++++++++++++--\n sequencer.h                    |  1 +\n t/t3436-rebase-more-options.sh | 57 ++++++++++++++++++++++++++++++++++\n 5 files changed, 118 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex dfa70263e6..e2717e20e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof each rebased commit (see linkgit:git-am[1]).\n+\tInstead of using the author date of the original commit, use\n+\tthe current time as the\tauthor date of the rebased commit.  This\n+\toption implies `--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n  * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 357cd6acf3..cf86240bc8 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -90,6 +90,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -129,6 +130,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.committer_date_is_author_date =\n \t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1008,6 +1010,8 @@ static int run_am(struct rebase_options *opts)\n \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n \tif (opts->committer_date_is_author_date)\n \t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&opts->git_am_opts, \"--ignore-date\");\n \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n \t\targv_array_push(&am.args, \"--resolved\");\n \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n@@ -1515,8 +1519,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current date\"),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n@@ -1809,13 +1813,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n-\tif (options.committer_date_is_author_date)\n+\tif (options.committer_date_is_author_date || options.ignore_date)\n \t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 44e0b45e53..a21364c3be 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n }\n \n+/* Construct a free()able author string with current time as the author date */\n+static char *ignore_author_date(const char *author)\n+{\n+\tint len = strlen(author);\n+\tstruct ident_split ident;\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\n+\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\terror(_(\"malformed ident line '%s'\"), author);\n+\t\treturn NULL;\n+\t}\n+\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n \n \tif (opts->committer_date_is_author_date)\n \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n \t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1387,7 +1410,8 @@ static int try_to_commit(struct repository *r,\n \t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n \t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n \t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n-\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n \t\tstrbuf_release(&date);\n \n \t\tif (res)\n@@ -1453,6 +1477,16 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tauthor = ignore_author_date(author);\n+\t\tif (!author) {\n+\t\t\tres = -1;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tfree(author_to_free);\n+\t\tauthor_to_free = (char *)author;\n+\t}\n+\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -2582,6 +2616,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->committer_date_is_author_date = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2674,6 +2713,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n \tif (opts->committer_date_is_author_date)\n \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3596,7 +3637,11 @@ static int do_merge(struct repository *r,\n \n \t\tif (opts->committer_date_is_author_date)\n \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3876,7 +3921,8 @@ static int pick_commits(struct repository *r,\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n \t\t\t\topts->record_origin || opts->edit ||\n-\t\t\t\topts->committer_date_is_author_date));\n+\t\t\t\topts->committer_date_is_author_date ||\n+\t\t\t\topts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 4ab94119ae..3587878e3b 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -46,6 +46,7 @@ struct replay_opts {\n \tint quiet;\n \tint reschedule_failed_exec;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 7e68fb9753..a3f9d5b41a 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -134,6 +134,63 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n \ttest_cmp expect actual\n '\n \n+# Checking for +0000 in author time is enough since default\n+# timezone is UTC, but the timezone used while committing\n+# sets to +0530.\n+test_expect_success '--ignore-date works with apply backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works with merge backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgrep \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -m \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgrep +0000 authortime\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\tgit log --pretty=%ai >authortime &&\n+\t! grep -v \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\tgit log -2 --pretty=%ai >authortime &&\n+\tgit log -2 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\t! grep -v \"+0000\" authortime\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tgit rebase -i --strategy=resolve --ignore-date \\\n+\t\t--committer-date-is-author-date side side &&\n+\tgit log -1 --pretty=%ai >authortime &&\n+\tgit log -1 --pretty=%ci >committertime &&\n+\ttest_cmp authortime committertime &&\n+\tgrep \"+0000\" authortime\n+ '\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"398672","messageId":"20200527173356.47364-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200527173356.47364-1-phillip.wood123@gmail.com","subject":"[PATCH v4 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T17:33:56Z","receivedAt":"2020-05-27T17:34:18Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe previous commit introduced --ignore-date flag to rebase -i, but the\nname is rather vague as it does not say whether the author date or the\ncommitter date is ignored. Add an alias to convey the precise purpose.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt   |  1 +\n builtin/rebase.c               |  6 ++++--\n t/t3436-rebase-more-options.sh | 34 ++++++++++++++++++++++------------\n 3 files changed, 27 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e2717e20e6..a5f82913fb 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the author date of the original commit, use\n \tthe current time as the\tauthor date of the rebased commit.  This\n \toption implies `--force-rebase`.\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex cf86240bc8..911587690b 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1519,8 +1519,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n-\t\t\t \"ignore author date and use current date\"),\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex a3f9d5b41a..5ee193f333 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -137,22 +137,22 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n # Checking for +0000 in author time is enough since default\n # timezone is UTC, but the timezone used while committing\n # sets to +0530.\n-test_expect_success '--ignore-date works with apply backend' '\n+test_expect_success '--reset-author-date works with apply backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit rebase --apply --reset-author-date HEAD^ &&\n \tgit log -1 --pretty=%ai >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date works with merge backend' '\n+test_expect_success '--reset-author-date works with merge backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit rebase --reset-author-date -m HEAD^ &&\n \tgit log -1 --pretty=%ai >authortime &&\n \tgrep \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date works after conflict resolution' '\n-\ttest_must_fail git rebase --ignore-date -m \\\n+test_expect_success '--reset-author-date works after conflict resolution' '\n+\ttest_must_fail git rebase --reset-author-date -m \\\n \t\t--onto commit2^^ commit2^ commit2 &&\n \techo resolved >foo &&\n \tgit add foo &&\n@@ -161,17 +161,17 @@ test_expect_success '--ignore-date works after conflict resolution' '\n \tgrep +0000 authortime\n '\n \n-test_expect_success '--ignore-date works with rebase -r' '\n+test_expect_success '--reset-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n-\tgit rebase -r --root --ignore-date &&\n+\tgit rebase -r --root --reset-author-date &&\n \tgit log --pretty=%ai >authortime &&\n \t! grep -v \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '\n \ttest_must_fail git rebase -m --committer-date-is-author-date \\\n-\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\t\t--reset-author-date --onto commit2^^ commit2^ commit3 &&\n \tgit checkout --theirs foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n@@ -181,16 +181,26 @@ test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n \t! grep -v \"+0000\" authortime\n '\n \n-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n-\t\tgit rebase -i --strategy=resolve --ignore-date \\\n+\t\tgit rebase -i --strategy=resolve --reset-author-date \\\n \t\t--committer-date-is-author-date side side &&\n \tgit log -1 --pretty=%ai >authortime &&\n \tgit log -1 --pretty=%ci >committertime &&\n \ttest_cmp authortime committertime &&\n \tgrep \"+0000\" authortime\n  '\n \n+test_expect_success '--ignore-date is an alias for --reset-author-date' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase -m --ignore-date HEAD^ &&\n+\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n+\tgrep \"+0000\" authortime >output &&\n+\ttest_line_count = 2 output\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.26.2\n\n"},{"id":"398674","messageId":"20200527175748.54468-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200527173356.47364-6-phillip.wood123@gmail.com","subject":"[PATCH v4 6/5] fixup! rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-05-27T17:57:48Z","receivedAt":"2020-05-27T17:58:03Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nSorry I somehow forgot to commit this before sending the v4 patches,\nit fixes up the final patch\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n t/t3436-rebase-more-options.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 5ee193f333..ecfd68397f 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n \tgit rebase --apply --ignore-date HEAD^ &&\n \tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n \tgit rebase -m --ignore-date HEAD^ &&\n-\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n+\tgit log -2 --pretty=%ai >authortime &&\n \tgrep \"+0000\" authortime >output &&\n \ttest_line_count = 2 output\n '\n-- \n2.26.2\n\n"},{"id":"398694","messageId":"xmqq5zchkrtf.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200527173356.47364-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v4 0/5] cleanup ra/rebase-i-more-options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-05-27T21:10:04Z","receivedAt":"2020-05-27T21:10:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>     -+\tgit log -1 --pretty=\"format:%ai\" >authortime &&\n>     ++\tgit log -1 --pretty=%ai >authortime &&\n\nIt probably wouldn't make too much of a difference in real life, but\nI think \"--format=%ai\" is how the above is customary written.\n\nSome history.\n\nThe --pretty=\"format:<string with per-cent placeholder>\" came first,\nwith an explicit goal of giving us enough flexibility to mimick\ncanned \"pretty print\" formats like --pretty=medium, --pretty=short,\netc. (note: it was *not* part of the goal to actually replace the\nimplementation of canned formats with hardcoded set of placeholder\nstrings).\n\nIf you run \"git log --pretty=medium -2\", you'd observe that the\ntopmost commit is shown immediately without any preceding blank\nline, then an extra blank line is shown, and then the second commit\nis shown, and after that, the output ends without any extra blank\nline.  With respect to the \"extra blank line\", we call this\n\"separator semantics\"---an extra blank is given _between_ two items\nthat are shown.\n\nLike \"git log --pretty=medium\", the \"format:<custom>\" pretty print\nformat uses the \"separator semantics\".  There is no \"extra LF\" after\nshowing the last item.\n\nOf course, the \"separator\" behaviour was later found to be\ncumbersome if we wanted to mimick \"--pretty=oneline\".  The payload\nof each item in the oneline output format lacks the terminating LF,\nso instead of an extra LF between two items, we want an extra LF\nafter every item.  This, in contrast to \"separator\" semantics, is\ncalled \"terminator\" semantics and --pretty=\"tformat:<custom>\" was\nintroduced to allow.\n\nLater, when we introduced --format=<format>, we made it so that \n\n (1) when <format> is equal to one of the canned format names,\n     \"--format=<format>\" is equivalent to \"--<format>\".\n\n (2) otherwise, when <format> has placeholders, \"--format=<format>\"\n     acts the same way as \"--pretty=tformat:<format>\".\n\nas we found out that people are often using custom format that\nconsists of only one line of payload, quite often as a way to\nextract a handful of \"fields\" from each commit object.\n\nSo given all of the above, the \"let's grab the author-time in iso\nformat and nothing else from each commit object\" in the above\nexcerpt from your test is the use case for which --format=%ai was\ndesigned.\n\n"},{"id":"398733","messageId":"20200528131701.GD1983@danh.dev","threadId":"53176","inReplyTo":"20200527175748.54468-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v4 6/5] fixup! rebase: add --reset-author-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-05-28T13:17:01Z","receivedAt":"2020-05-28T13:17:07Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"On 2020-05-27 18:57:48+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> Sorry I somehow forgot to commit this before sending the v4 patches,\n> it fixes up the final patch\n> \n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  t/t3436-rebase-more-options.sh | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n> \n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 5ee193f333..ecfd68397f 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n>  \tgit rebase --apply --ignore-date HEAD^ &&\n>  \tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n>  \tgit rebase -m --ignore-date HEAD^ &&\n> -\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n> +\tgit log -2 --pretty=%ai >authortime &&\n>  \tgrep \"+0000\" authortime >output &&\n>  \ttest_line_count = 2 output\n>  '\n\nThis version addressed all of my concerns, LGTM.\n\nOnly the last\n\n\ttest_line_count = 2 output\n\npuzzled me at first.\nSince it's the only usage of test_line_count in this version\nTurn out, it's equivalence with:\n-----------8<-----------\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex ecfd68397f..abe9af4d8c 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -197,8 +197,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n \tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n \tgit rebase -m --ignore-date HEAD^ &&\n \tgit log -2 --pretty=%ai >authortime &&\n-\tgrep \"+0000\" authortime >output &&\n-\ttest_line_count = 2 output\n+\t! grep -v \"+0000\" authortime\n '\n \n # This must be the last test in this file\n------>8------\n\nThis is the check used in t3436.15\nCurrent version is good as is, anyway.\n\n-- \nDanh\n"},{"id":"398901","messageId":"nycvar.QRO.7.76.6.2005290437350.56@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"20200527173356.47364-2-phillip.wood123@gmail.com","subject":"Re: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-05-29T02:38:37Z","receivedAt":"2020-05-29T19:12:31Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nsorry to be _so_ late in the game. (And sorry for sending this to you\ntwice, I managed to skip all the Cc:s due to the Reply-To: header the\nfirst time round.)\n\nOn Wed, 27 May 2020, Phillip Wood wrote:\n\n> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>\n> Rebase is implemented with two different backends - 'apply' and 'merge'\n> each of which support a different set of options. In particuar the apply\n> backend supports a number of options implemented by 'git am' that are\n> not available to the merge backend. As part of an on going effort to\n\nAs a non-native speaker, I am thrown off when reading \"available to\"\ninstead of the grammatically correct (I believe) \"available in\". Likewise,\n\"on going\" instead of \"ongoing\" just disrupts my workflow.\n\nMaybe these can be fixed?\n\n> remove the apply backend this patch adds support for the\n> --ignore-whitespace option to the merge backend. This option treats\n> lines with only whitespace changes as unchanged and is implemented in\n> the merge backend by translating it to -Xignore-space-change.\n>\n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt           | 19 +++++-\n>  builtin/rebase.c                       | 19 ++++--\n>  t/t3422-rebase-incompatible-options.sh |  1 -\n>  t/t3436-rebase-more-options.sh         | 86 ++++++++++++++++++++++++++\n>  4 files changed, 118 insertions(+), 7 deletions(-)\n>  create mode 100755 t/t3436-rebase-more-options.sh\n>\n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index f7a6033607..b003784f01 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n>  with `--keep-base` in order to drop those commits from your branch.\n>\n>  --ignore-whitespace::\n> +\tIgnore whitespace differences when trying to reconcile\n> +differences. Currently, each backend implements an approximation of\n> +this behavior:\n> ++\n> +apply backend: When applying a patch, ignore changes in whitespace in\n> +context lines. Unfortunately, this means that if the \"old\" lines being\n> +replaced by the patch differ only in whitespace from the existing\n> +file, you will get a merge conflict instead of a successful patch\n> +application.\n> ++\n> +merge backend: Treat lines with only whitespace changes as unchanged\n> +when merging. Unfortunately, this means that any patch hunks that were\n> +intended to modify whitespace and nothing else will be dropped, even\n> +if the other side had no changes that conflicted.\n> +\n>  --whitespace=<option>::\n> -\tThese flags are passed to the 'git apply' program\n> +\tThis flag is passed to the 'git apply' program\n>  \t(see linkgit:git-apply[1]) that applies the patch.\n>  \tImplies --apply.\n>  +\n> @@ -572,7 +587,6 @@ The following options:\n>   * --apply\n>   * --committer-date-is-author-date\n>   * --ignore-date\n> - * --ignore-whitespace\n>   * --whitespace\n>   * -C\n>\n> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --signoff\n>   * --preserve-merges and --rebase-merges\n>   * --preserve-merges and --empty=\n> + * --preserve-merges and --ignore-whitespace\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 27a07d4e78..5d8e117276 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -86,6 +86,7 @@ struct rebase_options {\n>  \tint signoff;\n>  \tint allow_rerere_autoupdate;\n>  \tint autosquash;\n> +\tint ignore_whitespace;\n>  \tchar *gpg_sign_opt;\n>  \tint autostash;\n>  \tchar *cmd;\n> @@ -108,6 +109,7 @@ struct rebase_options {\n>\n>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  {\n> +\tstruct strbuf strategy_buf = STRBUF_INIT;\n>  \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n>\n>  \treplay.action = REPLAY_INTERACTIVE_REBASE;\n> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>  \treplay.strategy = opts->strategy;\n> +\n>  \tif (opts->strategy_opts)\n> -\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n> +\t\tstrbuf_addstr(&strategy_buf, opts->strategy_opts);\n> +\tif (opts->ignore_whitespace)\n> +\t\tstrbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n> +\tif (strategy_buf.len)\n> +\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n\nQuite honestly, this is very, very ugly.\n\nI would have expected this at a way earlier layer, namely in\n`cmd__rebase()`. Something along these lines:\n\n-- snip --\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 37ba76ac3d26..748e08aee2f2 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1289,6 +1289,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tstruct strbuf revisions = STRBUF_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct object_id merge_base;\n+\tint ignore_whitespace = 0;\n \tenum action action = ACTION_NONE;\n \tconst char *gpg_sign = NULL;\n \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n@@ -1318,9 +1319,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n+\t\t\t N_(\"passed to 'git am'\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n@@ -1682,6 +1682,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\timply_merge(&options, \"--rebase-merges\");\n \t}\n\n+\tif (ignore_whitespace) {\n+\t\tif (options.type == REBASE_APPLY)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--ignore-whitespace\");\n+\t\telse\n+\t\t\tstring_list_append(&stragey_options,\n+\t\t\t\t\t   \"--ignore-space-change\");\n+\t}\n+\n \tif (strategy_options.nr) {\n \t\tint i;\n\n-- snap --\n\n\n>\n>  \tif (opts->squash_onto) {\n>  \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n>  \t\treplay.have_squash_onto = 1;\n>  \t}\n>\n> +\tstrbuf_release(&strategy_buf);\n>  \treturn replay;\n>  }\n>\n> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>  \targc = parse_options(argc, argv, prefix, options,\n>  \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n>\n> +\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n\nI am not sure what this is about: `opts.strategy_opts` is of type `char\n*`, i.e. it is supposed to be already allocated.\n\nNot that `cmd_rebase__interactive()` matters _all_ that much anymore, of\ncourse: it is only used by the --preserve-merges backend, which will\nhopefully be retired soon.\n\n> +\n>  \tif (!is_null_oid(&squash_onto))\n>  \t\topts.squash_onto = &squash_onto;\n>\n> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)\n>  \tam.git_cmd = 1;\n>  \targv_array_push(&am.args, \"am\");\n>\n> +\tif (opts->ignore_whitespace)\n> +\t\targv_array_push(&am.args, \"--ignore-whitespace\");\n>  \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n>  \t\targv_array_push(&am.args, \"--resolved\");\n>  \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>  \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>  \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n> -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n> -\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n> -\t\t\t\t  PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>  \t\t\t\t  &options.git_am_opts, NULL,\n>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>  \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n> +\t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n> +\t\t\t N_(\"ignore changes in whitespace\")),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>  \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>  \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 50e7960702..55ca46786d 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>\n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --ignore-whitespace\n>  test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> new file mode 100755\n> index 0000000000..fb5e747e86\n> --- /dev/null\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -0,0 +1,86 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2019 Rohit Ashiwal\n> +#\n> +\n> +test_description='tests to ensure compatibility between am and interactive backends'\n> +\n> +. ./test-lib.sh\n> +\n> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n> +\n> +# This is a special case in which both am and interactive backends\n> +# provide the same output. It was done intentionally because\n> +# both the backends fall short of optimal behaviour.\n> +test_expect_success 'setup' '\n> +\tgit checkout -b topic &&\n> +\tq_to_tab >file <<-\\EOF &&\n> +\tline 1\n> +\tQline 2\n> +\tline 3\n> +\tEOF\n> +\tgit add file &&\n> +\tgit commit -m \"add file\" &&\n> +\tcat >file <<-\\EOF &&\n> +\tline 1\n> +\tnew line 2\n> +\tline 3\n> +\tEOF\n> +\tgit commit -am \"update file\" &&\n> +\tgit tag side &&\n> +\n> +\tgit checkout --orphan master &&\n> +\tsed -e \"s/^|//\" >file <<-\\EOF &&\n> +\t|line 1\n> +\t|        line 2\n> +\t|line 3\n> +\tEOF\n> +\tgit add file &&\n> +\tgit commit -m \"add file\" &&\n> +\tgit tag main\n> +'\n\nThe file contents are repeated in an awfully repetitive manner. That not\nonly makes things a bit hard to read, it also makes it all too easy to\nslip in bugs by mistake. How about something like this instead?\n\n\ttest_commit file &&\n\n\ttest_write_lines line1 Qline2 line3 >templ &&\n\n\tq_to_tab <templ >file.t &&\n\tgit commit -m tab file.t &&\n\n\tsed \"s/Q/new /\" <templ >file.t &&\n\tgit commit -m new file.t &&\n\tgit tag side &&\n\n\tgit checkout file -- &&\n\tsed \"s/Q/        /\" <templ >file.t &&\n\tgit commit -m spaces file.t\n\n... and then...\n\n> +\n> +test_expect_success '--ignore-whitespace works with apply backend' '\n> +\tcat >expect <<-\\EOF &&\n> +\tline 1\n> +\tnew line 2\n> +\tline 3\n> +\tEOF\n\n\tsed \"s/Q/new /\" <templ >expect\n\n> +\ttest_must_fail git rebase --apply main side &&\n> +\tgit rebase --abort &&\n> +\tgit rebase --apply --ignore-whitespace main side &&\n> +\ttest_cmp expect file\n\nPersonally, I prefer to read the contents of `expect` directly before the\n`test_cmp expect file.t`\n\n> +'\n> +\n> +test_expect_success '--ignore-whitespace works with merge backend' '\n> +\tcat >expect <<-\\EOF &&\n> +\tline 1\n> +\tnew line 2\n> +\tline 3\n> +\tEOF\n\nIsn't this totally identical to the `expect` constructed earlier? And in\nany case, isn't this identical to `git show main:file.t`, which is what we\n_actually_ expect: for the file contents to be identical to the tagged\n`main`? I.e.\n\n\tgit diff --exit-code main\n\n> +\ttest_must_fail git rebase --merge main side &&\n> +\tgit rebase --abort &&\n> +\tgit rebase --merge --ignore-whitespace main side &&\n> +\ttest_cmp expect file\n> +'\n> +\n> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n> +\tcat >expect <<-\\EOF &&\n> +\tline 1\n> +\tnew line 2\n> +\tline 3\n> +\tEOF\n> +\t(\n> +\t\tset_fake_editor &&\n> +\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n> +\t) &&\n> +\tgit rebase --continue &&\n> +\ttest_cmp expect file\n\nIt is a bit funny to see these two invocations _specifically_ pulled out\nfrom the subshell, that's not how we do things in other test scripts:\ninstead, we run all the Git commands _inside_ the subshell, and all the\nverifications after the subshell.\n\nI believe that with my suggestions, this test script will be a ton easier\nto read and to maintain. At least it will be a lot DRYer.\n\nCiao,\nDscho\n\n> +'\n> +\n> +# This must be the last test in this file\n> +test_expect_success '$EDITOR and friends are unchanged' '\n> +\ttest_editor_unchanged\n> +'\n> +\n> +test_done\n> --\n> 2.26.2\n>\n>\n"},{"id":"398903","messageId":"nycvar.QRO.7.76.6.2005290439030.56@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"20200527173356.47364-3-phillip.wood123@gmail.com","subject":"Re: [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-05-29T02:52:12Z","receivedAt":"2020-05-29T19:26:07Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Wed, 27 May 2020, Phillip Wood wrote:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> As part of the on-going effort to retire the apply rebase backend teach\n> the merge backend how to handle --committer-date-is-author-date.\n\nI forgot to mention this in my reply to the first patch in this series: it\nstrikes me as a mis-characterization that the `apply` backend is about to\nbe retired. What _is_ true is that the `merge` backend is the default\nbackend, and what is even more true is that it is cumbersome if certain\n`rebase` options cannot be combined because they are only implemented by\none of both rebase backends.\n\n>\n> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt           | 10 +++--\n>  builtin/rebase.c                       | 16 ++++---\n>  sequencer.c                            | 59 +++++++++++++++++++++++++-\n>  sequencer.h                            |  1 +\n>  t/t3422-rebase-incompatible-options.sh |  1 -\n>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++\n>  6 files changed, 133 insertions(+), 10 deletions(-)\n>\n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index b003784f01..dfa70263e6 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -445,9 +445,13 @@ if the other side had no changes that conflicted.\n>  See also INCOMPATIBLE OPTIONS below.\n>\n>  --committer-date-is-author-date::\n> +\tInstead of using the current time as the committer date, use\n> +\tthe author date of the commit being rebased as the committer\n> +\tdate. This option implies --force-rebase.\n> +\n>  --ignore-date::\n> -\tThese flags are passed to 'git am' to easily change the dates\n> -\tof the rebased commits (see linkgit:git-am[1]).\n> +\tThis flag is passed to 'git am' to change the author date\n> +\tof each rebased commit (see linkgit:git-am[1]).\n>  +\n>  See also INCOMPATIBLE OPTIONS below.\n>\n> @@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS\n>  The following options:\n>\n>   * --apply\n> - * --committer-date-is-author-date\n>   * --ignore-date\n>   * --whitespace\n>   * -C\n> @@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --rebase-merges\n>   * --preserve-merges and --empty=\n>   * --preserve-merges and --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 5d8e117276..357cd6acf3 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -89,6 +89,7 @@ struct rebase_options {\n>  \tint ignore_whitespace;\n>  \tchar *gpg_sign_opt;\n>  \tint autostash;\n> +\tint committer_date_is_author_date;\n>  \tchar *cmd;\n>  \tint allow_empty_message;\n>  \tint rebase_merges, rebase_cousins;\n> @@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n>  \treplay.verbose = opts->flags & REBASE_VERBOSE;\n>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n> +\treplay.committer_date_is_author_date =\n> +\t\t\t\t\topts->committer_date_is_author_date;\n>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>  \treplay.strategy = opts->strategy;\n>\n> @@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)\n>\n>  \tif (opts->ignore_whitespace)\n>  \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n> +\tif (opts->committer_date_is_author_date)\n> +\t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n\nAs before, I would rather see this in `cmd__rebase()` rahn in `run_am()`.\n\n>  \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n>  \t\targv_array_push(&am.args, \"--resolved\");\n>  \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n> @@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>  \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>  \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n> -\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n> -\t\t\t\t  &options.git_am_opts, NULL,\n> -\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> +\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n> +\t\t\t &options.committer_date_is_author_date,\n> +\t\t\t N_(\"make committer date match author date\")),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n> @@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t    options.autosquash) {\n>  \t\tallow_preemptive_ff = 0;\n>  \t}\n> +\tif (options.committer_date_is_author_date)\n> +\t\toptions.flags |= REBASE_FORCE;\n>\n>  \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n>  \t\tconst char *option = options.git_am_opts.argv[i], *p;\n> -\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n> -\t\t    !strcmp(option, \"--ignore-date\") ||\n> +\t\tif (!strcmp(option, \"--ignore-date\") ||\n>  \t\t    !strcmp(option, \"--whitespace=fix\") ||\n>  \t\t    !strcmp(option, \"--whitespace=strip\"))\n>  \t\t\tallow_preemptive_ff = 0;\n> diff --git a/sequencer.c b/sequencer.c\n> index 6fd2674632..8826c6325b 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   * command-line.\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -872,6 +873,22 @@ static char *get_author(const char *message)\n>  \treturn NULL;\n>  }\n>\n> +static const char *author_date_from_env_array(const struct argv_array *env)\n> +{\n> +\tint i;\n> +\tconst char *date;\n> +\n> +\tfor (i = 0; i < env->argc; i++)\n> +\t\tif (skip_prefix(env->argv[i],\n> +\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n> +\t\t\treturn date;\n> +\t/*\n> +\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n> +\t * reading the script\n> +\t */\n> +\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n> +}\n> +\n>  static const char staged_changes_advice[] =\n>  N_(\"you have staged changes in your working tree\\n\"\n>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n>  \t\t\t     gpg_opt, gpg_opt);\n>  \t}\n>\n> +\tif (opts->committer_date_is_author_date)\n> +\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\n>  \targv_array_push(&cmd.args, \"commit\");\n>\n>  \tif (!(flags & VERIFY_MSG))\n> @@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,\n>  \t\tcommit_list_insert(current_head, &parents);\n>  \t}\n>\n> +\tif (opts->committer_date_is_author_date) {\n> +\t\tint len = strlen(author);\n\nGiven that `len` is used only once, is this local variable really\nnecessary? You could just as well pass `(int)strlen(author)` in the\n`split_ident_line()` call below.\n\n> +\t\tstruct ident_split ident;\n> +\t\tstruct strbuf date = STRBUF_INIT;\n> +\n> +\t\tif (split_ident_line(&ident, author, len) < 0) {\n> +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n> +\t\t\tgoto out;\n> +\t\t}\n> +\t\tif (!ident.date_begin) {\n> +\t\t\tres = error(_(\"corrupted author without date information\"));\n> +\t\t\tgoto out;\n> +\t\t}\n> +\n> +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n> +\t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n> +\t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +\t\tstrbuf_release(&date);\n\nIt might be easier to read if it was written this way:\n\n\t\tif (split_ident_line(...) < 0)\n\t\t\tres = ...\n\t\telse if (!ident.date_begin)\n\t\t\tres = ...\n\t\telse {\n\t\t\tstrbuf_addf(...)\n\t\t\tres = ...\n\t\t\tstrbuf_release(&date);\n\t\t}\n\n\t\tif (res)\n\t\t\tgoto out;\n\n> +\n> +\t\tif (res)\n> +\t\t\tgoto out;\n> +\t}\n> +\n>  \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>  \t\tres = error(_(\"git write-tree failed to write a tree\"));\n>  \t\tgoto out;\n> @@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>  \t\t\topts->signoff = 1;\n>  \t\t}\n>\n> +\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n> +\t\t\topts->allow_ff = 0;\n> +\t\t\topts->committer_date_is_author_date = 1;\n> +\t\t}\n> +\n>  \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n>  \t\t\topts->reschedule_failed_exec = 1;\n>\n> @@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>  \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>  \tif (opts->keep_redundant_commits)\n>  \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n> +\tif (opts->committer_date_is_author_date)\n> +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>  \tif (opts->reschedule_failed_exec)\n>  \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>\n> @@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,\n>  \t\t\tgoto leave_merge;\n>  \t\t}\n>\n> +\t\tif (opts->committer_date_is_author_date)\n> +\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\n>  \t\tcmd.git_cmd = 1;\n>  \t\targv_array_push(&cmd.args, \"merge\");\n>  \t\targv_array_push(&cmd.args, \"-s\");\n> @@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,\n>  \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>  \tif (opts->allow_ff)\n>  \t\tassert(!(opts->signoff || opts->no_commit ||\n> -\t\t\t\topts->record_origin || opts->edit));\n> +\t\t\t\topts->record_origin || opts->edit ||\n> +\t\t\t\topts->committer_date_is_author_date));\n>  \tif (read_and_refresh_cache(r, opts))\n>  \t\treturn -1;\n>\n> diff --git a/sequencer.h b/sequencer.h\n> index 0bee85093e..4ab94119ae 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -45,6 +45,7 @@ struct replay_opts {\n>  \tint verbose;\n>  \tint quiet;\n>  \tint reschedule_failed_exec;\n> +\tint committer_date_is_author_date;\n>\n>  \tint mainline;\n>\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 55ca46786d..c8234062c6 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>\n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>\n>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index fb5e747e86..7e68fb9753 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>\n>  . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>\n> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> +export GIT_AUTHOR_DATE\n> +\n>  # This is a special case in which both am and interactive backends\n>  # provide the same output. It was done intentionally because\n>  # both the backends fall short of optimal behaviour.\n> @@ -28,8 +31,13 @@ test_expect_success 'setup' '\n>  \tEOF\n>  \tgit commit -am \"update file\" &&\n>  \tgit tag side &&\n> +\ttest_commit commit1 foo foo1 &&\n> +\ttest_commit commit2 foo foo2 &&\n> +\ttest_commit commit3 foo foo3 &&\n>\n>  \tgit checkout --orphan master &&\n> +\tgit rm --cached foo &&\n> +\trm foo &&\n>  \tsed -e \"s/^|//\" >file <<-\\EOF &&\n>  \t|line 1\n>  \t|        line 2\n> @@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n>  \ttest_cmp expect file\n>  '\n>\n> +test_expect_success '--committer-date-is-author-date works with apply backend' '\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n> +\tgit log -1 --pretty=%ai >authortime &&\n> +\tgit log -1 --pretty=%ci >committertime &&\n> +\ttest_cmp authortime committertime\n\nThis seems to be a repeated pattern. To dry it up, it would make sense to\ndo this:\n\n\ttest_ctime_is_atime () {\n\t\tgit log -1 --pretty=%ai >authortime &&\n\t\tgit log -1 --pretty=%ci >committertime &&\n\t\ttest_cmp authortime committertime\n\t}\n\nCiao,\nDscho\n\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with merge backend' '\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n> +\tgit log -1 --pretty=%ai >authortime &&\n> +\tgit log -1 --pretty=%ci >committertime &&\n> +\ttest_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n> +\tgit checkout side &&\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +\tgit rebase -r --root --committer-date-is-author-date &&\n> +\tgit log --pretty=%ai >authortime &&\n> +\tgit log --pretty=%ci >committertime &&\n> +\ttest_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n> +\tgit checkout side &&\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n> +\tgit log --pretty=%ai >authortime &&\n> +\tgit log --pretty=%ci >committertime &&\n> +\ttest_cmp authortime committertime\n> +\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n> +\tgit checkout commit2 &&\n> +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n> +\tgit log -1 --format=%at HEAD >expect &&\n> +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n> +\t\t--onto HEAD^^ HEAD^ &&\n> +\techo resolved > foo &&\n> +\tgit add foo &&\n> +\tgit rebase --continue &&\n> +\tgit log -1 --format=%ct HEAD >actual &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  # This must be the last test in this file\n>  test_expect_success '$EDITOR and friends are unchanged' '\n>  \ttest_editor_unchanged\n> --\n> 2.26.2\n>\n>\n"},{"id":"398906","messageId":"nycvar.QRO.7.76.6.2005290456190.56@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"20200528131701.GD1983@danh.dev","subject":"Re: [PATCH v4 6/5] fixup! rebase: add --reset-author-date","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-05-29T02:59:10Z","receivedAt":"2020-05-29T19:33:00Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 May 2020, Đoàn Trần Công Danh wrote:\n\n> On 2020-05-27 18:57:48+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> > From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> >\n> > Sorry I somehow forgot to commit this before sending the v4 patches,\n> > it fixes up the final patch\n> >\n> > Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> > ---\n> >  t/t3436-rebase-more-options.sh | 2 +-\n> >  1 file changed, 1 insertion(+), 1 deletion(-)\n> >\n> > diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> > index 5ee193f333..ecfd68397f 100755\n> > --- a/t/t3436-rebase-more-options.sh\n> > +++ b/t/t3436-rebase-more-options.sh\n> > @@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n> >  \tgit rebase --apply --ignore-date HEAD^ &&\n> >  \tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n> >  \tgit rebase -m --ignore-date HEAD^ &&\n> > -\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n> > +\tgit log -2 --pretty=%ai >authortime &&\n> >  \tgrep \"+0000\" authortime >output &&\n> >  \ttest_line_count = 2 output\n> >  '\n>\n> This version addressed all of my concerns, LGTM.\n>\n> Only the last\n>\n> \ttest_line_count = 2 output\n>\n> puzzled me at first.\n> Since it's the only usage of test_line_count in this version\n> Turn out, it's equivalence with:\n> -----------8<-----------\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index ecfd68397f..abe9af4d8c 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -197,8 +197,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n>  \tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n>  \tgit rebase -m --ignore-date HEAD^ &&\n>  \tgit log -2 --pretty=%ai >authortime &&\n> -\tgrep \"+0000\" authortime >output &&\n> -\ttest_line_count = 2 output\n> +\t! grep -v \"+0000\" authortime\n>  '\n>\n>  # This must be the last test in this file\n> ------>8------\n\nGood suggestion!\n\nI've read through all 5 patches, and rather than repeating much of what I\nsaid about 1/5 and 2/5 in 4/5, I'll just say it here that it applies\nthere, too: less repetitions in the test script, and I'd prefer the layer\nwhere the `apply` vs `merge` options are set to be `cmd__rebase()` rather\nthan `run_am()` (and `get_replay_opts()`).\n\nAll in all, it was a pleasant read.\n\nThanks,\nDscho\n"},{"id":"398973","messageId":"AM0PR02MB40817D1733D2070B8E0154B39C8A0@AM0PR02MB4081.eurprd02.prod.outlook.com","threadId":"53176","inReplyTo":"nycvar.QRO.7.76.6.2005290437350.56@tvgsbejvaqbjf.bet","subject":"RE: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Kerry, Richard","fromEmail":"richard.kerry@atos.net","sentAt":"2020-06-01T09:23:01Z","receivedAt":"2020-06-01T09:23:15Z","isPatch":true,"sender":{"key":"richard.kerry@atos.net","avatar":null},"body":"\nAs a non-native speaker, I am thrown off when reading \"available to\"\ninstead of the grammatically correct (I believe) \"available in\". Likewise, \"on going\" instead of \"ongoing\" just disrupts my workflow.\n\nMaybe these can be fixed?\n\n[RK] There is a distinct difference between \"available to\" and \"available in\".\n[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.\n[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.\n\n[RK] As for the other issue, I too would suggest \"ongoing\".\n\n[RK] Regards,\n[RK] Richard.\n\n"},{"id":"398974","messageId":"5003e918-5f24-2bf1-fbb0-1730961af8d7@gmail.com","threadId":"53176","inReplyTo":"nycvar.QRO.7.76.6.2005290437350.56@tvgsbejvaqbjf.bet","subject":"Re: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-01T10:26:08Z","receivedAt":"2020-06-01T10:26:14Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi dscho\n\nThanks for taking a look at this\n\nOn 29/05/2020 03:38, Johannes Schindelin wrote:\n> Hi Phillip,\n> \n> sorry to be _so_ late in the game. (And sorry for sending this to you\n> twice, I managed to skip all the Cc:s due to the Reply-To: header the\n> first time round.)\n> \n> On Wed, 27 May 2020, Phillip Wood wrote:\n> \n>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>>\n>> Rebase is implemented with two different backends - 'apply' and 'merge'\n>> each of which support a different set of options. In particuar the apply\n>> backend supports a number of options implemented by 'git am' that are\n>> not available to the merge backend. As part of an on going effort to\n> \n> As a non-native speaker, I am thrown off when reading \"available to\"\n> instead of the grammatically correct (I believe) \"available in\". Likewise,\n> \"on going\" instead of \"ongoing\" just disrupts my workflow.\n> \n> Maybe these can be fixed?\n\nSure\n\n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index 27a07d4e78..5d8e117276 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -86,6 +86,7 @@ struct rebase_options {\n>>  \tint signoff;\n>>  \tint allow_rerere_autoupdate;\n>>  \tint autosquash;\n>> +\tint ignore_whitespace;\n>>  \tchar *gpg_sign_opt;\n>>  \tint autostash;\n>>  \tchar *cmd;\n>> @@ -108,6 +109,7 @@ struct rebase_options {\n>>\n>>  static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>  {\n>> +\tstruct strbuf strategy_buf = STRBUF_INIT;\n>>  \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n>>\n>>  \treplay.action = REPLAY_INTERACTIVE_REBASE;\n>> @@ -126,14 +128,20 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>>  \treplay.strategy = opts->strategy;\n>> +\n>>  \tif (opts->strategy_opts)\n>> -\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n>> +\t\tstrbuf_addstr(&strategy_buf, opts->strategy_opts);\n>> +\tif (opts->ignore_whitespace)\n>> +\t\tstrbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n>> +\tif (strategy_buf.len)\n>> +\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n> \n> Quite honestly, this is very, very ugly.\n> \n> I would have expected this at a way earlier layer, namely in\n> `cmd__rebase()`. Something along these lines:\n\nYes your version is definitely better, I'll update with that (I had left\nthis patch mostly alone as unlike the later ones the original actually\nworked)\n\n> \n> -- snip --\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 37ba76ac3d26..748e08aee2f2 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -1289,6 +1289,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \tstruct strbuf revisions = STRBUF_INIT;\n>  \tstruct strbuf buf = STRBUF_INIT;\n>  \tstruct object_id merge_base;\n> +\tint ignore_whitespace = 0;\n>  \tenum action action = ACTION_NONE;\n>  \tconst char *gpg_sign = NULL;\n>  \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n> @@ -1318,9 +1319,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>  \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>  \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n> -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n> -\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n> -\t\t\t\t  PARSE_OPT_NOARG),\n> +\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n> +\t\t\t N_(\"passed to 'git am'\")),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>  \t\t\t\t  &options.git_am_opts, NULL,\n>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> @@ -1682,6 +1682,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\timply_merge(&options, \"--rebase-merges\");\n>  \t}\n> \n> +\tif (ignore_whitespace) {\n> +\t\tif (options.type == REBASE_APPLY)\n> +\t\t\targv_array_push(&options.git_am_opts,\n> +\t\t\t\t\t\"--ignore-whitespace\");\n> +\t\telse\n> +\t\t\tstring_list_append(&stragey_options,\n> +\t\t\t\t\t   \"--ignore-space-change\");\n> +\t}\n> +\n>  \tif (strategy_options.nr) {\n>  \t\tint i;\n> \n> -- snap --\n> \n> \n>>\n>>  \tif (opts->squash_onto) {\n>>  \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n>>  \t\treplay.have_squash_onto = 1;\n>>  \t}\n>>\n>> +\tstrbuf_release(&strategy_buf);\n>>  \treturn replay;\n>>  }\n>>\n>> @@ -539,6 +547,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>>  \targc = parse_options(argc, argv, prefix, options,\n>>  \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n>>\n>> +\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n> \n> I am not sure what this is about: `opts.strategy_opts` is of type `char\n> *`, i.e. it is supposed to be already allocated.\n> \n> Not that `cmd_rebase__interactive()` matters _all_ that much anymore, of\n> course: it is only used by the --preserve-merges backend, which will\n> hopefully be retired soon.\n> \n>> +\n>>  \tif (!is_null_oid(&squash_onto))\n>>  \t\topts.squash_onto = &squash_onto;\n>>\n>> @@ -991,6 +1001,8 @@ static int run_am(struct rebase_options *opts)\n>>  \tam.git_cmd = 1;\n>>  \targv_array_push(&am.args, \"am\");\n>>\n>> +\tif (opts->ignore_whitespace)\n>> +\t\targv_array_push(&am.args, \"--ignore-whitespace\");\n>>  \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n>>  \t\targv_array_push(&am.args, \"--resolved\");\n>>  \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n>> @@ -1495,16 +1507,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>  \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>>  \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>>  \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n>> -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n>> -\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n>> -\t\t\t\t  PARSE_OPT_NOARG),\n>>  \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>>  \t\t\t\t  &options.git_am_opts, NULL,\n>>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>>  \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>>  \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>>  \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n>> +\t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n>> +\t\t\t N_(\"ignore changes in whitespace\")),\n>>  \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>>  \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>>  \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>> index 50e7960702..55ca46786d 100755\n>> --- a/t/t3422-rebase-incompatible-options.sh\n>> +++ b/t/t3422-rebase-incompatible-options.sh\n>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>  }\n>>\n>>  test_rebase_am_only --whitespace=fix\n>> -test_rebase_am_only --ignore-whitespace\n>>  test_rebase_am_only --committer-date-is-author-date\n>>  test_rebase_am_only -C4\n>>\n>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>> new file mode 100755\n>> index 0000000000..fb5e747e86\n>> --- /dev/null\n>> +++ b/t/t3436-rebase-more-options.sh\n>> @@ -0,0 +1,86 @@\n>> +#!/bin/sh\n>> +#\n>> +# Copyright (c) 2019 Rohit Ashiwal\n>> +#\n>> +\n>> +test_description='tests to ensure compatibility between am and interactive backends'\n>> +\n>> +. ./test-lib.sh\n>> +\n>> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n>> +\n>> +# This is a special case in which both am and interactive backends\n>> +# provide the same output. It was done intentionally because\n>> +# both the backends fall short of optimal behaviour.\n>> +test_expect_success 'setup' '\n>> +\tgit checkout -b topic &&\n>> +\tq_to_tab >file <<-\\EOF &&\n>> +\tline 1\n>> +\tQline 2\n>> +\tline 3\n>> +\tEOF\n>> +\tgit add file &&\n>> +\tgit commit -m \"add file\" &&\n>> +\tcat >file <<-\\EOF &&\n>> +\tline 1\n>> +\tnew line 2\n>> +\tline 3\n>> +\tEOF\n>> +\tgit commit -am \"update file\" &&\n>> +\tgit tag side &&\n>> +\n>> +\tgit checkout --orphan master &&\n>> +\tsed -e \"s/^|//\" >file <<-\\EOF &&\n>> +\t|line 1\n>> +\t|        line 2\n>> +\t|line 3\n>> +\tEOF\n>> +\tgit add file &&\n>> +\tgit commit -m \"add file\" &&\n>> +\tgit tag main\n>> +'\n> \n> The file contents are repeated in an awfully repetitive manner. That not\n> only makes things a bit hard to read, it also makes it all too easy to\n> slip in bugs by mistake. How about something like this instead?\n> \n> \ttest_commit file &&\n> \n> \ttest_write_lines line1 Qline2 line3 >templ &&\n> \n> \tq_to_tab <templ >file.t &&\n> \tgit commit -m tab file.t &&\n> \n> \tsed \"s/Q/new /\" <templ >file.t &&\n> \tgit commit -m new file.t &&\n> \tgit tag side &&\n> \n> \tgit checkout file -- &&\n> \tsed \"s/Q/        /\" <templ >file.t &&\n> \tgit commit -m spaces file.t\n\nI'm not totally convinced by this, I'd prefer to be able to read the\ncontents rather than having to work out what sed is doing. What about\n\ntest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\nadd and commit\ntest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\ncommit and tag\ntest_write_lines \"line 1\" \"  line 2\" \"line 3\" >file &&\ncommit and tag\n\nIt does not get rid of the repetition but it does dispense with having\nthe work out what sed and q_to_tab are doing\n\n> ... and then...\n> \n>> +\n>> +test_expect_success '--ignore-whitespace works with apply backend' '\n>> +\tcat >expect <<-\\EOF &&\n>> +\tline 1\n>> +\tnew line 2\n>> +\tline 3\n>> +\tEOF\n> \n> \tsed \"s/Q/new /\" <templ >expect\n> \n>> +\ttest_must_fail git rebase --apply main side &&\n>> +\tgit rebase --abort &&\n>> +\tgit rebase --apply --ignore-whitespace main side &&\n>> +\ttest_cmp expect file\n> \n> Personally, I prefer to read the contents of `expect` directly before the\n> `test_cmp expect file.t`\n\nI can move it but if we use sed you cannot see the contents\n\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace works with merge backend' '\n>> +\tcat >expect <<-\\EOF &&\n>> +\tline 1\n>> +\tnew line 2\n>> +\tline 3\n>> +\tEOF\n> \n> Isn't this totally identical to the `expect` constructed earlier? And in\n> any case, isn't this identical to `git show main:file.t`, which is what we\n> _actually_ expect: for the file contents to be identical to the tagged\n> `main`? I.e.\n\nWell spotted I'll update (I think it's actually the same as side)\n\n> \tgit diff --exit-code main\n> \n>> +\ttest_must_fail git rebase --merge main side &&\n>> +\tgit rebase --abort &&\n>> +\tgit rebase --merge --ignore-whitespace main side &&\n>> +\ttest_cmp expect file\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n>> +\tcat >expect <<-\\EOF &&\n>> +\tline 1\n>> +\tnew line 2\n>> +\tline 3\n>> +\tEOF\n>> +\t(\n>> +\t\tset_fake_editor &&\n>> +\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n>> +\t) &&\n>> +\tgit rebase --continue &&\n>> +\ttest_cmp expect file\n> \n> It is a bit funny to see these two invocations _specifically_ pulled out\n> from the subshell, that's not how we do things in other test scripts:\n> instead, we run all the Git commands _inside_ the subshell, and all the\n> verifications after the subshell.\n\nThe idea was to only set the variable where it is used.\n\nBest Wishes\n\nPhillip\n\n> I believe that with my suggestions, this test script will be a ton easier\n> to read and to maintain. At least it will be a lot DRYer.\n> \n> Ciao,\n> Dscho\n> \n>> +'\n>> +\n>> +# This must be the last test in this file\n>> +test_expect_success '$EDITOR and friends are unchanged' '\n>> +\ttest_editor_unchanged\n>> +'\n>> +\n>> +test_done\n>> --\n>> 2.26.2\n>>\n>>\n\n"},{"id":"398975","messageId":"eb1d1067-ad1e-167e-747e-b04debf7d844@gmail.com","threadId":"53176","inReplyTo":"nycvar.QRO.7.76.6.2005290439030.56@tvgsbejvaqbjf.bet","subject":"Re: [PATCH v4 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-01T10:33:50Z","receivedAt":"2020-06-01T10:33:57Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi dscho\n\nOn 29/05/2020 03:52, Johannes Schindelin wrote:\n> Hi Phillip,\n> \n> On Wed, 27 May 2020, Phillip Wood wrote:\n> \n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> As part of the on-going effort to retire the apply rebase backend teach\n>> the merge backend how to handle --committer-date-is-author-date.\n> \n> I forgot to mention this in my reply to the first patch in this series: it\n> strikes me as a mis-characterization that the `apply` backend is about to\n> be retired. What _is_ true is that the `merge` backend is the default\n> backend, and what is even more true is that it is cumbersome if certain\n> `rebase` options cannot be combined because they are only implemented by\n> one of both rebase backends.\n\nI'm not trying to imply that the apply backend is about to be retired\nbut it is the long term plan to get rid of it isn't it?\n\n> \n>>\n>> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> ---\n>>  Documentation/git-rebase.txt           | 10 +++--\n>>  builtin/rebase.c                       | 16 ++++---\n>>  sequencer.c                            | 59 +++++++++++++++++++++++++-\n>>  sequencer.h                            |  1 +\n>>  t/t3422-rebase-incompatible-options.sh |  1 -\n>>  t/t3436-rebase-more-options.sh         | 56 ++++++++++++++++++++++++\n>>  6 files changed, 133 insertions(+), 10 deletions(-)\n>>\n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index 5d8e117276..357cd6acf3 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -89,6 +89,7 @@ struct rebase_options {\n>>  \tint ignore_whitespace;\n>>  \tchar *gpg_sign_opt;\n>>  \tint autostash;\n>> +\tint committer_date_is_author_date;\n>>  \tchar *cmd;\n>>  \tint allow_empty_message;\n>>  \tint rebase_merges, rebase_cousins;\n>> @@ -126,6 +127,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>  \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n>>  \treplay.verbose = opts->flags & REBASE_VERBOSE;\n>>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>> +\treplay.committer_date_is_author_date =\n>> +\t\t\t\t\topts->committer_date_is_author_date;\n>>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>>  \treplay.strategy = opts->strategy;\n>>\n>> @@ -1003,6 +1006,8 @@ static int run_am(struct rebase_options *opts)\n>>\n>>  \tif (opts->ignore_whitespace)\n>>  \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n>> +\tif (opts->committer_date_is_author_date)\n>> +\t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n> \n> As before, I would rather see this in `cmd__rebase()` rahn in `run_am()`.\n\nRight I'll take a look at that\n\n>>  \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n>>  \t\targv_array_push(&am.args, \"--resolved\");\n>>  \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n>> @@ -1507,9 +1512,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>  \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>>  \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>>  \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n>> -\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>> -\t\t\t\t  &options.git_am_opts, NULL,\n>> -\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>> +\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n>> +\t\t\t &options.committer_date_is_author_date,\n>> +\t\t\t N_(\"make committer date match author date\")),\n>>  \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>>  \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>> @@ -1804,11 +1809,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>  \t    options.autosquash) {\n>>  \t\tallow_preemptive_ff = 0;\n>>  \t}\n>> +\tif (options.committer_date_is_author_date)\n>> +\t\toptions.flags |= REBASE_FORCE;\n>>\n>>  \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n>>  \t\tconst char *option = options.git_am_opts.argv[i], *p;\n>> -\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n>> -\t\t    !strcmp(option, \"--ignore-date\") ||\n>> +\t\tif (!strcmp(option, \"--ignore-date\") ||\n>>  \t\t    !strcmp(option, \"--whitespace=fix\") ||\n>>  \t\t    !strcmp(option, \"--whitespace=strip\"))\n>>  \t\t\tallow_preemptive_ff = 0;\n>> diff --git a/sequencer.c b/sequencer.c\n>> index 6fd2674632..8826c6325b 100644\n>> --- a/sequencer.c\n>> +++ b/sequencer.c\n>> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>>   * command-line.\n>>   */\n>>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n>> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n>> @@ -872,6 +873,22 @@ static char *get_author(const char *message)\n>>  \treturn NULL;\n>>  }\n>>\n>> +static const char *author_date_from_env_array(const struct argv_array *env)\n>> +{\n>> +\tint i;\n>> +\tconst char *date;\n>> +\n>> +\tfor (i = 0; i < env->argc; i++)\n>> +\t\tif (skip_prefix(env->argv[i],\n>> +\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n>> +\t\t\treturn date;\n>> +\t/*\n>> +\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n>> +\t * reading the script\n>> +\t */\n>> +\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n>> +}\n>> +\n>>  static const char staged_changes_advice[] =\n>>  N_(\"you have staged changes in your working tree\\n\"\n>>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n>> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n>>  \t\t\t     gpg_opt, gpg_opt);\n>>  \t}\n>>\n>> +\tif (opts->committer_date_is_author_date)\n>> +\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>> +\t\t\t\t author_date_from_env_array(&cmd.env_array));\n>> +\n>>  \targv_array_push(&cmd.args, \"commit\");\n>>\n>>  \tif (!(flags & VERIFY_MSG))\n>> @@ -1349,6 +1370,30 @@ static int try_to_commit(struct repository *r,\n>>  \t\tcommit_list_insert(current_head, &parents);\n>>  \t}\n>>\n>> +\tif (opts->committer_date_is_author_date) {\n>> +\t\tint len = strlen(author);\n> \n> Given that `len` is used only once, is this local variable really\n> necessary? You could just as well pass `(int)strlen(author)` in the\n> `split_ident_line()` call below.\n\nI wonder if it makes the `split_ident_line()` line too long, I'll take a\nlook.\n\n>> +\t\tstruct ident_split ident;\n>> +\t\tstruct strbuf date = STRBUF_INIT;\n>> +\n>> +\t\tif (split_ident_line(&ident, author, len) < 0) {\n>> +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n>> +\t\t\tgoto out;\n>> +\t\t}\n>> +\t\tif (!ident.date_begin) {\n>> +\t\t\tres = error(_(\"corrupted author without date information\"));\n>> +\t\t\tgoto out;\n>> +\t\t}\n>> +\n>> +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n>> +\t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n>> +\t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n>> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n>> +\t\tstrbuf_release(&date);\n> \n> It might be easier to read if it was written this way:\n> \n> \t\tif (split_ident_line(...) < 0)\n> \t\t\tres = ...\n> \t\telse if (!ident.date_begin)\n> \t\t\tres = ...\n> \t\telse {\n> \t\t\tstrbuf_addf(...)\n> \t\t\tres = ...\n> \t\t\tstrbuf_release(&date);\n> \t\t}\n> \n> \t\tif (res)\n> \t\t\tgoto out;\n\nI'm not sure. The current style of \"if there's an error goto out\" makes\nthe control flow clear without having to reason ones way through a\nseries of else ifs\n\n>> +\n>> +\t\tif (res)\n>> +\t\t\tgoto out;\n>> +\t}\n>> +\n>>  \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>>  \t\tres = error(_(\"git write-tree failed to write a tree\"));\n>>  \t\tgoto out;\n>> @@ -2532,6 +2577,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>>  \t\t\topts->signoff = 1;\n>>  \t\t}\n>>\n>> +\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n>> +\t\t\topts->allow_ff = 0;\n>> +\t\t\topts->committer_date_is_author_date = 1;\n>> +\t\t}\n>> +\n>>  \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n>>  \t\t\topts->reschedule_failed_exec = 1;\n>>\n>> @@ -2622,6 +2672,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>>  \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>>  \tif (opts->keep_redundant_commits)\n>>  \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n>> +\tif (opts->committer_date_is_author_date)\n>> +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>>  \tif (opts->reschedule_failed_exec)\n>>  \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>>\n>> @@ -3542,6 +3594,10 @@ static int do_merge(struct repository *r,\n>>  \t\t\tgoto leave_merge;\n>>  \t\t}\n>>\n>> +\t\tif (opts->committer_date_is_author_date)\n>> +\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>> +\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n>> +\n>>  \t\tcmd.git_cmd = 1;\n>>  \t\targv_array_push(&cmd.args, \"merge\");\n>>  \t\targv_array_push(&cmd.args, \"-s\");\n>> @@ -3819,7 +3875,8 @@ static int pick_commits(struct repository *r,\n>>  \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>>  \tif (opts->allow_ff)\n>>  \t\tassert(!(opts->signoff || opts->no_commit ||\n>> -\t\t\t\topts->record_origin || opts->edit));\n>> +\t\t\t\topts->record_origin || opts->edit ||\n>> +\t\t\t\topts->committer_date_is_author_date));\n>>  \tif (read_and_refresh_cache(r, opts))\n>>  \t\treturn -1;\n>>\n>> diff --git a/sequencer.h b/sequencer.h\n>> index 0bee85093e..4ab94119ae 100644\n>> --- a/sequencer.h\n>> +++ b/sequencer.h\n>> @@ -45,6 +45,7 @@ struct replay_opts {\n>>  \tint verbose;\n>>  \tint quiet;\n>>  \tint reschedule_failed_exec;\n>> +\tint committer_date_is_author_date;\n>>\n>>  \tint mainline;\n>>\n>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>> index 55ca46786d..c8234062c6 100755\n>> --- a/t/t3422-rebase-incompatible-options.sh\n>> +++ b/t/t3422-rebase-incompatible-options.sh\n>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>  }\n>>\n>>  test_rebase_am_only --whitespace=fix\n>> -test_rebase_am_only --committer-date-is-author-date\n>>  test_rebase_am_only -C4\n>>\n>>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>> index fb5e747e86..7e68fb9753 100755\n>> --- a/t/t3436-rebase-more-options.sh\n>> +++ b/t/t3436-rebase-more-options.sh\n>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>>\n>>  . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>>\n>> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n>> +export GIT_AUTHOR_DATE\n>> +\n>>  # This is a special case in which both am and interactive backends\n>>  # provide the same output. It was done intentionally because\n>>  # both the backends fall short of optimal behaviour.\n>> @@ -28,8 +31,13 @@ test_expect_success 'setup' '\n>>  \tEOF\n>>  \tgit commit -am \"update file\" &&\n>>  \tgit tag side &&\n>> +\ttest_commit commit1 foo foo1 &&\n>> +\ttest_commit commit2 foo foo2 &&\n>> +\ttest_commit commit3 foo foo3 &&\n>>\n>>  \tgit checkout --orphan master &&\n>> +\tgit rm --cached foo &&\n>> +\trm foo &&\n>>  \tsed -e \"s/^|//\" >file <<-\\EOF &&\n>>  \t|line 1\n>>  \t|        line 2\n>> @@ -78,6 +86,54 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n>>  \ttest_cmp expect file\n>>  '\n>>\n>> +test_expect_success '--committer-date-is-author-date works with apply backend' '\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>> +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n>> +\tgit log -1 --pretty=%ai >authortime &&\n>> +\tgit log -1 --pretty=%ci >committertime &&\n>> +\ttest_cmp authortime committertime\n> \n> This seems to be a repeated pattern. To dry it up, it would make sense to\n> do this:\n> \n> \ttest_ctime_is_atime () {\n> \t\tgit log -1 --pretty=%ai >authortime &&\n> \t\tgit log -1 --pretty=%ci >committertime &&\n> \t\ttest_cmp authortime committertime\n> \t}\n\nGood suggestion (though we need to parametrize the -1 so we can use it\nwith the rebase --root cases)\n\nThanks\n\nPhillip\n\n> \n> Ciao,\n> Dscho\n> \n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with merge backend' '\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>> +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n>> +\tgit log -1 --pretty=%ai >authortime &&\n>> +\tgit log -1 --pretty=%ci >committertime &&\n>> +\ttest_cmp authortime committertime\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>> +\tgit checkout side &&\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>> +\tgit rebase -r --root --committer-date-is-author-date &&\n>> +\tgit log --pretty=%ai >authortime &&\n>> +\tgit log --pretty=%ci >committertime &&\n>> +\ttest_cmp authortime committertime\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n>> +\tgit checkout side &&\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>> +\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n>> +\tgit log --pretty=%ai >authortime &&\n>> +\tgit log --pretty=%ci >committertime &&\n>> +\ttest_cmp authortime committertime\n>> +\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n>> +\tgit checkout commit2 &&\n>> +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n>> +\tgit log -1 --format=%at HEAD >expect &&\n>> +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n>> +\t\t--onto HEAD^^ HEAD^ &&\n>> +\techo resolved > foo &&\n>> +\tgit add foo &&\n>> +\tgit rebase --continue &&\n>> +\tgit log -1 --format=%ct HEAD >actual &&\n>> +\ttest_cmp expect actual\n>> +'\n>> +\n>>  # This must be the last test in this file\n>>  test_expect_success '$EDITOR and friends are unchanged' '\n>>  \ttest_editor_unchanged\n>> --\n>> 2.26.2\n>>\n>>\n\n"},{"id":"398976","messageId":"b2c24c50-3e07-55d8-52f7-4573292f6695@gmail.com","threadId":"53176","inReplyTo":"nycvar.QRO.7.76.6.2005290456190.56@tvgsbejvaqbjf.bet","subject":"Re: [PATCH v4 6/5] fixup! rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-01T10:36:20Z","receivedAt":"2020-06-01T10:36:29Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi dscho and Danh\n\nOn 29/05/2020 03:59, Johannes Schindelin wrote:\n> Hi,\n> \n> On Thu, 28 May 2020, Đoàn Trần Công Danh wrote:\n> \n>> On 2020-05-27 18:57:48+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>>\n>>> Sorry I somehow forgot to commit this before sending the v4 patches,\n>>> it fixes up the final patch\n>>>\n>>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>> ---\n>>>  t/t3436-rebase-more-options.sh | 2 +-\n>>>  1 file changed, 1 insertion(+), 1 deletion(-)\n>>>\n>>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>>> index 5ee193f333..ecfd68397f 100755\n>>> --- a/t/t3436-rebase-more-options.sh\n>>> +++ b/t/t3436-rebase-more-options.sh\n>>> @@ -196,7 +196,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n>>>  \tgit rebase --apply --ignore-date HEAD^ &&\n>>>  \tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n>>>  \tgit rebase -m --ignore-date HEAD^ &&\n>>> -\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n>>> +\tgit log -2 --pretty=%ai >authortime &&\n>>>  \tgrep \"+0000\" authortime >output &&\n>>>  \ttest_line_count = 2 output\n>>>  '\n>>\n>> This version addressed all of my concerns, LGTM.\n>>\n>> Only the last\n>>\n>> \ttest_line_count = 2 output\n>>\n>> puzzled me at first.\n>> Since it's the only usage of test_line_count in this version\n>> Turn out, it's equivalence with:\n>> -----------8<-----------\n>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>> index ecfd68397f..abe9af4d8c 100755\n>> --- a/t/t3436-rebase-more-options.sh\n>> +++ b/t/t3436-rebase-more-options.sh\n>> @@ -197,8 +197,7 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n>>  \tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n>>  \tgit rebase -m --ignore-date HEAD^ &&\n>>  \tgit log -2 --pretty=%ai >authortime &&\n>> -\tgrep \"+0000\" authortime >output &&\n>> -\ttest_line_count = 2 output\n>> +\t! grep -v \"+0000\" authortime\n>>  '\n>>\n>>  # This must be the last test in this file\n>> ------>8------\n> \n> Good suggestion!\n\nYes thanks Danh I'll update with that\n\n> I've read through all 5 patches, and rather than repeating much of what I\n> said about 1/5 and 2/5 in 4/5, I'll just say it here that it applies\n> there, too: less repetitions in the test script,\n\nI'll look at adding a helper for to do the checks\n\n> and I'd prefer the layer\n> where the `apply` vs `merge` options are set to be `cmd__rebase()` rather\n> than `run_am()` (and `get_replay_opts()`).\n\nYeah that would make it nicer.\n\n> All in all, it was a pleasant read.\n\nThanks for your comments on this series\n\nPhillip\n\n> Thanks,\n> Dscho\n> \n\n"},{"id":"398999","messageId":"nycvar.QRO.7.76.6.2006012300460.56@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"5003e918-5f24-2bf1-fbb0-1730961af8d7@gmail.com","subject":"Re: [PATCH v4 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-06-01T21:03:05Z","receivedAt":"2020-06-01T21:03:19Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Mon, 1 Jun 2020, Phillip Wood wrote:\n\n> On 29/05/2020 03:38, Johannes Schindelin wrote:\n> >\n> > On Wed, 27 May 2020, Phillip Wood wrote:\n> >\n> >> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> >>\n> >> [...]\n> >> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> >> new file mode 100755\n> >> index 0000000000..fb5e747e86\n> >> --- /dev/null\n> >> +++ b/t/t3436-rebase-more-options.sh\n> >> @@ -0,0 +1,86 @@\n> >> +#!/bin/sh\n> >> +#\n> >> +# Copyright (c) 2019 Rohit Ashiwal\n> >> +#\n> >> +\n> >> +test_description='tests to ensure compatibility between am and interactive backends'\n> >> +\n> >> +. ./test-lib.sh\n> >> +\n> >> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n> >> +\n> >> +# This is a special case in which both am and interactive backends\n> >> +# provide the same output. It was done intentionally because\n> >> +# both the backends fall short of optimal behaviour.\n> >> +test_expect_success 'setup' '\n> >> +\tgit checkout -b topic &&\n> >> +\tq_to_tab >file <<-\\EOF &&\n> >> +\tline 1\n> >> +\tQline 2\n> >> +\tline 3\n> >> +\tEOF\n> >> +\tgit add file &&\n> >> +\tgit commit -m \"add file\" &&\n> >> +\tcat >file <<-\\EOF &&\n> >> +\tline 1\n> >> +\tnew line 2\n> >> +\tline 3\n> >> +\tEOF\n> >> +\tgit commit -am \"update file\" &&\n> >> +\tgit tag side &&\n> >> +\n> >> +\tgit checkout --orphan master &&\n> >> +\tsed -e \"s/^|//\" >file <<-\\EOF &&\n> >> +\t|line 1\n> >> +\t|        line 2\n> >> +\t|line 3\n> >> +\tEOF\n> >> +\tgit add file &&\n> >> +\tgit commit -m \"add file\" &&\n> >> +\tgit tag main\n> >> +'\n> >\n> > The file contents are repeated in an awfully repetitive manner. That not\n> > only makes things a bit hard to read, it also makes it all too easy to\n> > slip in bugs by mistake. How about something like this instead?\n> >\n> > \ttest_commit file &&\n> >\n> > \ttest_write_lines line1 Qline2 line3 >templ &&\n> >\n> > \tq_to_tab <templ >file.t &&\n> > \tgit commit -m tab file.t &&\n> >\n> > \tsed \"s/Q/new /\" <templ >file.t &&\n> > \tgit commit -m new file.t &&\n> > \tgit tag side &&\n> >\n> > \tgit checkout file -- &&\n> > \tsed \"s/Q/        /\" <templ >file.t &&\n> > \tgit commit -m spaces file.t\n>\n> I'm not totally convinced by this, I'd prefer to be able to read the\n> contents rather than having to work out what sed is doing. What about\n>\n> test_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n> add and commit\n> test_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n> commit and tag\n> test_write_lines \"line 1\" \"  line 2\" \"line 3\" >file &&\n> commit and tag\n>\n> It does not get rid of the repetition but it does dispense with having\n> the work out what sed and q_to_tab are doing\n\nSure. Your version is still tons easier to parse for a human being.\n\n> > \tgit diff --exit-code main\n> >\n> >> +\ttest_must_fail git rebase --merge main side &&\n> >> +\tgit rebase --abort &&\n> >> +\tgit rebase --merge --ignore-whitespace main side &&\n> >> +\ttest_cmp expect file\n> >> +'\n> >> +\n> >> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n> >> +\tcat >expect <<-\\EOF &&\n> >> +\tline 1\n> >> +\tnew line 2\n> >> +\tline 3\n> >> +\tEOF\n> >> +\t(\n> >> +\t\tset_fake_editor &&\n> >> +\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n> >> +\t) &&\n> >> +\tgit rebase --continue &&\n> >> +\ttest_cmp expect file\n> >\n> > It is a bit funny to see these two invocations _specifically_ pulled out\n> > from the subshell, that's not how we do things in other test scripts:\n> > instead, we run all the Git commands _inside_ the subshell, and all the\n> > verifications after the subshell.\n>\n> The idea was to only set the variable where it is used.\n\nI understand that, but I think that it would be better to follow the\nexisting pattern rather than introducing an inconsistent second one.\n\nThanks,\nDscho\n"},{"id":"400661","messageId":"20200626095528.117524-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH v5 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T09:55:23Z","receivedAt":"2020-06-26T09:55:41Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nI've updated the commit messages, option handling and tests as\nsuggested by dscho. I've also changed the tests that used\n'--strategy=resolve' to use a real external merge strategy so they\ncontinue to test the same code path once Alban's patches to handle the\nresolve strategy without forking are merged\n\nThanks for the review\n\nPhillip\n\nPhillip Wood (2):\n  rebase -i: support --committer-date-is-author-date\n  rebase -i: support --ignore-date\n\nRohit Ashiwal (3):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: rename amend_author to author_to_free\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt           |  33 ++++-\n builtin/rebase.c                       |  44 ++++--\n sequencer.c                            | 112 ++++++++++++++-\n sequencer.h                            |   2 +\n t/t3422-rebase-incompatible-options.sh |   2 -\n t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++\n 6 files changed, 350 insertions(+), 23 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\nRange-diff against v4:\n1:  df8c4ed2e9 ! 1:  43ee10d4d5 rebase -i: add --ignore-whitespace flag\n    @@ Metadata\n      ## Commit message ##\n         rebase -i: add --ignore-whitespace flag\n     \n    -    Rebase is implemented with two different backends - 'apply' and 'merge'\n    -    each of which support a different set of options. In particuar the apply\n    -    backend supports a number of options implemented by 'git am' that are\n    -    not available to the merge backend. As part of an on going effort to\n    -    remove the apply backend this patch adds support for the\n    +    Rebase is implemented with two different backends - 'apply' and\n    +    'merge' each of which support a different set of options. In\n    +    particular the apply backend supports a number of options implemented\n    +    by 'git am' that are not implemented in the merge backend. This means\n    +    that the available options are different depending on which backend is\n    +    used which is confusing. This patch adds support for the\n         --ignore-whitespace option to the merge backend. This option treats\n         lines with only whitespace changes as unchanged and is implemented in\n         the merge backend by translating it to -Xignore-space-change.\n    @@ Documentation/git-rebase.txt: In addition, the following pairs of options are in\n      \n     \n      ## builtin/rebase.c ##\n    -@@ builtin/rebase.c: struct rebase_options {\n    - \tint signoff;\n    - \tint allow_rerere_autoupdate;\n    - \tint autosquash;\n    -+\tint ignore_whitespace;\n    - \tchar *gpg_sign_opt;\n    - \tint autostash;\n    - \tchar *cmd;\n    -@@ builtin/rebase.c: struct rebase_options {\n    - \n    - static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n    - {\n    -+\tstruct strbuf strategy_buf = STRBUF_INIT;\n    - \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n    - \n    - \treplay.action = REPLAY_INTERACTIVE_REBASE;\n     @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n      \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n      \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n      \treplay.strategy = opts->strategy;\n     +\n      \tif (opts->strategy_opts)\n    --\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n    -+\t\tstrbuf_addstr(&strategy_buf, opts->strategy_opts);\n    -+\tif (opts->ignore_whitespace)\n    -+\t\tstrbuf_addstr(&strategy_buf, \" --ignore-space-change\");\n    -+\tif (strategy_buf.len)\n    -+\t\tparse_strategy_opts(&replay, strategy_buf.buf);\n    - \n    - \tif (opts->squash_onto) {\n    - \t\toidcpy(&replay.squash_onto, opts->squash_onto);\n    - \t\treplay.have_squash_onto = 1;\n    - \t}\n    - \n    -+\tstrbuf_release(&strategy_buf);\n    - \treturn replay;\n    - }\n    - \n    -@@ builtin/rebase.c: int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n    - \targc = parse_options(argc, argv, prefix, options,\n    - \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n    - \n    -+\topts.strategy_opts = xstrdup_or_null(opts.strategy_opts);\n    -+\n    - \tif (!is_null_oid(&squash_onto))\n    - \t\topts.squash_onto = &squash_onto;\n    - \n    -@@ builtin/rebase.c: static int run_am(struct rebase_options *opts)\n    - \tam.git_cmd = 1;\n    - \targv_array_push(&am.args, \"am\");\n    - \n    -+\tif (opts->ignore_whitespace)\n    -+\t\targv_array_push(&am.args, \"--ignore-whitespace\");\n    - \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n    - \t\targv_array_push(&am.args, \"--resolved\");\n    - \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n    + \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n    + \n    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n    + \tstruct strbuf revisions = STRBUF_INIT;\n    + \tstruct strbuf buf = STRBUF_INIT;\n    + \tstruct object_id merge_base;\n    ++\tint ignore_whitespace = 0;\n    + \tenum action action = ACTION_NONE;\n    + \tconst char *gpg_sign = NULL;\n    + \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n      \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n      \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n      \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n      \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n    -+\t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n    ++\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n     +\t\t\t N_(\"ignore changes in whitespace\")),\n      \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n      \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n      \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n    + \t\timply_merge(&options, \"--rebase-merges\");\n    + \t}\n    + \n    ++\tif (options.type == REBASE_APPLY) {\n    ++\t\tif (ignore_whitespace)\n    ++\t\t\targv_array_push (&options.git_am_opts,\n    ++\t\t\t\t\t \"--ignore-whitespace\");\n    ++\t} else if (ignore_whitespace) {\n    ++\t\t\tstring_list_append (&strategy_options,\n    ++\t\t\t\t\t    \"ignore-space-change\");\n    ++\t}\n    ++\n    + \tif (strategy_options.nr) {\n    + \t\tint i;\n    + \n     \n      ## t/t3422-rebase-incompatible-options.sh ##\n     @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {\n    @@ t/t3436-rebase-more-options.sh (new)\n     +# both the backends fall short of optimal behaviour.\n     +test_expect_success 'setup' '\n     +\tgit checkout -b topic &&\n    -+\tq_to_tab >file <<-\\EOF &&\n    -+\tline 1\n    -+\tQline 2\n    -+\tline 3\n    -+\tEOF\n    ++\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n     +\tgit add file &&\n     +\tgit commit -m \"add file\" &&\n    -+\tcat >file <<-\\EOF &&\n    -+\tline 1\n    -+\tnew line 2\n    -+\tline 3\n    -+\tEOF\n    ++\n    ++\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n     +\tgit commit -am \"update file\" &&\n     +\tgit tag side &&\n     +\n     +\tgit checkout --orphan master &&\n    -+\tsed -e \"s/^|//\" >file <<-\\EOF &&\n    -+\t|line 1\n    -+\t|        line 2\n    -+\t|line 3\n    -+\tEOF\n    -+\tgit add file &&\n    -+\tgit commit -m \"add file\" &&\n    ++\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n    ++\tgit commit -am \"add file\" &&\n     +\tgit tag main\n     +'\n     +\n     +test_expect_success '--ignore-whitespace works with apply backend' '\n    -+\tcat >expect <<-\\EOF &&\n    -+\tline 1\n    -+\tnew line 2\n    -+\tline 3\n    -+\tEOF\n     +\ttest_must_fail git rebase --apply main side &&\n     +\tgit rebase --abort &&\n     +\tgit rebase --apply --ignore-whitespace main side &&\n    -+\ttest_cmp expect file\n    ++\tgit diff --exit-code side\n     +'\n     +\n     +test_expect_success '--ignore-whitespace works with merge backend' '\n    -+\tcat >expect <<-\\EOF &&\n    -+\tline 1\n    -+\tnew line 2\n    -+\tline 3\n    -+\tEOF\n     +\ttest_must_fail git rebase --merge main side &&\n     +\tgit rebase --abort &&\n     +\tgit rebase --merge --ignore-whitespace main side &&\n    -+\ttest_cmp expect file\n    ++\tgit diff --exit-code side\n     +'\n     +\n     +test_expect_success '--ignore-whitespace is remembered when continuing' '\n    -+\tcat >expect <<-\\EOF &&\n    -+\tline 1\n    -+\tnew line 2\n    -+\tline 3\n    -+\tEOF\n     +\t(\n     +\t\tset_fake_editor &&\n    -+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace main side\n    ++\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n    ++\t\t\tmain side &&\n    ++\t\tgit rebase --continue\n     +\t) &&\n    -+\tgit rebase --continue &&\n    -+\ttest_cmp expect file\n    ++\tgit diff --exit-code side\n     +'\n     +\n     +# This must be the last test in this file\n2:  ad21e5d8fb ! 2:  a2b57df19c rebase -i: support --committer-date-is-author-date\n    @@ Metadata\n      ## Commit message ##\n         rebase -i: support --committer-date-is-author-date\n     \n    -    As part of the on-going effort to retire the apply rebase backend teach\n    -    the merge backend how to handle --committer-date-is-author-date.\n    +    Rebase is implemented with two different backends - 'apply' and\n    +    'merge' each of which support a different set of options. In\n    +    particular the apply backend supports a number of options implemented\n    +    by 'git am' that are not implemented in the merge backend. This means\n    +    that the available options are different depending on which backend is\n    +    used which is confusing. This patch adds support for the\n    +    --committer-date-is-author-date option to the merge backend. This\n    +    option uses the author date of the commit that is being rewritten as\n    +    the committer date when the new commit is created.\n     \n         Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n         Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n    @@ Documentation/git-rebase.txt: In addition, the following pairs of options are in\n     \n      ## builtin/rebase.c ##\n     @@ builtin/rebase.c: struct rebase_options {\n    - \tint ignore_whitespace;\n    + \tint autosquash;\n      \tchar *gpg_sign_opt;\n      \tint autostash;\n     +\tint committer_date_is_author_date;\n    @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_\n      \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n      \treplay.strategy = opts->strategy;\n      \n    -@@ builtin/rebase.c: static int run_am(struct rebase_options *opts)\n    - \n    - \tif (opts->ignore_whitespace)\n    - \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n    -+\tif (opts->committer_date_is_author_date)\n    -+\t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n    - \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n    - \t\targv_array_push(&am.args, \"--resolved\");\n    - \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n      \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n      \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t    !strcmp(option, \"--whitespace=fix\") ||\n      \t\t    !strcmp(option, \"--whitespace=strip\"))\n      \t\t\tallow_preemptive_ff = 0;\n    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n    + \t\tif (ignore_whitespace)\n    + \t\t\targv_array_push (&options.git_am_opts,\n    + \t\t\t\t\t \"--ignore-whitespace\");\n    ++\t\tif (options.committer_date_is_author_date)\n    ++\t\t\targv_array_push(&options.git_am_opts,\n    ++\t\t\t\t\t\"--committer-date-is-author-date\");\n    + \t} else if (ignore_whitespace) {\n    + \t\t\tstring_list_append (&strategy_options,\n    + \t\t\t\t\t    \"ignore-space-change\");\n     \n      ## sequencer.c ##\n     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n    @@ sequencer.c: static int try_to_commit(struct repository *r,\n      \t}\n      \n     +\tif (opts->committer_date_is_author_date) {\n    -+\t\tint len = strlen(author);\n     +\t\tstruct ident_split ident;\n     +\t\tstruct strbuf date = STRBUF_INIT;\n     +\n    -+\t\tif (split_ident_line(&ident, author, len) < 0) {\n    ++\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n     +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n     +\t\t\tgoto out;\n     +\t\t}\n    @@ sequencer.c: static int try_to_commit(struct repository *r,\n     +\t\t}\n     +\n     +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n    -+\t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n    -+\t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n    ++\t\t\t    (int)(ident.date_end - ident.date_begin),\n    ++\t\t\t    ident.date_begin,\n    ++\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n    ++\t\t\t    ident.tz_begin);\n     +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n     +\t\tstrbuf_release(&date);\n     +\n    @@ t/t3436-rebase-more-options.sh: test_description='tests to ensure compatibility\n      # provide the same output. It was done intentionally because\n      # both the backends fall short of optimal behaviour.\n     @@ t/t3436-rebase-more-options.sh: test_expect_success 'setup' '\n    - \tEOF\n    + \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n      \tgit commit -am \"update file\" &&\n      \tgit tag side &&\n     +\ttest_commit commit1 foo foo1 &&\n     +\ttest_commit commit2 foo foo2 &&\n     +\ttest_commit commit3 foo foo3 &&\n      \n      \tgit checkout --orphan master &&\n    -+\tgit rm --cached foo &&\n     +\trm foo &&\n    - \tsed -e \"s/^|//\" >file <<-\\EOF &&\n    - \t|line 1\n    - \t|        line 2\n    + \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n    + \tgit commit -am \"add file\" &&\n    +-\tgit tag main\n    ++\tgit tag main &&\n    ++\n    ++\tmkdir test-bin &&\n    ++\twrite_script test-bin/git-merge-test <<-\\EOF\n    ++\texec git-merge-recursive \"$@\"\n    ++\tEOF\n    + '\n    + \n    + test_expect_success '--ignore-whitespace works with apply backend' '\n     @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-whitespace is remembered when continuing' '\n    - \ttest_cmp expect file\n    + \tgit diff --exit-code side\n      '\n      \n    ++test_ctime_is_atime () {\n    ++\tgit log $1 --format=%ai >authortime &&\n    ++\tgit log $1 --format=%ci >committertime &&\n    ++\ttest_cmp authortime committertime\n    ++}\n    ++\n     +test_expect_success '--committer-date-is-author-date works with apply backend' '\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n     +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n    -+\tgit log -1 --pretty=%ai >authortime &&\n    -+\tgit log -1 --pretty=%ci >committertime &&\n    -+\ttest_cmp authortime committertime\n    ++\ttest_ctime_is_atime -1\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works with merge backend' '\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n     +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n    -+\tgit log -1 --pretty=%ai >authortime &&\n    -+\tgit log -1 --pretty=%ci >committertime &&\n    -+\ttest_cmp authortime committertime\n    ++\ttest_ctime_is_atime -1\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n     +\tgit checkout side &&\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n     +\tgit rebase -r --root --committer-date-is-author-date &&\n    -+\tgit log --pretty=%ai >authortime &&\n    -+\tgit log --pretty=%ci >committertime &&\n    -+\ttest_cmp authortime committertime\n    ++\ttest_ctime_is_atime\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works when forking merge' '\n     +\tgit checkout side &&\n     +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n    -+\tgit rebase -r --root --strategy=resolve --committer-date-is-author-date &&\n    -+\tgit log --pretty=%ai >authortime &&\n    -+\tgit log --pretty=%ci >committertime &&\n    -+\ttest_cmp authortime committertime\n    -+\n    ++\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n    ++\t\t\t\t\t--committer-date-is-author-date &&\n    ++\ttest_ctime_is_atime\n     +'\n     +\n     +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n     +\tgit checkout commit2 &&\n     +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n    -+\tgit log -1 --format=%at HEAD >expect &&\n     +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n     +\t\t--onto HEAD^^ HEAD^ &&\n     +\techo resolved > foo &&\n     +\tgit add foo &&\n     +\tgit rebase --continue &&\n    -+\tgit log -1 --format=%ct HEAD >actual &&\n    -+\ttest_cmp expect actual\n    ++\ttest_ctime_is_atime -1\n     +'\n     +\n      # This must be the last test in this file\n3:  af92e29cf9 = 3:  363a0140ad sequencer: rename amend_author to author_to_free\n4:  4399dc19b6 ! 4:  46d9e108be rebase -i: support --ignore-date\n    @@ Metadata\n      ## Commit message ##\n         rebase -i: support --ignore-date\n     \n    -    As part of the on-going effort to retire the apply rebase backend\n    -    teach the merge backend how to handle --ignore-date. We take care to\n    -    handle the combination of --ignore-date and\n    -    --committer-date-is-author-date in the same way as the apply backend.\n    +    Rebase is implemented with two different backends - 'apply' and\n    +    'merge' each of which support a different set of options. In\n    +    particular the apply backend supports a number of options implemented\n    +    by 'git am' that are not implemented in the merge backend. This means\n    +    that the available options are different depending on which backend is\n    +    used which is confusing. This patch adds support for the --ignore-date\n    +    option to the merge backend. This option uses the current time as the\n    +    author date rather than reusing the original author date when\n    +    rewriting commits. We take care to handle the combination of\n    +    --ignore-date and --committer-date-is-author-date in the same way as\n    +    the apply backend.\n     \n         Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n         Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n    @@ builtin/rebase.c: static struct replay_opts get_replay_opts(const struct rebase_\n      \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n      \treplay.strategy = opts->strategy;\n      \n    -@@ builtin/rebase.c: static int run_am(struct rebase_options *opts)\n    - \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n    - \tif (opts->committer_date_is_author_date)\n    - \t\targv_array_push(&opts->git_am_opts, \"--committer-date-is-author-date\");\n    -+\tif (opts->ignore_date)\n    -+\t\targv_array_push(&opts->git_am_opts, \"--ignore-date\");\n    - \tif (opts->action && !strcmp(\"continue\", opts->action)) {\n    - \t\targv_array_push(&am.args, \"--resolved\");\n    - \t\targv_array_pushf(&am.args, \"--resolvemsg=%s\", resolvemsg);\n     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n      \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n      \t\t\t &options.committer_date_is_author_date,\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n     +\t\t\t \"ignore author date and use current date\"),\n      \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n      \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n    - \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n    + \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n      \t    options.autosquash) {\n      \t\tallow_preemptive_ff = 0;\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t    !strcmp(option, \"--whitespace=strip\"))\n      \t\t\tallow_preemptive_ff = 0;\n      \t\telse if (skip_prefix(option, \"-C\", &p)) {\n    +@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n    + \t\tif (options.committer_date_is_author_date)\n    + \t\t\targv_array_push(&options.git_am_opts,\n    + \t\t\t\t\t\"--committer-date-is-author-date\");\n    ++\t\tif (options.ignore_date)\n    ++\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n    + \t} else if (ignore_whitespace) {\n    + \t\t\tstring_list_append (&strategy_options,\n    + \t\t\t\t\t    \"ignore-space-change\");\n     \n      ## sequencer.c ##\n     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n    @@ sequencer.c: static int run_git_commit(struct repository *r,\n      \targv_array_push(&cmd.args, \"commit\");\n      \n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n    - \t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n    - \t\t\t    (int)(ident.date_end - ident.date_begin), ident.date_begin,\n    - \t\t\t    (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);\n    + \t\t\t    ident.date_begin,\n    + \t\t\t    (int)(ident.tz_end - ident.tz_begin),\n    + \t\t\t    ident.tz_begin);\n     -\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n     +\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n     +\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n    @@ sequencer.h: struct replay_opts {\n     \n      ## t/t3436-rebase-more-options.sh ##\n     @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-date works when committing confl\n    - \ttest_cmp expect actual\n    + \ttest_ctime_is_atime -1\n      '\n      \n    -+# Checking for +0000 in author time is enough since default\n    -+# timezone is UTC, but the timezone used while committing\n    -+# sets to +0530.\n    ++# Checking for +0000 in the author date is sufficient since the\n    ++# default timezone is UTC but the timezone used while committing is\n    ++# +0530. The inverted logic in the grep is necessary to check all the\n    ++# author dates in the file.\n    ++test_ctime_is_ignored () {\n    ++\tgit log $1 --format=%ai >authortime &&\n    ++\t! grep -v +0000 authortime\n    ++}\n    ++\n     +test_expect_success '--ignore-date works with apply backend' '\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     +\tgit rebase --apply --ignore-date HEAD^ &&\n    -+\tgit log -1 --pretty=%ai >authortime &&\n    -+\tgrep \"+0000\" authortime\n    ++\ttest_ctime_is_ignored -1\n     +'\n     +\n     +test_expect_success '--ignore-date works with merge backend' '\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     +\tgit rebase --ignore-date -m HEAD^ &&\n    -+\tgit log -1 --pretty=%ai >authortime &&\n    -+\tgrep \"+0000\" authortime\n    ++\ttest_ctime_is_ignored -1\n     +'\n     +\n     +test_expect_success '--ignore-date works after conflict resolution' '\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-\n     +\techo resolved >foo &&\n     +\tgit add foo &&\n     +\tgit rebase --continue &&\n    -+\tgit log -1 --pretty=%ai >authortime &&\n    -+\tgrep +0000 authortime\n    ++\ttest_ctime_is_ignored -1\n     +'\n     +\n     +test_expect_success '--ignore-date works with rebase -r' '\n     +\tgit checkout side &&\n     +\tgit merge --no-ff commit3 &&\n     +\tgit rebase -r --root --ignore-date &&\n    -+\tgit log --pretty=%ai >authortime &&\n    -+\t! grep -v \"+0000\" authortime\n    ++\ttest_ctime_is_ignored\n     +'\n     +\n     +test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-\n     +\tgit checkout --theirs foo &&\n     +\tgit add foo &&\n     +\tgit rebase --continue &&\n    -+\tgit log -2 --pretty=%ai >authortime &&\n    -+\tgit log -2 --pretty=%ci >committertime &&\n    -+\ttest_cmp authortime committertime &&\n    -+\t! grep -v \"+0000\" authortime\n    ++\ttest_ctime_is_atime -2 &&\n    ++\ttest_ctime_is_ignored -2\n     +'\n     +\n     +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n     +\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n    -+\t\tgit rebase -i --strategy=resolve --ignore-date \\\n    -+\t\t--committer-date-is-author-date side side &&\n    -+\tgit log -1 --pretty=%ai >authortime &&\n    -+\tgit log -1 --pretty=%ci >committertime &&\n    -+\ttest_cmp authortime committertime &&\n    -+\tgrep \"+0000\" authortime\n    ++\t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n    ++\t\t\t\t--ignore-date --committer-date-is-author-date \\\n    ++\t\t\t\tside side &&\n    ++\ttest_ctime_is_atime -1 &&\n    ++\ttest_ctime_is_ignored -1\n     + '\n     +\n      # This must be the last test in this file\n5:  a11db78eb4 ! 5:  26d5eefdcb rebase: add --reset-author-date\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n     +\t\t\t\tN_(\"synonym of --reset-author-date\")),\n      \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n      \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n    - \t\tOPT_BOOL(0, \"ignore-whitespace\", &options.ignore_whitespace,\n    + \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n     \n      ## t/t3436-rebase-more-options.sh ##\n    -@@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-date works when committing confl\n    - # Checking for +0000 in author time is enough since default\n    - # timezone is UTC, but the timezone used while committing\n    - # sets to +0530.\n    +@@ t/t3436-rebase-more-options.sh: test_ctime_is_ignored () {\n    + \t! grep -v +0000 authortime\n    + }\n    + \n     -test_expect_success '--ignore-date works with apply backend' '\n     +test_expect_success '--reset-author-date works with apply backend' '\n      \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     -\tgit rebase --apply --ignore-date HEAD^ &&\n     +\tgit rebase --apply --reset-author-date HEAD^ &&\n    - \tgit log -1 --pretty=%ai >authortime &&\n    - \tgrep \"+0000\" authortime\n    + \ttest_ctime_is_ignored -1\n      '\n      \n     -test_expect_success '--ignore-date works with merge backend' '\n     +test_expect_success '--reset-author-date works with merge backend' '\n      \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     -\tgit rebase --ignore-date -m HEAD^ &&\n     +\tgit rebase --reset-author-date -m HEAD^ &&\n    - \tgit log -1 --pretty=%ai >authortime &&\n    - \tgrep \"+0000\" authortime\n    + \ttest_ctime_is_ignored -1\n      '\n      \n     -test_expect_success '--ignore-date works after conflict resolution' '\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--committer-date-is-author-\n      \t\t--onto commit2^^ commit2^ commit2 &&\n      \techo resolved >foo &&\n      \tgit add foo &&\n    -@@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date works after conflict resolution' '\n    - \tgrep +0000 authortime\n    + \tgit rebase --continue &&\n    + \ttest_ctime_is_ignored -1\n      '\n      \n     -test_expect_success '--ignore-date works with rebase -r' '\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date works after c\n      \tgit merge --no-ff commit3 &&\n     -\tgit rebase -r --root --ignore-date &&\n     +\tgit rebase -r --root --reset-author-date &&\n    - \tgit log --pretty=%ai >authortime &&\n    - \t! grep -v \"+0000\" authortime\n    + \ttest_ctime_is_ignored\n      '\n      \n     -test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n    @@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date works after c\n      \tgit checkout --theirs foo &&\n      \tgit add foo &&\n      \tgit rebase --continue &&\n    -@@ t/t3436-rebase-more-options.sh: test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n    - \t! grep -v \"+0000\" authortime\n    + \ttest_ctime_is_atime -2 &&\n    + \ttest_ctime_is_ignored -2\n      '\n      \n     -test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n     +test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n      \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n    --\t\tgit rebase -i --strategy=resolve --ignore-date \\\n    -+\t\tgit rebase -i --strategy=resolve --reset-author-date \\\n    - \t\t--committer-date-is-author-date side side &&\n    - \tgit log -1 --pretty=%ai >authortime &&\n    - \tgit log -1 --pretty=%ci >committertime &&\n    - \ttest_cmp authortime committertime &&\n    - \tgrep \"+0000\" authortime\n    + \t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n    +-\t\t\t\t--ignore-date --committer-date-is-author-date \\\n    +-\t\t\t\tside side &&\n    ++\t\t\t\t--reset-author-date \\\n    ++\t\t\t\t--committer-date-is-author-date side side &&\n    + \ttest_ctime_is_atime -1 &&\n    + \ttest_ctime_is_ignored -1\n       '\n      \n     +test_expect_success '--ignore-date is an alias for --reset-author-date' '\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     +\tgit rebase --apply --ignore-date HEAD^ &&\n     +\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n     +\tgit rebase -m --ignore-date HEAD^ &&\n    -+\tgit log -2 --pretty=\"format:%ai\" >authortime &&\n    -+\tgrep \"+0000\" authortime >output &&\n    -+\ttest_line_count = 2 output\n    ++\ttest_ctime_is_ignored -2\n     +'\n     +\n      # This must be the last test in this file\n-- \n2.27.0\n\n"},{"id":"400662","messageId":"20200626095528.117524-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200626095528.117524-1-phillip.wood123@gmail.com","subject":"[PATCH v5 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T09:55:24Z","receivedAt":"2020-06-26T09:55:42Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--ignore-whitespace option to the merge backend. This option treats\nlines with only whitespace changes as unchanged and is implemented in\nthe merge backend by translating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 19 +++++++-\n builtin/rebase.c                       | 16 +++++--\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++\n 4 files changed, 90 insertions(+), 6 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f7a6033607..b003784f01 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tIgnore whitespace differences when trying to reconcile\n+differences. Currently, each backend implements an approximation of\n+this behavior:\n++\n+apply backend: When applying a patch, ignore changes in whitespace in\n+context lines. Unfortunately, this means that if the \"old\" lines being\n+replaced by the patch differ only in whitespace from the existing\n+file, you will get a merge conflict instead of a successful patch\n+application.\n++\n+merge backend: Treat lines with only whitespace changes as unchanged\n+when merging. Unfortunately, this means that any patch hunks that were\n+intended to modify whitespace and nothing else will be dropped, even\n+if the other side had no changes that conflicted.\n+\n --whitespace=<option>::\n-\tThese flags are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n \tImplies --apply.\n +\n@@ -572,7 +587,6 @@ The following options:\n  * --apply\n  * --committer-date-is-author-date\n  * --ignore-date\n- * --ignore-whitespace\n  * --whitespace\n  * -C\n \n@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n+ * --preserve-merges and --ignore-whitespace\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 27a07d4e78..810c9b7779 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n \n@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tstruct strbuf revisions = STRBUF_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct object_id merge_base;\n+\tint ignore_whitespace = 0;\n \tenum action action = ACTION_NONE;\n \tconst char *gpg_sign = NULL;\n \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n@@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\timply_merge(&options, \"--rebase-merges\");\n \t}\n \n+\tif (options.type == REBASE_APPLY) {\n+\t\tif (ignore_whitespace)\n+\t\t\targv_array_push (&options.git_am_opts,\n+\t\t\t\t\t \"--ignore-whitespace\");\n+\t} else if (ignore_whitespace) {\n+\t\t\tstring_list_append (&strategy_options,\n+\t\t\t\t\t    \"ignore-space-change\");\n+\t}\n+\n \tif (strategy_options.nr) {\n \t\tint i;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..55ca46786d 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nnew file mode 100755\nindex 0000000000..4f8a6e51c9\n--- /dev/null\n+++ b/t/t3436-rebase-more-options.sh\n@@ -0,0 +1,60 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\n+\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\n+\tgit checkout --orphan master &&\n+\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n+\tgit commit -am \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with apply backend' '\n+\ttest_must_fail git rebase --apply main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --apply --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace works with merge backend' '\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n+\t\t\tmain side &&\n+\t\tgit rebase --continue\n+\t) &&\n+\tgit diff --exit-code side\n+'\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n+test_done\n-- \n2.27.0\n\n"},{"id":"400663","messageId":"20200626095528.117524-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200626095528.117524-1-phillip.wood123@gmail.com","subject":"[PATCH v5 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T09:55:25Z","receivedAt":"2020-06-26T09:55:44Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--committer-date-is-author-date option to the merge backend. This\noption uses the author date of the commit that is being rewritten as\nthe committer date when the new commit is created.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 10 +++--\n builtin/rebase.c                       | 17 +++++---\n sequencer.c                            | 60 +++++++++++++++++++++++++-\n sequencer.h                            |  1 +\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++++++++++-\n 6 files changed, 136 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex b003784f01..dfa70263e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of using the current time as the committer date, use\n+\tthe author date of the commit being rebased as the committer\n+\tdate. This option implies --force-rebase.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tThis flag is passed to 'git am' to change the author date\n+\tof each rebased commit (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 810c9b7779..a7c3d5c92b 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -88,6 +88,7 @@ struct rebase_options {\n \tint autosquash;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n+\tif (options.committer_date_is_author_date)\n+\t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n+\t\tif (!strcmp(option, \"--ignore-date\") ||\n \t\t    !strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (ignore_whitespace)\n \t\t\targv_array_push (&options.git_am_opts,\n \t\t\t\t\t \"--ignore-whitespace\");\n+\t\tif (options.committer_date_is_author_date)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--committer-date-is-author-date\");\n \t} else if (ignore_whitespace) {\n \t\t\tstring_list_append (&strategy_options,\n \t\t\t\t\t    \"ignore-space-change\");\ndiff --git a/sequencer.c b/sequencer.c\nindex 6fd2674632..368d397970 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -872,6 +873,22 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+static const char *author_date_from_env_array(const struct argv_array *env)\n+{\n+\tint i;\n+\tconst char *date;\n+\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n \n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \targv_array_push(&cmd.args, \"commit\");\n \n \tif (!(flags & VERIFY_MSG))\n@@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,\n \t\tcommit_list_insert(current_head, &parents);\n \t}\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tstruct ident_split ident;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n+\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!ident.date_begin) {\n+\t\t\tres = error(_(\"corrupted author without date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(ident.date_end - ident.date_begin),\n+\t\t\t    ident.date_begin,\n+\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n+\t\t\t    ident.tz_begin);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&date);\n+\n+\t\tif (res)\n+\t\t\tgoto out;\n+\t}\n+\n \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n \t\tres = error(_(\"git write-tree failed to write a tree\"));\n \t\tgoto out;\n@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n \tif (opts->keep_redundant_commits)\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n \t\t\tgoto leave_merge;\n \t\t}\n \n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n \t\targv_array_push(&cmd.args, \"-s\");\n@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t\topts->record_origin || opts->edit ||\n+\t\t\t\topts->committer_date_is_author_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 0bee85093e..4ab94119ae 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -45,6 +45,7 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n \n \tint mainline;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 55ca46786d..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 4f8a6e51c9..50a63d8ebe 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n # This is a special case in which both am and interactive backends\n # provide the same output. It was done intentionally because\n # both the backends fall short of optimal behaviour.\n@@ -21,11 +24,20 @@ test_expect_success 'setup' '\n \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n \tgit commit -am \"update file\" &&\n \tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n \n \tgit checkout --orphan master &&\n+\trm foo &&\n \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n \tgit commit -am \"add file\" &&\n-\tgit tag main\n+\tgit tag main &&\n+\n+\tmkdir test-bin &&\n+\twrite_script test-bin/git-merge-test <<-\\EOF\n+\texec git-merge-recursive \"$@\"\n+\tEOF\n '\n \n test_expect_success '--ignore-whitespace works with apply backend' '\n@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n \tgit diff --exit-code side\n '\n \n+test_ctime_is_atime () {\n+\tgit log $1 --format=%ai >authortime &&\n+\tgit log $1 --format=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+}\n+\n+test_expect_success '--committer-date-is-author-date works with apply backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with merge backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n+\t\t\t\t\t--committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -1\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"400664","messageId":"20200626095528.117524-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200626095528.117524-1-phillip.wood123@gmail.com","subject":"[PATCH v5 3/5] sequencer: rename amend_author to author_to_free","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T09:55:26Z","receivedAt":"2020-06-26T09:55:46Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() when amending a commit. But we can\nalso use the variable to free() the author at our convenience.\nRename it to convey this meaning.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 368d397970..29f6d1bc39 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n-\tchar *amend_author = NULL;\n+\tchar *author_to_free = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tstrbuf_addstr(msg, orig_message);\n \t\t\thook_commit = \"HEAD\";\n \t\t}\n-\t\tauthor = amend_author = get_author(message);\n+\t\tauthor = author_to_free = get_author(message);\n \t\tunuse_commit_buffer(current_head, message);\n \t\tif (!author) {\n \t\t\tres = error(_(\"unable to parse commit author\"));\n@@ -1474,7 +1474,7 @@ static int try_to_commit(struct repository *r,\n \tfree_commit_extra_headers(extra);\n \tstrbuf_release(&err);\n \tstrbuf_release(&commit_msg);\n-\tfree(amend_author);\n+\tfree(author_to_free);\n \n \treturn res;\n }\n-- \n2.27.0\n\n"},{"id":"400665","messageId":"20200626095528.117524-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200626095528.117524-1-phillip.wood123@gmail.com","subject":"[PATCH v5 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T09:55:27Z","receivedAt":"2020-06-26T09:55:47Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the --ignore-date\noption to the merge backend. This option uses the current time as the\nauthor date rather than reusing the original author date when\nrewriting commits. We take care to handle the combination of\n--ignore-date and --committer-date-is-author-date in the same way as\nthe apply backend.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt   |  7 +++--\n builtin/rebase.c               | 13 +++++---\n sequencer.c                    | 50 ++++++++++++++++++++++++++++--\n sequencer.h                    |  1 +\n t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++\n 5 files changed, 117 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex dfa70263e6..e2717e20e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof each rebased commit (see linkgit:git-am[1]).\n+\tInstead of using the author date of the original commit, use\n+\tthe current time as the\tauthor date of the rebased commit.  This\n+\toption implies `--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n  * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex a7c3d5c92b..890dd4c588 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -89,6 +89,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.committer_date_is_author_date =\n \t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current date\"),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n-\tif (options.committer_date_is_author_date)\n+\tif (options.committer_date_is_author_date || options.ignore_date)\n \t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\n@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (options.committer_date_is_author_date)\n \t\t\targv_array_push(&options.git_am_opts,\n \t\t\t\t\t\"--committer-date-is-author-date\");\n+\t\tif (options.ignore_date)\n+\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n \t} else if (ignore_whitespace) {\n \t\t\tstring_list_append (&strategy_options,\n \t\t\t\t\t    \"ignore-space-change\");\ndiff --git a/sequencer.c b/sequencer.c\nindex 29f6d1bc39..f8e1e38623 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n }\n \n+/* Construct a free()able author string with current time as the author date */\n+static char *ignore_author_date(const char *author)\n+{\n+\tint len = strlen(author);\n+\tstruct ident_split ident;\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\n+\tif (split_ident_line(&ident, author, len) < 0) {\n+\t\terror(_(\"malformed ident line '%s'\"), author);\n+\t\treturn NULL;\n+\t}\n+\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n \n \tif (opts->committer_date_is_author_date)\n \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n \t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,\n \t\t\t    ident.date_begin,\n \t\t\t    (int)(ident.tz_end - ident.tz_begin),\n \t\t\t    ident.tz_begin);\n-\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n \t\tstrbuf_release(&date);\n \n \t\tif (res)\n@@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tauthor = ignore_author_date(author);\n+\t\tif (!author) {\n+\t\t\tres = -1;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tfree(author_to_free);\n+\t\tauthor_to_free = (char *)author;\n+\t}\n+\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->committer_date_is_author_date = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n \tif (opts->committer_date_is_author_date)\n \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,\n \n \t\tif (opts->committer_date_is_author_date)\n \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n \t\t\t\topts->record_origin || opts->edit ||\n-\t\t\t\topts->committer_date_is_author_date));\n+\t\t\t\topts->committer_date_is_author_date ||\n+\t\t\t\topts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 4ab94119ae..3587878e3b 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -46,6 +46,7 @@ struct replay_opts {\n \tint quiet;\n \tint reschedule_failed_exec;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 50a63d8ebe..0ede2b8900 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n \ttest_ctime_is_atime -1\n '\n \n+# Checking for +0000 in the author date is sufficient since the\n+# default timezone is UTC but the timezone used while committing is\n+# +0530. The inverted logic in the grep is necessary to check all the\n+# author dates in the file.\n+test_ctime_is_ignored () {\n+\tgit log $1 --format=%ai >authortime &&\n+\t! grep -v +0000 authortime\n+}\n+\n+test_expect_success '--ignore-date works with apply backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with merge backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -m HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -m \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\ttest_ctime_is_ignored\n+'\n+\n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -2 &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n+\t\t\t\t--ignore-date --committer-date-is-author-date \\\n+\t\t\t\tside side &&\n+\ttest_ctime_is_atime -1 &&\n+\ttest_ctime_is_ignored -1\n+ '\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"400666","messageId":"20200626095528.117524-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200626095528.117524-1-phillip.wood123@gmail.com","subject":"[PATCH v5 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T09:55:28Z","receivedAt":"2020-06-26T09:55:49Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe previous commit introduced --ignore-date flag to rebase -i, but the\nname is rather vague as it does not say whether the author date or the\ncommitter date is ignored. Add an alias to convey the precise purpose.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt   |  1 +\n builtin/rebase.c               |  6 ++++--\n t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------\n 3 files changed, 26 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e2717e20e6..a5f82913fb 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the author date of the original commit, use\n \tthe current time as the\tauthor date of the rebased commit.  This\n \toption implies `--force-rebase`.\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 890dd4c588..3fe33beef4 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n-\t\t\t \"ignore author date and use current date\"),\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 0ede2b8900..5b8963272a 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -117,53 +117,61 @@ test_ctime_is_ignored () {\n \t! grep -v +0000 authortime\n }\n \n-test_expect_success '--ignore-date works with apply backend' '\n+test_expect_success '--reset-author-date works with apply backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit rebase --apply --reset-author-date HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with merge backend' '\n+test_expect_success '--reset-author-date works with merge backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit rebase --reset-author-date -m HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works after conflict resolution' '\n-\ttest_must_fail git rebase --ignore-date -m \\\n+test_expect_success '--reset-author-date works after conflict resolution' '\n+\ttest_must_fail git rebase --reset-author-date -m \\\n \t\t--onto commit2^^ commit2^ commit2 &&\n \techo resolved >foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with rebase -r' '\n+test_expect_success '--reset-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n-\tgit rebase -r --root --ignore-date &&\n+\tgit rebase -r --root --reset-author-date &&\n \ttest_ctime_is_ignored\n '\n \n-test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '\n \ttest_must_fail git rebase -m --committer-date-is-author-date \\\n-\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\t\t--reset-author-date --onto commit2^^ commit2^ commit3 &&\n \tgit checkout --theirs foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_atime -2 &&\n \ttest_ctime_is_ignored -2\n '\n \n-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n \t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n-\t\t\t\t--ignore-date --committer-date-is-author-date \\\n-\t\t\t\tside side &&\n+\t\t\t\t--reset-author-date \\\n+\t\t\t\t--committer-date-is-author-date side side &&\n \ttest_ctime_is_atime -1 &&\n \ttest_ctime_is_ignored -1\n  '\n \n+test_expect_success '--ignore-date is an alias for --reset-author-date' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase -m --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"400681","messageId":"20200626133714.GB12504@danh.dev","threadId":"53176","inReplyTo":"20200626095528.117524-2-phillip.wood123@gmail.com","subject":"Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-06-26T13:37:14Z","receivedAt":"2020-06-26T13:37:21Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"On 2020-06-26 10:55:24+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> \n> Rebase is implemented with two different backends - 'apply' and\n> 'merge' each of which support a different set of options. In\n> particular the apply backend supports a number of options implemented\n> by 'git am' that are not implemented in the merge backend. This means\n> that the available options are different depending on which backend is\n> used which is confusing. This patch adds support for the\n> --ignore-whitespace option to the merge backend. This option treats\n> lines with only whitespace changes as unchanged and is implemented in\n> the merge backend by translating it to -Xignore-space-change.\n> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt           | 19 +++++++-\n>  builtin/rebase.c                       | 16 +++++--\n>  t/t3422-rebase-incompatible-options.sh |  1 -\n>  t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++\n>  4 files changed, 90 insertions(+), 6 deletions(-)\n>  create mode 100755 t/t3436-rebase-more-options.sh\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index f7a6033607..b003784f01 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n>  with `--keep-base` in order to drop those commits from your branch.\n>  \n>  --ignore-whitespace::\n> +\tIgnore whitespace differences when trying to reconcile\n> +differences. Currently, each backend implements an approximation of\n> +this behavior:\n> ++\n> +apply backend: When applying a patch, ignore changes in whitespace in\n> +context lines. Unfortunately, this means that if the \"old\" lines being\n> +replaced by the patch differ only in whitespace from the existing\n> +file, you will get a merge conflict instead of a successful patch\n> +application.\n> ++\n> +merge backend: Treat lines with only whitespace changes as unchanged\n> +when merging. Unfortunately, this means that any patch hunks that were\n> +intended to modify whitespace and nothing else will be dropped, even\n> +if the other side had no changes that conflicted.\n> +\n>  --whitespace=<option>::\n> -\tThese flags are passed to the 'git apply' program\n> +\tThis flag is passed to the 'git apply' program\n>  \t(see linkgit:git-apply[1]) that applies the patch.\n>  \tImplies --apply.\n>  +\n> @@ -572,7 +587,6 @@ The following options:\n>   * --apply\n>   * --committer-date-is-author-date\n>   * --ignore-date\n> - * --ignore-whitespace\n>   * --whitespace\n>   * -C\n>  \n> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --signoff\n>   * --preserve-merges and --rebase-merges\n>   * --preserve-merges and --empty=\n> + * --preserve-merges and --ignore-whitespace\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>  \n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 27a07d4e78..810c9b7779 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>  \treplay.strategy = opts->strategy;\n> +\n>  \tif (opts->strategy_opts)\n>  \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n>  \n> @@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \tstruct strbuf revisions = STRBUF_INIT;\n>  \tstruct strbuf buf = STRBUF_INIT;\n>  \tstruct object_id merge_base;\n> +\tint ignore_whitespace = 0;\n>  \tenum action action = ACTION_NONE;\n>  \tconst char *gpg_sign = NULL;\n>  \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n> @@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>  \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>  \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n> -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n> -\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n> -\t\t\t\t  PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>  \t\t\t\t  &options.git_am_opts, NULL,\n>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>  \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n> +\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n> +\t\t\t N_(\"ignore changes in whitespace\")),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>  \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>  \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n> @@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\timply_merge(&options, \"--rebase-merges\");\n>  \t}\n>  \n> +\tif (options.type == REBASE_APPLY) {\n> +\t\tif (ignore_whitespace)\n> +\t\t\targv_array_push (&options.git_am_opts,\n> +\t\t\t\t\t \"--ignore-whitespace\");\n> +\t} else if (ignore_whitespace) {\n> +\t\t\tstring_list_append (&strategy_options,\n> +\t\t\t\t\t    \"ignore-space-change\");\n> +\t}\n> +\n\nHm, I've just noticed this by now.\nWould it's better if we rewrite it as:\n\n\tif (ignore_whitespace) {\n\t\tif (options.type == REBASE_APPLY)\n\t\t\targv_array_push(&options.git_am_opts,\n\t\t\t\t\t\"--ignore-whitespace\");\n\t\telse\n\t\t\tstring_list_append(&strategy_options,\n\t\t\t\t\t   \"ignore-space-change\");\n\t}\n\nAh, the incoming patches will add more conditions into the:\n\n\tif (options.type == REBASE_APPLY)\n\nI'm still not convinced, though.\n\nAnyway, IIRC, --ignore-whitespace and --ignore-space-change has the\nsame meaning, I think it's better to use the same option for both\nlegs, no?\n\nI can understand the decision to use --ignore-whitespace as keeping\nthe pass-through behavior of old code, but I think future maintenance\nis more important than that.\n\nI've tried changing ignore-whitespace to ignore-space-change and run\nmake test\n\nIt looks good to me (aka nothing failed _in my machine_),\n4/5 and 5/5 is not applied, though.\n\n>  \tif (strategy_options.nr) {\n>  \t\tint i;\n>  \n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 50e7960702..55ca46786d 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>  \n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --ignore-whitespace\n>  test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>  \n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> new file mode 100755\n> index 0000000000..4f8a6e51c9\n> --- /dev/null\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -0,0 +1,60 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2019 Rohit Ashiwal\n> +#\n> +\n> +test_description='tests to ensure compatibility between am and interactive backends'\n> +\n> +. ./test-lib.sh\n> +\n> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n> +\n> +# This is a special case in which both am and interactive backends\n> +# provide the same output. It was done intentionally because\n> +# both the backends fall short of optimal behaviour.\n> +test_expect_success 'setup' '\n> +\tgit checkout -b topic &&\n> +\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n> +\tgit add file &&\n> +\tgit commit -m \"add file\" &&\n> +\n> +\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n> +\tgit commit -am \"update file\" &&\n> +\tgit tag side &&\n> +\n> +\tgit checkout --orphan master &&\n> +\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n> +\tgit commit -am \"add file\" &&\n> +\tgit tag main\n> +'\n> +\n> +test_expect_success '--ignore-whitespace works with apply backend' '\n> +\ttest_must_fail git rebase --apply main side &&\n> +\tgit rebase --abort &&\n> +\tgit rebase --apply --ignore-whitespace main side &&\n> +\tgit diff --exit-code side\n> +'\n> +\n> +test_expect_success '--ignore-whitespace works with merge backend' '\n> +\ttest_must_fail git rebase --merge main side &&\n> +\tgit rebase --abort &&\n> +\tgit rebase --merge --ignore-whitespace main side &&\n> +\tgit diff --exit-code side\n> +'\n> +\n> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n> +\t(\n> +\t\tset_fake_editor &&\n> +\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n> +\t\t\tmain side &&\n> +\t\tgit rebase --continue\n> +\t) &&\n> +\tgit diff --exit-code side\n> +'\n> +\n> +# This must be the last test in this file\n> +test_expect_success '$EDITOR and friends are unchanged' '\n> +\ttest_editor_unchanged\n> +'\n> +\n> +test_done\n> -- \n> 2.27.0\n> \n\n-- \nDanh\n"},{"id":"400684","messageId":"20200626140854.GC12504@danh.dev","threadId":"53176","inReplyTo":"20200626095528.117524-5-phillip.wood123@gmail.com","subject":"Re: [PATCH v5 4/5] rebase -i: support --ignore-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-06-26T14:09:05Z","receivedAt":"2020-06-26T14:09:10Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"On 2020-06-26 10:55:27+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> Rebase is implemented with two different backends - 'apply' and\n> 'merge' each of which support a different set of options. In\n> particular the apply backend supports a number of options implemented\n> by 'git am' that are not implemented in the merge backend. This means\n> that the available options are different depending on which backend is\n> used which is confusing. This patch adds support for the --ignore-date\n> option to the merge backend. This option uses the current time as the\n> author date rather than reusing the original author date when\n> rewriting commits. We take care to handle the combination of\n> --ignore-date and --committer-date-is-author-date in the same way as\n> the apply backend.\n> \n> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt   |  7 +++--\n>  builtin/rebase.c               | 13 +++++---\n>  sequencer.c                    | 50 ++++++++++++++++++++++++++++--\n>  sequencer.h                    |  1 +\n>  t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++\n>  5 files changed, 117 insertions(+), 10 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index dfa70263e6..e2717e20e6 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n>  \tdate. This option implies --force-rebase.\n>  \n>  --ignore-date::\n> -\tThis flag is passed to 'git am' to change the author date\n> -\tof each rebased commit (see linkgit:git-am[1]).\n> +\tInstead of using the author date of the original commit, use\n> +\tthe current time as the\tauthor date of the rebased commit.  This\n> +\toption implies `--force-rebase`.\n>  +\n>  See also INCOMPATIBLE OPTIONS below.\n>  \n> @@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n>  The following options:\n>  \n>   * --apply\n> - * --ignore-date\n>   * --whitespace\n>   * -C\n>  \n> @@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --empty=\n>   * --preserve-merges and --ignore-whitespace\n>   * --preserve-merges and --committer-date-is-author-date\n> + * --preserve-merges and --ignore-date\n>   * --keep-base and --onto\n>   * --keep-base and --root\n>  \n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index a7c3d5c92b..890dd4c588 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -89,6 +89,7 @@ struct rebase_options {\n>  \tchar *gpg_sign_opt;\n>  \tint autostash;\n>  \tint committer_date_is_author_date;\n> +\tint ignore_date;\n>  \tchar *cmd;\n>  \tint allow_empty_message;\n>  \tint rebase_merges, rebase_cousins;\n> @@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>  \treplay.committer_date_is_author_date =\n>  \t\t\t\t\topts->committer_date_is_author_date;\n> +\treplay.ignore_date = opts->ignore_date;\n>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>  \treplay.strategy = opts->strategy;\n>  \n> @@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n>  \t\t\t &options.committer_date_is_author_date,\n>  \t\t\t N_(\"make committer date match author date\")),\n> -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n> -\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> +\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n> +\t\t\t \"ignore author date and use current date\"),\n\nNit: The options' description is subjected to l10n.\n\ns/\".*\"/N_(&)/\n\n>  \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>  \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n>  \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n> @@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t    options.autosquash) {\n>  \t\tallow_preemptive_ff = 0;\n>  \t}\n> -\tif (options.committer_date_is_author_date)\n> +\tif (options.committer_date_is_author_date || options.ignore_date)\n>  \t\toptions.flags |= REBASE_FORCE;\n>  \n>  \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n>  \t\tconst char *option = options.git_am_opts.argv[i], *p;\n> -\t\tif (!strcmp(option, \"--ignore-date\") ||\n> -\t\t    !strcmp(option, \"--whitespace=fix\") ||\n> +\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n>  \t\t    !strcmp(option, \"--whitespace=strip\"))\n>  \t\t\tallow_preemptive_ff = 0;\n>  \t\telse if (skip_prefix(option, \"-C\", &p)) {\n> @@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\tif (options.committer_date_is_author_date)\n>  \t\t\targv_array_push(&options.git_am_opts,\n>  \t\t\t\t\t\"--committer-date-is-author-date\");\n> +\t\tif (options.ignore_date)\n> +\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n>  \t} else if (ignore_whitespace) {\n>  \t\t\tstring_list_append (&strategy_options,\n>  \t\t\t\t\t    \"ignore-space-change\");\n> diff --git a/sequencer.c b/sequencer.c\n> index 29f6d1bc39..f8e1e38623 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n>  static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n> +static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n>  \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n>  }\n>  \n> +/* Construct a free()able author string with current time as the author date */\n> +static char *ignore_author_date(const char *author)\n> +{\n> +\tint len = strlen(author);\n> +\tstruct ident_split ident;\n> +\tstruct strbuf new_author = STRBUF_INIT;\n> +\n> +\tif (split_ident_line(&ident, author, len) < 0) {\n> +\t\terror(_(\"malformed ident line '%s'\"), author);\n> +\t\treturn NULL;\n> +\t}\n> +\n> +\tlen = ident.mail_end - ident.name_begin + 1;\n> +\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n\nI wonder if we can do this instead:\n\n\tstrbuf_add(&new_author, ident.name_begin, len);\n\nQuick skim through the code and nothing crashes when make test with:\n\n\tCFLAGS=\"-fstack-clash-protection -D_FORTIFY_SOURCE=2\"\n\nI think it's OK to be changed.\n\n> +\tdatestamp(&new_author);\n> +\treturn strbuf_detach(&new_author, NULL);\n> +}\n> +\n\n-- \nDanh\n"},{"id":"400688","messageId":"d0d8dcb2-6714-f0a6-61a3-55c5e0b6ab19@gmail.com","threadId":"53176","inReplyTo":"20200626140854.GC12504@danh.dev","subject":"Re: [PATCH v5 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T14:38:38Z","receivedAt":"2020-06-26T14:38:44Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 26/06/2020 15:09, Đoàn Trần Công Danh wrote:\n> On 2020-06-26 10:55:27+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> Rebase is implemented with two different backends - 'apply' and\n>> 'merge' each of which support a different set of options. In\n>> particular the apply backend supports a number of options implemented\n>> by 'git am' that are not implemented in the merge backend. This means\n>> that the available options are different depending on which backend is\n>> used which is confusing. This patch adds support for the --ignore-date\n>> option to the merge backend. This option uses the current time as the\n>> author date rather than reusing the original author date when\n>> rewriting commits. We take care to handle the combination of\n>> --ignore-date and --committer-date-is-author-date in the same way as\n>> the apply backend.\n>>\n>> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> ---\n>>   Documentation/git-rebase.txt   |  7 +++--\n>>   builtin/rebase.c               | 13 +++++---\n>>   sequencer.c                    | 50 ++++++++++++++++++++++++++++--\n>>   sequencer.h                    |  1 +\n>>   t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++\n>>   5 files changed, 117 insertions(+), 10 deletions(-)\n>>\n>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n>> index dfa70263e6..e2717e20e6 100644\n>> --- a/Documentation/git-rebase.txt\n>> +++ b/Documentation/git-rebase.txt\n>> @@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n>>   \tdate. This option implies --force-rebase.\n>>   \n>>   --ignore-date::\n>> -\tThis flag is passed to 'git am' to change the author date\n>> -\tof each rebased commit (see linkgit:git-am[1]).\n>> +\tInstead of using the author date of the original commit, use\n>> +\tthe current time as the\tauthor date of the rebased commit.  This\n>> +\toption implies `--force-rebase`.\n>>   +\n>>   See also INCOMPATIBLE OPTIONS below.\n>>   \n>> @@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n>>   The following options:\n>>   \n>>    * --apply\n>> - * --ignore-date\n>>    * --whitespace\n>>    * -C\n>>   \n>> @@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n>>    * --preserve-merges and --empty=\n>>    * --preserve-merges and --ignore-whitespace\n>>    * --preserve-merges and --committer-date-is-author-date\n>> + * --preserve-merges and --ignore-date\n>>    * --keep-base and --onto\n>>    * --keep-base and --root\n>>   \n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index a7c3d5c92b..890dd4c588 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -89,6 +89,7 @@ struct rebase_options {\n>>   \tchar *gpg_sign_opt;\n>>   \tint autostash;\n>>   \tint committer_date_is_author_date;\n>> +\tint ignore_date;\n>>   \tchar *cmd;\n>>   \tint allow_empty_message;\n>>   \tint rebase_merges, rebase_cousins;\n>> @@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>   \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>>   \treplay.committer_date_is_author_date =\n>>   \t\t\t\t\topts->committer_date_is_author_date;\n>> +\treplay.ignore_date = opts->ignore_date;\n>>   \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>>   \treplay.strategy = opts->strategy;\n>>   \n>> @@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>   \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n>>   \t\t\t &options.committer_date_is_author_date,\n>>   \t\t\t N_(\"make committer date match author date\")),\n>> -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>> -\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>> +\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n>> +\t\t\t \"ignore author date and use current date\"),\n> \n> Nit: The options' description is subjected to l10n.\n> \n> s/\".*\"/N_(&)/\n\nWell spotted, thanks\n\n>>   \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>>   \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n>>   \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n>> @@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>   \t    options.autosquash) {\n>>   \t\tallow_preemptive_ff = 0;\n>>   \t}\n>> -\tif (options.committer_date_is_author_date)\n>> +\tif (options.committer_date_is_author_date || options.ignore_date)\n>>   \t\toptions.flags |= REBASE_FORCE;\n>>   \n>>   \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n>>   \t\tconst char *option = options.git_am_opts.argv[i], *p;\n>> -\t\tif (!strcmp(option, \"--ignore-date\") ||\n>> -\t\t    !strcmp(option, \"--whitespace=fix\") ||\n>> +\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n>>   \t\t    !strcmp(option, \"--whitespace=strip\"))\n>>   \t\t\tallow_preemptive_ff = 0;\n>>   \t\telse if (skip_prefix(option, \"-C\", &p)) {\n>> @@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>   \t\tif (options.committer_date_is_author_date)\n>>   \t\t\targv_array_push(&options.git_am_opts,\n>>   \t\t\t\t\t\"--committer-date-is-author-date\");\n>> +\t\tif (options.ignore_date)\n>> +\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n>>   \t} else if (ignore_whitespace) {\n>>   \t\t\tstring_list_append (&strategy_options,\n>>   \t\t\t\t\t    \"ignore-space-change\");\n>> diff --git a/sequencer.c b/sequencer.c\n>> index 29f6d1bc39..f8e1e38623 100644\n>> --- a/sequencer.c\n>> +++ b/sequencer.c\n>> @@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>>    */\n>>   static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n>>   static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>> +static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n>>   static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>>   static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>>   static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n>> @@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n>>   \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n>>   }\n>>   \n>> +/* Construct a free()able author string with current time as the author date */\n>> +static char *ignore_author_date(const char *author)\n>> +{\n>> +\tint len = strlen(author);\n>> +\tstruct ident_split ident;\n>> +\tstruct strbuf new_author = STRBUF_INIT;\n>> +\n>> +\tif (split_ident_line(&ident, author, len) < 0) {\n>> +\t\terror(_(\"malformed ident line '%s'\"), author);\n>> +\t\treturn NULL;\n>> +\t}\n>> +\n>> +\tlen = ident.mail_end - ident.name_begin + 1;\n>> +\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n> \n> I wonder if we can do this instead:\n> \n> \tstrbuf_add(&new_author, ident.name_begin, len);\n\nThere is a space at the end of the format string, which I think is \nneeded to separate the name and email from the date we add with \ndatestamp() below\n\nBest Wishes\n\nPhillip\n\n> Quick skim through the code and nothing crashes when make test with:\n>\n> \tCFLAGS=\"-fstack-clash-protection -D_FORTIFY_SOURCE=2\"\n> \n> I think it's OK to be changed.\n> \n>> +\tdatestamp(&new_author);\n>> +\treturn strbuf_detach(&new_author, NULL);\n>> +}\n>> +\n> \n"},{"id":"400691","messageId":"78c32f2d-3af6-1514-51a3-1110531cbb88@gmail.com","threadId":"53176","inReplyTo":"20200626133714.GB12504@danh.dev","subject":"Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T14:43:00Z","receivedAt":"2020-06-26T14:43:05Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 26/06/2020 14:37, Đoàn Trần Công Danh wrote:\n> On 2020-06-26 10:55:24+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>>\n>> Rebase is implemented with two different backends - 'apply' and\n>> 'merge' each of which support a different set of options. In\n>> particular the apply backend supports a number of options implemented\n>> by 'git am' that are not implemented in the merge backend. This means\n>> that the available options are different depending on which backend is\n>> used which is confusing. This patch adds support for the\n>> --ignore-whitespace option to the merge backend. This option treats\n>> lines with only whitespace changes as unchanged and is implemented in\n>> the merge backend by translating it to -Xignore-space-change.\n>>\n>> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> ---\n>>   Documentation/git-rebase.txt           | 19 +++++++-\n>>   builtin/rebase.c                       | 16 +++++--\n>>   t/t3422-rebase-incompatible-options.sh |  1 -\n>>   t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++\n>>   4 files changed, 90 insertions(+), 6 deletions(-)\n>>   create mode 100755 t/t3436-rebase-more-options.sh\n>>\n>> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n>> index f7a6033607..b003784f01 100644\n>> --- a/Documentation/git-rebase.txt\n>> +++ b/Documentation/git-rebase.txt\n>> @@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n>>   with `--keep-base` in order to drop those commits from your branch.\n>>   \n>>   --ignore-whitespace::\n>> +\tIgnore whitespace differences when trying to reconcile\n>> +differences. Currently, each backend implements an approximation of\n>> +this behavior:\n>> ++\n>> +apply backend: When applying a patch, ignore changes in whitespace in\n>> +context lines. Unfortunately, this means that if the \"old\" lines being\n>> +replaced by the patch differ only in whitespace from the existing\n>> +file, you will get a merge conflict instead of a successful patch\n>> +application.\n>> ++\n>> +merge backend: Treat lines with only whitespace changes as unchanged\n>> +when merging. Unfortunately, this means that any patch hunks that were\n>> +intended to modify whitespace and nothing else will be dropped, even\n>> +if the other side had no changes that conflicted.\n>> +\n>>   --whitespace=<option>::\n>> -\tThese flags are passed to the 'git apply' program\n>> +\tThis flag is passed to the 'git apply' program\n>>   \t(see linkgit:git-apply[1]) that applies the patch.\n>>   \tImplies --apply.\n>>   +\n>> @@ -572,7 +587,6 @@ The following options:\n>>    * --apply\n>>    * --committer-date-is-author-date\n>>    * --ignore-date\n>> - * --ignore-whitespace\n>>    * --whitespace\n>>    * -C\n>>   \n>> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n>>    * --preserve-merges and --signoff\n>>    * --preserve-merges and --rebase-merges\n>>    * --preserve-merges and --empty=\n>> + * --preserve-merges and --ignore-whitespace\n>>    * --keep-base and --onto\n>>    * --keep-base and --root\n>>   \n>> diff --git a/builtin/rebase.c b/builtin/rebase.c\n>> index 27a07d4e78..810c9b7779 100644\n>> --- a/builtin/rebase.c\n>> +++ b/builtin/rebase.c\n>> @@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>>   \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>>   \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>>   \treplay.strategy = opts->strategy;\n>> +\n>>   \tif (opts->strategy_opts)\n>>   \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n>>   \n>> @@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>   \tstruct strbuf revisions = STRBUF_INIT;\n>>   \tstruct strbuf buf = STRBUF_INIT;\n>>   \tstruct object_id merge_base;\n>> +\tint ignore_whitespace = 0;\n>>   \tenum action action = ACTION_NONE;\n>>   \tconst char *gpg_sign = NULL;\n>>   \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n>> @@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>   \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>>   \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>>   \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n>> -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n>> -\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n>> -\t\t\t\t  PARSE_OPT_NOARG),\n>>   \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n>>   \t\t\t\t  &options.git_am_opts, NULL,\n>>   \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>>   \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>>   \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>>   \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n>>   \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n>> +\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n>> +\t\t\t N_(\"ignore changes in whitespace\")),\n>>   \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n>>   \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n>>   \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n>> @@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>>   \t\timply_merge(&options, \"--rebase-merges\");\n>>   \t}\n>>   \n>> +\tif (options.type == REBASE_APPLY) {\n>> +\t\tif (ignore_whitespace)\n>> +\t\t\targv_array_push (&options.git_am_opts,\n>> +\t\t\t\t\t \"--ignore-whitespace\");\n>> +\t} else if (ignore_whitespace) {\n>> +\t\t\tstring_list_append (&strategy_options,\n>> +\t\t\t\t\t    \"ignore-space-change\");\n>> +\t}\n>> +\n> \n> Hm, I've just noticed this by now.\n> Would it's better if we rewrite it as:\n> \n> \tif (ignore_whitespace) {\n> \t\tif (options.type == REBASE_APPLY)\n> \t\t\targv_array_push(&options.git_am_opts,\n> \t\t\t\t\t\"--ignore-whitespace\");\n> \t\telse\n> \t\t\tstring_list_append(&strategy_options,\n> \t\t\t\t\t   \"ignore-space-change\");\n> \t}\n> \n> Ah, the incoming patches will add more conditions into the:\n> \n> \tif (options.type == REBASE_APPLY)\n> \n> I'm still not convinced, though.\n\nI wanted to keep the subsequent patches as simple as possible. Having to \nrewrite the if statement in the next patch just clutters it up and makes \nthe real changes introduced by that patch less obvious\n\n> Anyway, IIRC, --ignore-whitespace and --ignore-space-change has the\n> same meaning, I think it's better to use the same option for both\n> legs, no?\n> \n> I can understand the decision to use --ignore-whitespace as keeping\n> the pass-through behavior of old code, but I think future maintenance\n> is more important than that.\n\nI'm not sure how it affects future maintenance. The two different \noptions are for two different commands so I'm not sure it is worth the \neffort\n\nBest Wishes\n\nPhillip\n\n> I've tried changing ignore-whitespace to ignore-space-change and run\n> make test\n> \n> It looks good to me (aka nothing failed _in my machine_),\n> 4/5 and 5/5 is not applied, though.\n> \n>>   \tif (strategy_options.nr) {\n>>   \t\tint i;\n>>   \n>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>> index 50e7960702..55ca46786d 100755\n>> --- a/t/t3422-rebase-incompatible-options.sh\n>> +++ b/t/t3422-rebase-incompatible-options.sh\n>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>   }\n>>   \n>>   test_rebase_am_only --whitespace=fix\n>> -test_rebase_am_only --ignore-whitespace\n>>   test_rebase_am_only --committer-date-is-author-date\n>>   test_rebase_am_only -C4\n>>   \n>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>> new file mode 100755\n>> index 0000000000..4f8a6e51c9\n>> --- /dev/null\n>> +++ b/t/t3436-rebase-more-options.sh\n>> @@ -0,0 +1,60 @@\n>> +#!/bin/sh\n>> +#\n>> +# Copyright (c) 2019 Rohit Ashiwal\n>> +#\n>> +\n>> +test_description='tests to ensure compatibility between am and interactive backends'\n>> +\n>> +. ./test-lib.sh\n>> +\n>> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n>> +\n>> +# This is a special case in which both am and interactive backends\n>> +# provide the same output. It was done intentionally because\n>> +# both the backends fall short of optimal behaviour.\n>> +test_expect_success 'setup' '\n>> +\tgit checkout -b topic &&\n>> +\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n>> +\tgit add file &&\n>> +\tgit commit -m \"add file\" &&\n>> +\n>> +\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>> +\tgit commit -am \"update file\" &&\n>> +\tgit tag side &&\n>> +\n>> +\tgit checkout --orphan master &&\n>> +\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n>> +\tgit commit -am \"add file\" &&\n>> +\tgit tag main\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace works with apply backend' '\n>> +\ttest_must_fail git rebase --apply main side &&\n>> +\tgit rebase --abort &&\n>> +\tgit rebase --apply --ignore-whitespace main side &&\n>> +\tgit diff --exit-code side\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace works with merge backend' '\n>> +\ttest_must_fail git rebase --merge main side &&\n>> +\tgit rebase --abort &&\n>> +\tgit rebase --merge --ignore-whitespace main side &&\n>> +\tgit diff --exit-code side\n>> +'\n>> +\n>> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n>> +\t(\n>> +\t\tset_fake_editor &&\n>> +\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n>> +\t\t\tmain side &&\n>> +\t\tgit rebase --continue\n>> +\t) &&\n>> +\tgit diff --exit-code side\n>> +'\n>> +\n>> +# This must be the last test in this file\n>> +test_expect_success '$EDITOR and friends are unchanged' '\n>> +\ttest_editor_unchanged\n>> +'\n>> +\n>> +test_done\n>> -- \n>> 2.27.0\n>>\n> \n"},{"id":"400693","messageId":"xmqqsgehhnrq.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200626095528.117524-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v5 0/5] cleanup ra/rebase-i-more-options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-06-26T15:04:09Z","receivedAt":"2020-06-26T15:04:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> I've updated the commit messages, option handling and tests as\n> suggested by dscho. I've also changed the tests that used\n> '--strategy=resolve' to use a real external merge strategy so they\n> continue to test the same code path once Alban's patches to handle the\n> resolve strategy without forking are merged\n\nThanks, will take a look and replace.\n\n"},{"id":"400694","messageId":"xmqqo8p5hlyi.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200626095528.117524-2-phillip.wood123@gmail.com","subject":"Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-06-26T15:43:17Z","receivedAt":"2020-06-26T15:43:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> ... This option treats\n> lines with only whitespace changes as unchanged and is implemented in\n> the merge backend by translating it to -Xignore-space-change.\n\nOK.  Hiding the subtle difference is good.\n\n> @@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n>   * --preserve-merges and --signoff\n>   * --preserve-merges and --rebase-merges\n>   * --preserve-merges and --empty=\n> + * --preserve-merges and --ignore-whitespace\n>   * --keep-base and --onto\n>   * --keep-base and --root\n\nHmph...\n\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 27a07d4e78..810c9b7779 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>  \treplay.strategy = opts->strategy;\n> +\n>  \tif (opts->strategy_opts)\n>  \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n\nUsually I would complain about whitespace-only changes to places\nwhere there is no real change, but I am OK with this one.  It does\nmake sense to have a blank here.\n\n> @@ -1850,6 +1851,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\timply_merge(&options, \"--rebase-merges\");\n>  \t}\n>  \n> +\tif (options.type == REBASE_APPLY) {\n> +\t\tif (ignore_whitespace)\n> +\t\t\targv_array_push (&options.git_am_opts,\n> +\t\t\t\t\t \"--ignore-whitespace\");\n> +\t} else if (ignore_whitespace) {\n> +\t\t\tstring_list_append (&strategy_options,\n> +\t\t\t\t\t    \"ignore-space-change\");\n> +\t}\n\nI agree with the other reviewer that \"when --ignore-whitespace is\ngiven, do these different things depending on the .type\" is easier\nto follow.  Also pay attention to the style.  There is no SP between\nthe name of the function and the opening '(' for its parameter list.\n\n\tif (ignore_whitespace) {\n        \tif (options.type == REBASE_APPLY)\n\t\t\targv_array_push(&options.git_am_opts, \"--ignore-whitespace\");\n\t\telse\n\t\t\tstring_list_append(&strategy_options, \"ignore-space-change\");\n\t}\n\n\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 50e7960702..55ca46786d 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>  \n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --ignore-whitespace\n>  test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n\nOK.\n\nThanks.\n"},{"id":"400695","messageId":"xmqqk0zthl0j.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"78c32f2d-3af6-1514-51a3-1110531cbb88@gmail.com","subject":"Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-06-26T16:03:40Z","receivedAt":"2020-06-26T16:03:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>>>   +\tif (options.type == REBASE_APPLY) {\n>>> +\t\tif (ignore_whitespace)\n>>> +\t\t\targv_array_push (&options.git_am_opts,\n>>> +\t\t\t\t\t \"--ignore-whitespace\");\n>>> +\t} else if (ignore_whitespace) {\n>>> +\t\t\tstring_list_append (&strategy_options,\n>>> +\t\t\t\t\t    \"ignore-space-change\");\n>>> +\t}\n>>> +\n>> ...\n> I wanted to keep the subsequent patches as simple as possible. Having\n> to rewrite the if statement in the next patch just clutters it up and\n> makes the real changes introduced by that patch less obvious\n\nA set of different behaviour depending on .type is OK, but then at\nleast the above should be more like this:\n\n\tif (options.type == REBASE_APPLY) {\n\t\tif (ignore_whitespace)\n\t\t\targv_array_push(...);\n\t} else {\n\t\t/* REBASE_MERGE and PRESERVE_MERGES */\n\t\tif (ignore_whitespace)\n\t\t\tstring_list_append(...);\n\t}\n\nor even\n\n\tswitch (options.type) {\n\tcase REBASE_APPLY:\n\t\t...\n\t\tbreak;\n\tcase REBASE_MERGE:\n\tcase REBASE_PRESERVE_MERGES:\n\t\t...\n\t\tbreak;\n\tdefault:\n\t\tBUG(\"unhandled rebase type %d\", options.type);\n\t}\n\nThat would clarify the flow of the logic better.\n\nThanks.\n"},{"id":"400708","messageId":"xmqqftahhjtq.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200626095528.117524-5-phillip.wood123@gmail.com","subject":"Re: [PATCH v5 4/5] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-06-26T16:29:21Z","receivedAt":"2020-06-26T16:29:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> +/* Construct a free()able author string with current time as the author date */\n> +static char *ignore_author_date(const char *author)\n> +{\n> +\tint len = strlen(author);\n\nI'd rather not to see this initialization, because ...\n\n> +\tstruct ident_split ident;\n> +\tstruct strbuf new_author = STRBUF_INIT;\n> +\n> +\tif (split_ident_line(&ident, author, len) < 0) {\n\n... it is away from this line.  This line is better written\n\n\tif (split_ident_line(&ident, author, strlen(author)) < 0) {\n\nto show what the third parameter is about.  It is not just \"len\",\nbut is the length of the second parameter, author.\n\n> +\t\terror(_(\"malformed ident line '%s'\"), author);\n> +\t\treturn NULL;\n> +\t}\n> +\n> +\tlen = ident.mail_end - ident.name_begin + 1;\n> +\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n> +\tdatestamp(&new_author);\n> +\treturn strbuf_detach(&new_author, NULL);\n> +}\n"},{"id":"400709","messageId":"xmqqbll5hjit.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200626095528.117524-6-phillip.wood123@gmail.com","subject":"Re: [PATCH v5 5/5] rebase: add --reset-author-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-06-26T16:35:54Z","receivedAt":"2020-06-26T16:36:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>\n> The previous commit introduced --ignore-date flag to rebase -i, but the\n> name is rather vague as it does not say whether the author date or the\n> committer date is ignored. Add an alias to convey the precise purpose.\n>\n> Helped-by: Junio C Hamano <gitster@pobox.com>\n\nHmph, did I?\n\n> +\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n> +\t\t\t N_(\"ignore author date and use current date\")),\n> +\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n> +\t\t\t\tN_(\"synonym of --reset-author-date\")),\n\nIt is merely hidden but still supported.\n\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 0ede2b8900..5b8963272a 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -117,53 +117,61 @@ test_ctime_is_ignored () {\n>  \t! grep -v +0000 authortime\n>  }\n>  \n> -test_expect_success '--ignore-date works with apply backend' '\n> +test_expect_success '--reset-author-date works with apply backend' '\n>  \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> -\tgit rebase --apply --ignore-date HEAD^ &&\n> +\tgit rebase --apply --reset-author-date HEAD^ &&\n>  \ttest_ctime_is_ignored -1\n>  '\n\nAre there still some tests that check \"--ignore-date\"?  We probably\nshould have them, if we are not removing the support.\n\nThanks.  The entire series looked reasonable to me.\n"},{"id":"400711","messageId":"f0e71021-6aa0-5c7c-4ba5-2b2a892fcad0@gmail.com","threadId":"53176","inReplyTo":"xmqqbll5hjit.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v5 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-06-26T18:07:11Z","receivedAt":"2020-06-26T18:07:16Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Junio\n\nOn 26/06/2020 17:35, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>>\n>> The previous commit introduced --ignore-date flag to rebase -i, but the\n>> name is rather vague as it does not say whether the author date or the\n>> committer date is ignored. Add an alias to convey the precise purpose.\n>>\n>> Helped-by: Junio C Hamano <gitster@pobox.com>\n> \n> Hmph, did I?\n\nYes, you added a fixup d82dfa7f5b (\"rebase -i: finishing touches to\n--reset-author-date\", 2019-11-21) which I squashed into this patch\n\n> \n>> +\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n>> +\t\t\t N_(\"ignore author date and use current date\")),\n>> +\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n>> +\t\t\t\tN_(\"synonym of --reset-author-date\")),\n> \n> It is merely hidden but still supported.\n> \n>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>> index 0ede2b8900..5b8963272a 100755\n>> --- a/t/t3436-rebase-more-options.sh\n>> +++ b/t/t3436-rebase-more-options.sh\n>> @@ -117,53 +117,61 @@ test_ctime_is_ignored () {\n>>  \t! grep -v +0000 authortime\n>>  }\n>>  \n>> -test_expect_success '--ignore-date works with apply backend' '\n>> +test_expect_success '--reset-author-date works with apply backend' '\n>>  \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n>> -\tgit rebase --apply --ignore-date HEAD^ &&\n>> +\tgit rebase --apply --reset-author-date HEAD^ &&\n>>  \ttest_ctime_is_ignored -1\n>>  '\n> \n> Are there still some tests that check \"--ignore-date\"?  We probably\n> should have them, if we are not removing the support.\n\nThis patch converts the existing --ignore-date tests to use\n--reset-author-date and adds a single new test at the end to check\n--ignore-date\n\nBest Wishes\n\nPhillip\n\n> \n> Thanks.  The entire series looked reasonable to me.\n> \n\n"},{"id":"400756","messageId":"20200629141453.GB20303@danh.dev","threadId":"53176","inReplyTo":"78c32f2d-3af6-1514-51a3-1110531cbb88@gmail.com","subject":"Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-06-29T14:14:53Z","receivedAt":"2020-06-29T19:09:11Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"Hi Phillip,\n\nOn 2020-06-26 15:43:00+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> > > +\tif (options.type == REBASE_APPLY) {\n> > > +\t\tif (ignore_whitespace)\n> > > +\t\t\targv_array_push (&options.git_am_opts,\n> > > +\t\t\t\t\t \"--ignore-whitespace\");\n> > > +\t} else if (ignore_whitespace) {\n> > > +\t\t\tstring_list_append (&strategy_options,\n> > > +\t\t\t\t\t    \"ignore-space-change\");\n> > > +\t}\n> > > +\n> > \n> > Hm, I've just noticed this by now.\n> > Would it's better if we rewrite it as:\n> > \n> > \tif (ignore_whitespace) {\n> > \t\tif (options.type == REBASE_APPLY)\n> > \t\t\targv_array_push(&options.git_am_opts,\n> > \t\t\t\t\t\"--ignore-whitespace\");\n> > \t\telse\n> > \t\t\tstring_list_append(&strategy_options,\n> > \t\t\t\t\t   \"ignore-space-change\");\n> > \t}\n> > \n> > Ah, the incoming patches will add more conditions into the:\n> > \n> > \tif (options.type == REBASE_APPLY)\n> > \n> > I'm still not convinced, though.\n> \n> I wanted to keep the subsequent patches as simple as possible. Having to\n> rewrite the if statement in the next patch just clutters it up and makes the\n> real changes introduced by that patch less obvious\n\nI think the code suggested by Junio may be cleaner ;)\nI may write as:\n\n\tif (ignore_whitespace) {\n\t\tif (options.type == REBASE_APPLY)\n\t\t\targv_array_push(...)\n\t\telse\n\t\t\tstring_list_append(...)\n\t}\n\n\tif (other_condition)\n\t\tdo_something_else(...)\n\nI don't know if it's cleaner or not.\nI haven't tried applied it into real code.\n\n> > Anyway, IIRC, --ignore-whitespace and --ignore-space-change has the\n> > same meaning, I think it's better to use the same option for both\n> > legs, no?\n> > \n> > I can understand the decision to use --ignore-whitespace as keeping\n> > the pass-through behavior of old code, but I think future maintenance\n> > is more important than that.\n> \n> I'm not sure how it affects future maintenance. The two different options\n> are for two different commands so I'm not sure it is worth the effort\n\nI vaguely remember I was thinking about same option text in both leg\nwould make the code easier for reasoning. And we can unify the\nrecommendation for both backend. We will never strip\n--ignore-whitespace from git-apply, but it would be easier to always\nanswer: \"--ignore-space-change should be used to ignore space\" when\nsomeone asks about it.\n\nTyping this now makes me wonder if we should teach --ignore-space-change to\ngit-rebase?\n\nThanks,\n\n-- Danh\n\n> \n> Best Wishes\n> \n> Phillip\n> \n> > I've tried changing ignore-whitespace to ignore-space-change and run\n> > make test\n> > \n> > It looks good to me (aka nothing failed _in my machine_),\n> > 4/5 and 5/5 is not applied, though.\n> > \n> > >   \tif (strategy_options.nr) {\n> > >   \t\tint i;\n> > > diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> > > index 50e7960702..55ca46786d 100755\n> > > --- a/t/t3422-rebase-incompatible-options.sh\n> > > +++ b/t/t3422-rebase-incompatible-options.sh\n> > > @@ -61,7 +61,6 @@ test_rebase_am_only () {\n> > >   }\n> > >   test_rebase_am_only --whitespace=fix\n> > > -test_rebase_am_only --ignore-whitespace\n> > >   test_rebase_am_only --committer-date-is-author-date\n> > >   test_rebase_am_only -C4\n> > > diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> > > new file mode 100755\n> > > index 0000000000..4f8a6e51c9\n> > > --- /dev/null\n> > > +++ b/t/t3436-rebase-more-options.sh\n> > > @@ -0,0 +1,60 @@\n> > > +#!/bin/sh\n> > > +#\n> > > +# Copyright (c) 2019 Rohit Ashiwal\n> > > +#\n> > > +\n> > > +test_description='tests to ensure compatibility between am and interactive backends'\n> > > +\n> > > +. ./test-lib.sh\n> > > +\n> > > +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n> > > +\n> > > +# This is a special case in which both am and interactive backends\n> > > +# provide the same output. It was done intentionally because\n> > > +# both the backends fall short of optimal behaviour.\n> > > +test_expect_success 'setup' '\n> > > +\tgit checkout -b topic &&\n> > > +\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n> > > +\tgit add file &&\n> > > +\tgit commit -m \"add file\" &&\n> > > +\n> > > +\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n> > > +\tgit commit -am \"update file\" &&\n> > > +\tgit tag side &&\n> > > +\n> > > +\tgit checkout --orphan master &&\n> > > +\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n> > > +\tgit commit -am \"add file\" &&\n> > > +\tgit tag main\n> > > +'\n> > > +\n> > > +test_expect_success '--ignore-whitespace works with apply backend' '\n> > > +\ttest_must_fail git rebase --apply main side &&\n> > > +\tgit rebase --abort &&\n> > > +\tgit rebase --apply --ignore-whitespace main side &&\n> > > +\tgit diff --exit-code side\n> > > +'\n> > > +\n> > > +test_expect_success '--ignore-whitespace works with merge backend' '\n> > > +\ttest_must_fail git rebase --merge main side &&\n> > > +\tgit rebase --abort &&\n> > > +\tgit rebase --merge --ignore-whitespace main side &&\n> > > +\tgit diff --exit-code side\n> > > +'\n> > > +\n> > > +test_expect_success '--ignore-whitespace is remembered when continuing' '\n> > > +\t(\n> > > +\t\tset_fake_editor &&\n> > > +\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n> > > +\t\t\tmain side &&\n> > > +\t\tgit rebase --continue\n> > > +\t) &&\n> > > +\tgit diff --exit-code side\n> > > +'\n> > > +\n> > > +# This must be the last test in this file\n> > > +test_expect_success '$EDITOR and friends are unchanged' '\n> > > +\ttest_editor_unchanged\n> > > +'\n> > > +\n> > > +test_done\n> > > -- \n> > > 2.27.0\n> > > \n> > \n\n-- \nDanh\n"},{"id":"401477","messageId":"e4a440e5-fc10-f22c-bca2-b5cb077f49a6@gmail.com","threadId":"53176","inReplyTo":"20200629141453.GB20303@danh.dev","subject":"Re: [PATCH v5 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-13T10:02:30Z","receivedAt":"2020-07-13T10:02:36Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 29/06/2020 15:14, Đoàn Trần Công Danh wrote:\n> Hi Phillip,\n> \n> On 2020-06-26 15:43:00+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>>> +\tif (options.type == REBASE_APPLY) {\n>>>> +\t\tif (ignore_whitespace)\n>>>> +\t\t\targv_array_push (&options.git_am_opts,\n>>>> +\t\t\t\t\t \"--ignore-whitespace\");\n>>>> +\t} else if (ignore_whitespace) {\n>>>> +\t\t\tstring_list_append (&strategy_options,\n>>>> +\t\t\t\t\t    \"ignore-space-change\");\n>>>> +\t}\n>>>> +\n>>>\n>>> Hm, I've just noticed this by now.\n>>> Would it's better if we rewrite it as:\n>>>\n>>> \tif (ignore_whitespace) {\n>>> \t\tif (options.type == REBASE_APPLY)\n>>> \t\t\targv_array_push(&options.git_am_opts,\n>>> \t\t\t\t\t\"--ignore-whitespace\");\n>>> \t\telse\n>>> \t\t\tstring_list_append(&strategy_options,\n>>> \t\t\t\t\t   \"ignore-space-change\");\n>>> \t}\n>>>\n>>> Ah, the incoming patches will add more conditions into the:\n>>>\n>>> \tif (options.type == REBASE_APPLY)\n>>>\n>>> I'm still not convinced, though.\n>>\n>> I wanted to keep the subsequent patches as simple as possible. Having to\n>> rewrite the if statement in the next patch just clutters it up and makes the\n>> real changes introduced by that patch less obvious\n> \n> I think the code suggested by Junio may be cleaner ;)\n\nYes, I'll reroll with Junio's suggestion\n\n> I may write as:\n> \n> \tif (ignore_whitespace) {\n> \t\tif (options.type == REBASE_APPLY)\n> \t\t\targv_array_push(...)\n> \t\telse\n> \t\t\tstring_list_append(...)\n> \t}\n> \n> \tif (other_condition)\n> \t\tdo_something_else(...)\n> \n> I don't know if it's cleaner or not.\n\nIt leads to a lot of repetition of ' && options.type == REBASE_APPLY' as\nall the other conditions apart from --ignore-whitespace only need\nhandling for the apply backend here.\n\n> I haven't tried applied it into real code.\n> \n>>> Anyway, IIRC, --ignore-whitespace and --ignore-space-change has the\n>>> same meaning, I think it's better to use the same option for both\n>>> legs, no?\n>>>\n>>> I can understand the decision to use --ignore-whitespace as keeping\n>>> the pass-through behavior of old code, but I think future maintenance\n>>> is more important than that.\n>>\n>> I'm not sure how it affects future maintenance. The two different options\n>> are for two different commands so I'm not sure it is worth the effort\n> \n> I vaguely remember I was thinking about same option text in both leg\n> would make the code easier for reasoning. And we can unify the\n> recommendation for both backend. We will never strip\n> --ignore-whitespace from git-apply, but it would be easier to always\n> answer: \"--ignore-space-change should be used to ignore space\" when\n> someone asks about it.\n> \n> Typing this now makes me wonder if we should teach --ignore-space-change to\n> git-rebase?\n\nPossibly but not as part of this series which is about improving the\nmerge backend rather than adding new options to rebase itself\n\nBest Wishes\n\nPhillip\n\n> \n> Thanks,\n> \n> -- Danh\n> \n>>\n>> Best Wishes\n>>\n>> Phillip\n>>\n>>> I've tried changing ignore-whitespace to ignore-space-change and run\n>>> make test\n>>>\n>>> It looks good to me (aka nothing failed _in my machine_),\n>>> 4/5 and 5/5 is not applied, though.\n>>>\n>>>>   \tif (strategy_options.nr) {\n>>>>   \t\tint i;\n>>>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>>>> index 50e7960702..55ca46786d 100755\n>>>> --- a/t/t3422-rebase-incompatible-options.sh\n>>>> +++ b/t/t3422-rebase-incompatible-options.sh\n>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>>>   }\n>>>>   test_rebase_am_only --whitespace=fix\n>>>> -test_rebase_am_only --ignore-whitespace\n>>>>   test_rebase_am_only --committer-date-is-author-date\n>>>>   test_rebase_am_only -C4\n>>>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>>>> new file mode 100755\n>>>> index 0000000000..4f8a6e51c9\n>>>> --- /dev/null\n>>>> +++ b/t/t3436-rebase-more-options.sh\n>>>> @@ -0,0 +1,60 @@\n>>>> +#!/bin/sh\n>>>> +#\n>>>> +# Copyright (c) 2019 Rohit Ashiwal\n>>>> +#\n>>>> +\n>>>> +test_description='tests to ensure compatibility between am and interactive backends'\n>>>> +\n>>>> +. ./test-lib.sh\n>>>> +\n>>>> +. \"$TEST_DIRECTORY\"/lib-rebase.sh\n>>>> +\n>>>> +# This is a special case in which both am and interactive backends\n>>>> +# provide the same output. It was done intentionally because\n>>>> +# both the backends fall short of optimal behaviour.\n>>>> +test_expect_success 'setup' '\n>>>> +\tgit checkout -b topic &&\n>>>> +\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n>>>> +\tgit add file &&\n>>>> +\tgit commit -m \"add file\" &&\n>>>> +\n>>>> +\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>>>> +\tgit commit -am \"update file\" &&\n>>>> +\tgit tag side &&\n>>>> +\n>>>> +\tgit checkout --orphan master &&\n>>>> +\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n>>>> +\tgit commit -am \"add file\" &&\n>>>> +\tgit tag main\n>>>> +'\n>>>> +\n>>>> +test_expect_success '--ignore-whitespace works with apply backend' '\n>>>> +\ttest_must_fail git rebase --apply main side &&\n>>>> +\tgit rebase --abort &&\n>>>> +\tgit rebase --apply --ignore-whitespace main side &&\n>>>> +\tgit diff --exit-code side\n>>>> +'\n>>>> +\n>>>> +test_expect_success '--ignore-whitespace works with merge backend' '\n>>>> +\ttest_must_fail git rebase --merge main side &&\n>>>> +\tgit rebase --abort &&\n>>>> +\tgit rebase --merge --ignore-whitespace main side &&\n>>>> +\tgit diff --exit-code side\n>>>> +'\n>>>> +\n>>>> +test_expect_success '--ignore-whitespace is remembered when continuing' '\n>>>> +\t(\n>>>> +\t\tset_fake_editor &&\n>>>> +\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n>>>> +\t\t\tmain side &&\n>>>> +\t\tgit rebase --continue\n>>>> +\t) &&\n>>>> +\tgit diff --exit-code side\n>>>> +'\n>>>> +\n>>>> +# This must be the last test in this file\n>>>> +test_expect_success '$EDITOR and friends are unchanged' '\n>>>> +\ttest_editor_unchanged\n>>>> +'\n>>>> +\n>>>> +test_done\n>>>> -- \n>>>> 2.27.0\n>>>>\n>>>\n> \n\n"},{"id":"401478","messageId":"20200713101045.27335-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH v6 0/5] fixup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-13T10:10:40Z","receivedAt":"2020-07-13T10:10:55Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThanks for the comments on the last round, I've modified the\ncontroversial conditional in the first patch as suggested by Junio and\nupdated patch 4 as suggested as well\n\nBest Wishes\n\nPhillip\n\nPhillip Wood (2):\n  rebase -i: support --committer-date-is-author-date\n  rebase -i: support --ignore-date\n\nRohit Ashiwal (3):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: rename amend_author to author_to_free\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt           |  33 ++++-\n builtin/rebase.c                       |  47 +++++--\n sequencer.c                            | 112 ++++++++++++++-\n sequencer.h                            |   2 +\n t/t3422-rebase-incompatible-options.sh |   2 -\n t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++\n 6 files changed, 353 insertions(+), 23 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\nRange-diff against v5:\n1:  43ee10d4d5 ! 1:  5bb4226007 rebase -i: add --ignore-whitespace flag\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \n     +\tif (options.type == REBASE_APPLY) {\n     +\t\tif (ignore_whitespace)\n    -+\t\t\targv_array_push (&options.git_am_opts,\n    -+\t\t\t\t\t \"--ignore-whitespace\");\n    -+\t} else if (ignore_whitespace) {\n    -+\t\t\tstring_list_append (&strategy_options,\n    -+\t\t\t\t\t    \"ignore-space-change\");\n    ++\t\t\targv_array_push(&options.git_am_opts,\n    ++\t\t\t\t\t\"--ignore-whitespace\");\n    ++\t} else {\n    ++\t\t/* REBASE_MERGE and PRESERVE_MERGES */\n    ++\t\tif (ignore_whitespace) {\n    ++\t\t\tstring_list_append(&strategy_options,\n    ++\t\t\t\t\t   \"ignore-space-change\");\n    ++\t\t}\n     +\t}\n     +\n      \tif (strategy_options.nr) {\n2:  a2b57df19c ! 2:  e5fdb574ed rebase -i: support --committer-date-is-author-date\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t\tallow_preemptive_ff = 0;\n     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)\n      \t\tif (ignore_whitespace)\n    - \t\t\targv_array_push (&options.git_am_opts,\n    - \t\t\t\t\t \"--ignore-whitespace\");\n    + \t\t\targv_array_push(&options.git_am_opts,\n    + \t\t\t\t\t\"--ignore-whitespace\");\n     +\t\tif (options.committer_date_is_author_date)\n     +\t\t\targv_array_push(&options.git_am_opts,\n     +\t\t\t\t\t\"--committer-date-is-author-date\");\n    - \t} else if (ignore_whitespace) {\n    - \t\t\tstring_list_append (&strategy_options,\n    - \t\t\t\t\t    \"ignore-space-change\");\n    + \t} else {\n    + \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n    + \t\tif (ignore_whitespace) {\n     \n      ## sequencer.c ##\n     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n3:  363a0140ad = 3:  cf5c9a2456 sequencer: rename amend_author to author_to_free\n4:  46d9e108be ! 4:  0fc90eaff1 rebase -i: support --ignore-date\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n     -\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n     -\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n     +\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n    -+\t\t\t \"ignore author date and use current date\"),\n    ++\t\t\t N_(\"ignore author date and use current date\")),\n      \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n      \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n      \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t\t\t\t\"--committer-date-is-author-date\");\n     +\t\tif (options.ignore_date)\n     +\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n    - \t} else if (ignore_whitespace) {\n    - \t\t\tstring_list_append (&strategy_options,\n    - \t\t\t\t\t    \"ignore-space-change\");\n    + \t} else {\n    + \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n    + \t\tif (ignore_whitespace) {\n     \n      ## sequencer.c ##\n     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n    @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr\n     +/* Construct a free()able author string with current time as the author date */\n     +static char *ignore_author_date(const char *author)\n     +{\n    -+\tint len = strlen(author);\n    ++\tint len;\n     +\tstruct ident_split ident;\n     +\tstruct strbuf new_author = STRBUF_INIT;\n     +\n    -+\tif (split_ident_line(&ident, author, len) < 0) {\n    ++\tif (split_ident_line(&ident, author, strlen(author)) < 0) {\n     +\t\terror(_(\"malformed ident line '%s'\"), author);\n     +\t\treturn NULL;\n     +\t}\n5:  26d5eefdcb ! 5:  21cf5e5512 rebase: add --reset-author-date\n    @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix\n      \t\t\t &options.committer_date_is_author_date,\n      \t\t\t N_(\"make committer date match author date\")),\n     -\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n    --\t\t\t \"ignore author date and use current date\"),\n     +\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n    -+\t\t\t N_(\"ignore author date and use current date\")),\n    + \t\t\t N_(\"ignore author date and use current date\")),\n     +\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n     +\t\t\t\tN_(\"synonym of --reset-author-date\")),\n      \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n-- \n2.27.0\n\n"},{"id":"401479","messageId":"20200713101045.27335-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200713101045.27335-1-phillip.wood123@gmail.com","subject":"[PATCH v6 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-13T10:10:42Z","receivedAt":"2020-07-13T10:10:58Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--committer-date-is-author-date option to the merge backend. This\noption uses the author date of the commit that is being rewritten as\nthe committer date when the new commit is created.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 10 +++--\n builtin/rebase.c                       | 17 +++++---\n sequencer.c                            | 60 +++++++++++++++++++++++++-\n sequencer.h                            |  1 +\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++++++++++-\n 6 files changed, 136 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex b003784f01..dfa70263e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of using the current time as the committer date, use\n+\tthe author date of the commit being rebased as the committer\n+\tdate. This option implies --force-rebase.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tThis flag is passed to 'git am' to change the author date\n+\tof each rebased commit (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex bd93e9742c..2579380729 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -88,6 +88,7 @@ struct rebase_options {\n \tint autosquash;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n+\tif (options.committer_date_is_author_date)\n+\t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n+\t\tif (!strcmp(option, \"--ignore-date\") ||\n \t\t    !strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (ignore_whitespace)\n \t\t\targv_array_push(&options.git_am_opts,\n \t\t\t\t\t\"--ignore-whitespace\");\n+\t\tif (options.committer_date_is_author_date)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--committer-date-is-author-date\");\n \t} else {\n \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n \t\tif (ignore_whitespace) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 6fd2674632..368d397970 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -872,6 +873,22 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+static const char *author_date_from_env_array(const struct argv_array *env)\n+{\n+\tint i;\n+\tconst char *date;\n+\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n \n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \targv_array_push(&cmd.args, \"commit\");\n \n \tif (!(flags & VERIFY_MSG))\n@@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,\n \t\tcommit_list_insert(current_head, &parents);\n \t}\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tstruct ident_split ident;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n+\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!ident.date_begin) {\n+\t\t\tres = error(_(\"corrupted author without date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(ident.date_end - ident.date_begin),\n+\t\t\t    ident.date_begin,\n+\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n+\t\t\t    ident.tz_begin);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&date);\n+\n+\t\tif (res)\n+\t\t\tgoto out;\n+\t}\n+\n \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n \t\tres = error(_(\"git write-tree failed to write a tree\"));\n \t\tgoto out;\n@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n \tif (opts->keep_redundant_commits)\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n \t\t\tgoto leave_merge;\n \t\t}\n \n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n \t\targv_array_push(&cmd.args, \"-s\");\n@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t\topts->record_origin || opts->edit ||\n+\t\t\t\topts->committer_date_is_author_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 0bee85093e..4ab94119ae 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -45,6 +45,7 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n \n \tint mainline;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 55ca46786d..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 4f8a6e51c9..50a63d8ebe 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n # This is a special case in which both am and interactive backends\n # provide the same output. It was done intentionally because\n # both the backends fall short of optimal behaviour.\n@@ -21,11 +24,20 @@ test_expect_success 'setup' '\n \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n \tgit commit -am \"update file\" &&\n \tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n \n \tgit checkout --orphan master &&\n+\trm foo &&\n \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n \tgit commit -am \"add file\" &&\n-\tgit tag main\n+\tgit tag main &&\n+\n+\tmkdir test-bin &&\n+\twrite_script test-bin/git-merge-test <<-\\EOF\n+\texec git-merge-recursive \"$@\"\n+\tEOF\n '\n \n test_expect_success '--ignore-whitespace works with apply backend' '\n@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n \tgit diff --exit-code side\n '\n \n+test_ctime_is_atime () {\n+\tgit log $1 --format=%ai >authortime &&\n+\tgit log $1 --format=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+}\n+\n+test_expect_success '--committer-date-is-author-date works with apply backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with merge backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n+\t\t\t\t\t--committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -1\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"401482","messageId":"20200713101045.27335-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200713101045.27335-1-phillip.wood123@gmail.com","subject":"[PATCH v6 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-13T10:10:41Z","receivedAt":"2020-07-13T10:11:00Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--ignore-whitespace option to the merge backend. This option treats\nlines with only whitespace changes as unchanged and is implemented in\nthe merge backend by translating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 19 +++++++-\n builtin/rebase.c                       | 19 ++++++--\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++\n 4 files changed, 93 insertions(+), 6 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f7a6033607..b003784f01 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tIgnore whitespace differences when trying to reconcile\n+differences. Currently, each backend implements an approximation of\n+this behavior:\n++\n+apply backend: When applying a patch, ignore changes in whitespace in\n+context lines. Unfortunately, this means that if the \"old\" lines being\n+replaced by the patch differ only in whitespace from the existing\n+file, you will get a merge conflict instead of a successful patch\n+application.\n++\n+merge backend: Treat lines with only whitespace changes as unchanged\n+when merging. Unfortunately, this means that any patch hunks that were\n+intended to modify whitespace and nothing else will be dropped, even\n+if the other side had no changes that conflicted.\n+\n --whitespace=<option>::\n-\tThese flags are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n \tImplies --apply.\n +\n@@ -572,7 +587,6 @@ The following options:\n  * --apply\n  * --committer-date-is-author-date\n  * --ignore-date\n- * --ignore-whitespace\n  * --whitespace\n  * -C\n \n@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n+ * --preserve-merges and --ignore-whitespace\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 27a07d4e78..bd93e9742c 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n \n@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tstruct strbuf revisions = STRBUF_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct object_id merge_base;\n+\tint ignore_whitespace = 0;\n \tenum action action = ACTION_NONE;\n \tconst char *gpg_sign = NULL;\n \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\timply_merge(&options, \"--rebase-merges\");\n \t}\n \n+\tif (options.type == REBASE_APPLY) {\n+\t\tif (ignore_whitespace)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--ignore-whitespace\");\n+\t} else {\n+\t\t/* REBASE_MERGE and PRESERVE_MERGES */\n+\t\tif (ignore_whitespace) {\n+\t\t\tstring_list_append(&strategy_options,\n+\t\t\t\t\t   \"ignore-space-change\");\n+\t\t}\n+\t}\n+\n \tif (strategy_options.nr) {\n \t\tint i;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..55ca46786d 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nnew file mode 100755\nindex 0000000000..4f8a6e51c9\n--- /dev/null\n+++ b/t/t3436-rebase-more-options.sh\n@@ -0,0 +1,60 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\n+\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\n+\tgit checkout --orphan master &&\n+\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n+\tgit commit -am \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with apply backend' '\n+\ttest_must_fail git rebase --apply main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --apply --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace works with merge backend' '\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n+\t\t\tmain side &&\n+\t\tgit rebase --continue\n+\t) &&\n+\tgit diff --exit-code side\n+'\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n+test_done\n-- \n2.27.0\n\n"},{"id":"401480","messageId":"20200713101045.27335-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200713101045.27335-1-phillip.wood123@gmail.com","subject":"[PATCH v6 3/5] sequencer: rename amend_author to author_to_free","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-13T10:10:43Z","receivedAt":"2020-07-13T10:11:01Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() when amending a commit. But we can\nalso use the variable to free() the author at our convenience.\nRename it to convey this meaning.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 368d397970..29f6d1bc39 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n-\tchar *amend_author = NULL;\n+\tchar *author_to_free = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tstrbuf_addstr(msg, orig_message);\n \t\t\thook_commit = \"HEAD\";\n \t\t}\n-\t\tauthor = amend_author = get_author(message);\n+\t\tauthor = author_to_free = get_author(message);\n \t\tunuse_commit_buffer(current_head, message);\n \t\tif (!author) {\n \t\t\tres = error(_(\"unable to parse commit author\"));\n@@ -1474,7 +1474,7 @@ static int try_to_commit(struct repository *r,\n \tfree_commit_extra_headers(extra);\n \tstrbuf_release(&err);\n \tstrbuf_release(&commit_msg);\n-\tfree(amend_author);\n+\tfree(author_to_free);\n \n \treturn res;\n }\n-- \n2.27.0\n\n"},{"id":"401483","messageId":"20200713101045.27335-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200713101045.27335-1-phillip.wood123@gmail.com","subject":"[PATCH v6 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-13T10:10:44Z","receivedAt":"2020-07-13T10:11:02Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the --ignore-date\noption to the merge backend. This option uses the current time as the\nauthor date rather than reusing the original author date when\nrewriting commits. We take care to handle the combination of\n--ignore-date and --committer-date-is-author-date in the same way as\nthe apply backend.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt   |  7 +++--\n builtin/rebase.c               | 13 +++++---\n sequencer.c                    | 50 ++++++++++++++++++++++++++++--\n sequencer.h                    |  1 +\n t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++\n 5 files changed, 117 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex dfa70263e6..e2717e20e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof each rebased commit (see linkgit:git-am[1]).\n+\tInstead of using the author date of the original commit, use\n+\tthe current time as the\tauthor date of the rebased commit.  This\n+\toption implies `--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n  * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 2579380729..583ac96fc7 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -89,6 +89,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.committer_date_is_author_date =\n \t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n-\tif (options.committer_date_is_author_date)\n+\tif (options.committer_date_is_author_date || options.ignore_date)\n \t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\n@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (options.committer_date_is_author_date)\n \t\t\targv_array_push(&options.git_am_opts,\n \t\t\t\t\t\"--committer-date-is-author-date\");\n+\t\tif (options.ignore_date)\n+\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n \t} else {\n \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n \t\tif (ignore_whitespace) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 29f6d1bc39..c140162cbd 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n }\n \n+/* Construct a free()able author string with current time as the author date */\n+static char *ignore_author_date(const char *author)\n+{\n+\tint len;\n+\tstruct ident_split ident;\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\n+\tif (split_ident_line(&ident, author, strlen(author)) < 0) {\n+\t\terror(_(\"malformed ident line '%s'\"), author);\n+\t\treturn NULL;\n+\t}\n+\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n \n \tif (opts->committer_date_is_author_date)\n \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n \t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,\n \t\t\t    ident.date_begin,\n \t\t\t    (int)(ident.tz_end - ident.tz_begin),\n \t\t\t    ident.tz_begin);\n-\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n \t\tstrbuf_release(&date);\n \n \t\tif (res)\n@@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tauthor = ignore_author_date(author);\n+\t\tif (!author) {\n+\t\t\tres = -1;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tfree(author_to_free);\n+\t\tauthor_to_free = (char *)author;\n+\t}\n+\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->committer_date_is_author_date = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n \tif (opts->committer_date_is_author_date)\n \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,\n \n \t\tif (opts->committer_date_is_author_date)\n \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n \t\t\t\topts->record_origin || opts->edit ||\n-\t\t\t\topts->committer_date_is_author_date));\n+\t\t\t\topts->committer_date_is_author_date ||\n+\t\t\t\topts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 4ab94119ae..3587878e3b 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -46,6 +46,7 @@ struct replay_opts {\n \tint quiet;\n \tint reschedule_failed_exec;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 50a63d8ebe..0ede2b8900 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n \ttest_ctime_is_atime -1\n '\n \n+# Checking for +0000 in the author date is sufficient since the\n+# default timezone is UTC but the timezone used while committing is\n+# +0530. The inverted logic in the grep is necessary to check all the\n+# author dates in the file.\n+test_ctime_is_ignored () {\n+\tgit log $1 --format=%ai >authortime &&\n+\t! grep -v +0000 authortime\n+}\n+\n+test_expect_success '--ignore-date works with apply backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with merge backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -m HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -m \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\ttest_ctime_is_ignored\n+'\n+\n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -2 &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n+\t\t\t\t--ignore-date --committer-date-is-author-date \\\n+\t\t\t\tside side &&\n+\ttest_ctime_is_atime -1 &&\n+\ttest_ctime_is_ignored -1\n+ '\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"401481","messageId":"20200713101045.27335-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200713101045.27335-1-phillip.wood123@gmail.com","subject":"[PATCH v6 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-13T10:10:45Z","receivedAt":"2020-07-13T10:11:03Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe previous commit introduced --ignore-date flag to rebase -i, but the\nname is rather vague as it does not say whether the author date or the\ncommitter date is ignored. Add an alias to convey the precise purpose.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt   |  1 +\n builtin/rebase.c               |  4 +++-\n t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------\n 3 files changed, 25 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e2717e20e6..a5f82913fb 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the author date of the original commit, use\n \tthe current time as the\tauthor date of the rebased commit.  This\n \toption implies `--force-rebase`.\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 583ac96fc7..b126fbe940 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n \t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 0ede2b8900..5b8963272a 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -117,53 +117,61 @@ test_ctime_is_ignored () {\n \t! grep -v +0000 authortime\n }\n \n-test_expect_success '--ignore-date works with apply backend' '\n+test_expect_success '--reset-author-date works with apply backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit rebase --apply --reset-author-date HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with merge backend' '\n+test_expect_success '--reset-author-date works with merge backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit rebase --reset-author-date -m HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works after conflict resolution' '\n-\ttest_must_fail git rebase --ignore-date -m \\\n+test_expect_success '--reset-author-date works after conflict resolution' '\n+\ttest_must_fail git rebase --reset-author-date -m \\\n \t\t--onto commit2^^ commit2^ commit2 &&\n \techo resolved >foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with rebase -r' '\n+test_expect_success '--reset-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n-\tgit rebase -r --root --ignore-date &&\n+\tgit rebase -r --root --reset-author-date &&\n \ttest_ctime_is_ignored\n '\n \n-test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '\n \ttest_must_fail git rebase -m --committer-date-is-author-date \\\n-\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\t\t--reset-author-date --onto commit2^^ commit2^ commit3 &&\n \tgit checkout --theirs foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_atime -2 &&\n \ttest_ctime_is_ignored -2\n '\n \n-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n \t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n-\t\t\t\t--ignore-date --committer-date-is-author-date \\\n-\t\t\t\tside side &&\n+\t\t\t\t--reset-author-date \\\n+\t\t\t\t--committer-date-is-author-date side side &&\n \ttest_ctime_is_atime -1 &&\n \ttest_ctime_is_ignored -1\n  '\n \n+test_expect_success '--ignore-date is an alias for --reset-author-date' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase -m --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"401490","messageId":"xmqqo8ojo2ml.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200713101045.27335-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v6 0/5] fixup ra/rebase-i-more-options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-07-13T15:28:50Z","receivedAt":"2020-07-13T15:28:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Phillip Wood (2):\n>   rebase -i: support --committer-date-is-author-date\n>   rebase -i: support --ignore-date\n>\n> Rohit Ashiwal (3):\n>   rebase -i: add --ignore-whitespace flag\n>   sequencer: rename amend_author to author_to_free\n>   rebase: add --reset-author-date\n\nThanks for polishing them further.\n\nWill queue; with help from others, this can be one of the early\ntopics to be merged after 2.28 gets tagged, hopefully?\n"},{"id":"401579","messageId":"e0cfe987-1b47-6b5e-b4e9-10223b73fe22@gmail.com","threadId":"53176","inReplyTo":"xmqqo8ojo2ml.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v6 0/5] fixup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-15T08:55:19Z","receivedAt":"2020-07-15T08:55:24Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/07/2020 16:28, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> Phillip Wood (2):\n>>    rebase -i: support --committer-date-is-author-date\n>>    rebase -i: support --ignore-date\n>>\n>> Rohit Ashiwal (3):\n>>    rebase -i: add --ignore-whitespace flag\n>>    sequencer: rename amend_author to author_to_free\n>>    rebase: add --reset-author-date\n> \n> Thanks for polishing them further.\n> \n> Will queue; with help from others, this can be one of the early\n> topics to be merged after 2.28 gets tagged, hopefully?\n\nYes I hope so, I'm not aware of any outstanding issues (lets see if the \nreviewers agree)\n\nBest Wishes\n\nPhillip\n\n"},{"id":"401586","messageId":"20200715142717.GA7803@danh.dev","threadId":"53176","inReplyTo":"20200713101045.27335-3-phillip.wood123@gmail.com","subject":"Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-07-15T14:27:33Z","receivedAt":"2020-07-15T14:27:38Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"\nHi Phillip,\n\nOn 2020-07-13 11:10:42+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index bd93e9742c..2579380729 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -88,6 +88,7 @@ struct rebase_options {\n>  \tint autosquash;\n>  \tchar *gpg_sign_opt;\n>  \tint autostash;\n> +\tint committer_date_is_author_date;\n>  \tchar *cmd;\n>  \tint allow_empty_message;\n>  \tint rebase_merges, rebase_cousins;\n> @@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>  \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n>  \treplay.verbose = opts->flags & REBASE_VERBOSE;\n>  \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n> +\treplay.committer_date_is_author_date =\n> +\t\t\t\t\topts->committer_date_is_author_date;\n>  \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>  \treplay.strategy = opts->strategy;\n>  \n> @@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n>  \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n>  \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n> -\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n> -\t\t\t\t  &options.git_am_opts, NULL,\n> -\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n> +\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n> +\t\t\t &options.committer_date_is_author_date,\n> +\t\t\t N_(\"make committer date match author date\")),\n>  \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n>  \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n>  \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n> @@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t    options.autosquash) {\n>  \t\tallow_preemptive_ff = 0;\n>  \t}\n> +\tif (options.committer_date_is_author_date)\n> +\t\toptions.flags |= REBASE_FORCE;\n>  \n>  \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n>  \t\tconst char *option = options.git_am_opts.argv[i], *p;\n> -\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n> -\t\t    !strcmp(option, \"--ignore-date\") ||\n> +\t\tif (!strcmp(option, \"--ignore-date\") ||\n>  \t\t    !strcmp(option, \"--whitespace=fix\") ||\n>  \t\t    !strcmp(option, \"--whitespace=strip\"))\n>  \t\t\tallow_preemptive_ff = 0;\n> @@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>  \t\tif (ignore_whitespace)\n>  \t\t\targv_array_push(&options.git_am_opts,\n>  \t\t\t\t\t\"--ignore-whitespace\");\n> +\t\tif (options.committer_date_is_author_date)\n> +\t\t\targv_array_push(&options.git_am_opts,\n> +\t\t\t\t\t\"--committer-date-is-author-date\");\n>  \t} else {\n>  \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n>  \t\tif (ignore_whitespace) {\n> diff --git a/sequencer.c b/sequencer.c\n> index 6fd2674632..368d397970 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n>   * command-line.\n>   */\n>  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n> +static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n>  static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n>  static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n>  static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n> @@ -872,6 +873,22 @@ static char *get_author(const char *message)\n>  \treturn NULL;\n>  }\n>  \n> +static const char *author_date_from_env_array(const struct argv_array *env)\n> +{\n> +\tint i;\n> +\tconst char *date;\n> +\n> +\tfor (i = 0; i < env->argc; i++)\n> +\t\tif (skip_prefix(env->argv[i],\n> +\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n> +\t\t\treturn date;\n> +\t/*\n> +\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n> +\t * reading the script\n> +\t */\n> +\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n> +}\n> +\n>  static const char staged_changes_advice[] =\n>  N_(\"you have staged changes in your working tree\\n\"\n>  \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n> @@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n>  \t\t\t     gpg_opt, gpg_opt);\n>  \t}\n>  \n> +\tif (opts->committer_date_is_author_date)\n> +\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\n>  \targv_array_push(&cmd.args, \"commit\");\n>  \n>  \tif (!(flags & VERIFY_MSG))\n> @@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,\n>  \t\tcommit_list_insert(current_head, &parents);\n>  \t}\n>  \n> +\tif (opts->committer_date_is_author_date) {\n> +\t\tstruct ident_split ident;\n> +\t\tstruct strbuf date = STRBUF_INIT;\n> +\n> +\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n> +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n\nI've checked with the translation for my native language (vi).\nThe translators seem to misread ident (as in identity) as\nindent (as in indentation).\n\nThe translation in po/vi.po:25045 (of v2.28.0-rc0) reads:\n\n\t#~ msgid \"malformed ident line\"\n\t#~ msgstr \"thụt đầu dòng dị hình\"\n\nTranslating back to English, it reads: \"malformed indentation\".\n\nHence, I think it would read better if we write:\n\n\tres = error(_(\"malformed identity line '%s'\"), author);\n\n3 more characters is not that much :)\n\n> +\t\t\tgoto out;\n> +\t\t}\n> +\t\tif (!ident.date_begin) {\n> +\t\t\tres = error(_(\"corrupted author without date information\"));\n> +\t\t\tgoto out;\n> +\t\t}\n> +\n> +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n> +\t\t\t    (int)(ident.date_end - ident.date_begin),\n> +\t\t\t    ident.date_begin,\n> +\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n> +\t\t\t    ident.tz_begin);\n> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +\t\tstrbuf_release(&date);\n> +\n> +\t\tif (res)\n> +\t\t\tgoto out;\n> +\t}\n> +\n>  \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>  \t\tres = error(_(\"git write-tree failed to write a tree\"));\n>  \t\tgoto out;\n> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>  \t\t\topts->signoff = 1;\n>  \t\t}\n>  \n> +\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n> +\t\t\topts->allow_ff = 0;\n> +\t\t\topts->committer_date_is_author_date = 1;\n> +\t\t}\n> +\n>  \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n>  \t\t\topts->reschedule_failed_exec = 1;\n>  \n> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>  \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>  \tif (opts->keep_redundant_commits)\n>  \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n> +\tif (opts->committer_date_is_author_date)\n> +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>  \tif (opts->reschedule_failed_exec)\n>  \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>  \n> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n>  \t\t\tgoto leave_merge;\n>  \t\t}\n>  \n> +\t\tif (opts->committer_date_is_author_date)\n> +\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\n>  \t\tcmd.git_cmd = 1;\n>  \t\targv_array_push(&cmd.args, \"merge\");\n>  \t\targv_array_push(&cmd.args, \"-s\");\n> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n>  \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>  \tif (opts->allow_ff)\n>  \t\tassert(!(opts->signoff || opts->no_commit ||\n> -\t\t\t\topts->record_origin || opts->edit));\n> +\t\t\t\topts->record_origin || opts->edit ||\n> +\t\t\t\topts->committer_date_is_author_date));\n>  \tif (read_and_refresh_cache(r, opts))\n>  \t\treturn -1;\n>  \n> diff --git a/sequencer.h b/sequencer.h\n> index 0bee85093e..4ab94119ae 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -45,6 +45,7 @@ struct replay_opts {\n>  \tint verbose;\n>  \tint quiet;\n>  \tint reschedule_failed_exec;\n> +\tint committer_date_is_author_date;\n>  \n>  \tint mainline;\n>  \n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 55ca46786d..c8234062c6 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>  \n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>  \n>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 4f8a6e51c9..50a63d8ebe 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>  \n>  . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>  \n> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> +export GIT_AUTHOR_DATE\n> +\n>  # This is a special case in which both am and interactive backends\n>  # provide the same output. It was done intentionally because\n>  # both the backends fall short of optimal behaviour.\n> @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n>  \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>  \tgit commit -am \"update file\" &&\n>  \tgit tag side &&\n> +\ttest_commit commit1 foo foo1 &&\n> +\ttest_commit commit2 foo foo2 &&\n> +\ttest_commit commit3 foo foo3 &&\n>  \n>  \tgit checkout --orphan master &&\n> +\trm foo &&\n>  \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n>  \tgit commit -am \"add file\" &&\n> -\tgit tag main\n> +\tgit tag main &&\n> +\n> +\tmkdir test-bin &&\n> +\twrite_script test-bin/git-merge-test <<-\\EOF\n> +\texec git-merge-recursive \"$@\"\n> +\tEOF\n>  '\n>  \n>  test_expect_success '--ignore-whitespace works with apply backend' '\n> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n>  \tgit diff --exit-code side\n>  '\n>  \n> +test_ctime_is_atime () {\n> +\tgit log $1 --format=%ai >authortime &&\n> +\tgit log $1 --format=%ci >committertime &&\n> +\ttest_cmp authortime committertime\n> +}\n> +\n> +test_expect_success '--committer-date-is-author-date works with apply backend' '\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n> +\ttest_ctime_is_atime -1\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with merge backend' '\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n> +\ttest_ctime_is_atime -1\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n> +\tgit checkout side &&\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +\tgit rebase -r --root --committer-date-is-author-date &&\n> +\ttest_ctime_is_atime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n> +\tgit checkout side &&\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n> +\t\t\t\t\t--committer-date-is-author-date &&\n> +\ttest_ctime_is_atime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n> +\tgit checkout commit2 &&\n> +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n> +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n> +\t\t--onto HEAD^^ HEAD^ &&\n> +\techo resolved > foo &&\n\nNitpick: no space after \">\" :D\n\n-- \nDanh\n"},{"id":"401618","messageId":"281d92d3-f901-bca1-6030-fd0c8761f214@gmail.com","threadId":"53176","inReplyTo":"20200715142717.GA7803@danh.dev","subject":"Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T08:23:17Z","receivedAt":"2020-07-16T08:23:23Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 15/07/2020 15:27, Đoàn Trần Công Danh wrote:\n> \n> Hi Phillip,\n> \n> On 2020-07-13 11:10:42+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n >> [...]\n>>   \n>> +\tif (opts->committer_date_is_author_date) {\n>> +\t\tstruct ident_split ident;\n>> +\t\tstruct strbuf date = STRBUF_INIT;\n>> +\n>> +\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n>> +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n> \n> I've checked with the translation for my native language (vi).\n> The translators seem to misread ident (as in identity) as\n> indent (as in indentation).\n> \n> The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:\n> \n> \t#~ msgid \"malformed ident line\"\n> \t#~ msgstr \"thụt đầu dòng dị hình\"\n> \n> Translating back to English, it reads: \"malformed indentation\".\n> \n> Hence, I think it would read better if we write:\n> \n> \tres = error(_(\"malformed identity line '%s'\"), author);\n> \n> 3 more characters is not that much :)\n\nLooking through the existing strings \"invalid ident line: %.*s\" is \nalready used by am so maybe we should reuse that (log.c also contains \n\"invalid ident line: %s\"). Is the translation correct?\n\n#: builtin/am.c:1270\n#, c-format\nmsgid \"invalid ident line: %.*s\"\nmsgstr \"dòng thụt lề không hợp lệ: %.*s\"\n\nBest Wishes\n\nPhillip\n\n> \n>> +\t\t\tgoto out;\n>> +\t\t}\n>> +\t\tif (!ident.date_begin) {\n>> +\t\t\tres = error(_(\"corrupted author without date information\"));\n>> +\t\t\tgoto out;\n>> +\t\t}\n>> +\n>> +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n>> +\t\t\t    (int)(ident.date_end - ident.date_begin),\n>> +\t\t\t    ident.date_begin,\n>> +\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n>> +\t\t\t    ident.tz_begin);\n>> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n>> +\t\tstrbuf_release(&date);\n>> +\n>> +\t\tif (res)\n>> +\t\t\tgoto out;\n>> +\t}\n>> +\n>>   \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>>   \t\tres = error(_(\"git write-tree failed to write a tree\"));\n>>   \t\tgoto out;\n>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>>   \t\t\topts->signoff = 1;\n>>   \t\t}\n>>   \n>> +\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n>> +\t\t\topts->allow_ff = 0;\n>> +\t\t\topts->committer_date_is_author_date = 1;\n>> +\t\t}\n>> +\n>>   \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n>>   \t\t\topts->reschedule_failed_exec = 1;\n>>   \n>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>>   \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>>   \tif (opts->keep_redundant_commits)\n>>   \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n>> +\tif (opts->committer_date_is_author_date)\n>> +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>>   \tif (opts->reschedule_failed_exec)\n>>   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>>   \n>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n>>   \t\t\tgoto leave_merge;\n>>   \t\t}\n>>   \n>> +\t\tif (opts->committer_date_is_author_date)\n>> +\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>> +\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n>> +\n>>   \t\tcmd.git_cmd = 1;\n>>   \t\targv_array_push(&cmd.args, \"merge\");\n>>   \t\targv_array_push(&cmd.args, \"-s\");\n>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n>>   \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>>   \tif (opts->allow_ff)\n>>   \t\tassert(!(opts->signoff || opts->no_commit ||\n>> -\t\t\t\topts->record_origin || opts->edit));\n>> +\t\t\t\topts->record_origin || opts->edit ||\n>> +\t\t\t\topts->committer_date_is_author_date));\n>>   \tif (read_and_refresh_cache(r, opts))\n>>   \t\treturn -1;\n>>   \n>> diff --git a/sequencer.h b/sequencer.h\n>> index 0bee85093e..4ab94119ae 100644\n>> --- a/sequencer.h\n>> +++ b/sequencer.h\n>> @@ -45,6 +45,7 @@ struct replay_opts {\n>>   \tint verbose;\n>>   \tint quiet;\n>>   \tint reschedule_failed_exec;\n>> +\tint committer_date_is_author_date;\n>>   \n>>   \tint mainline;\n>>   \n>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>> index 55ca46786d..c8234062c6 100755\n>> --- a/t/t3422-rebase-incompatible-options.sh\n>> +++ b/t/t3422-rebase-incompatible-options.sh\n>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>   }\n>>   \n>>   test_rebase_am_only --whitespace=fix\n>> -test_rebase_am_only --committer-date-is-author-date\n>>   test_rebase_am_only -C4\n>>   \n>>   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>> index 4f8a6e51c9..50a63d8ebe 100755\n>> --- a/t/t3436-rebase-more-options.sh\n>> +++ b/t/t3436-rebase-more-options.sh\n>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>>   \n>>   . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>>   \n>> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n>> +export GIT_AUTHOR_DATE\n>> +\n>>   # This is a special case in which both am and interactive backends\n>>   # provide the same output. It was done intentionally because\n>>   # both the backends fall short of optimal behaviour.\n>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n>>   \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>>   \tgit commit -am \"update file\" &&\n>>   \tgit tag side &&\n>> +\ttest_commit commit1 foo foo1 &&\n>> +\ttest_commit commit2 foo foo2 &&\n>> +\ttest_commit commit3 foo foo3 &&\n>>   \n>>   \tgit checkout --orphan master &&\n>> +\trm foo &&\n>>   \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n>>   \tgit commit -am \"add file\" &&\n>> -\tgit tag main\n>> +\tgit tag main &&\n>> +\n>> +\tmkdir test-bin &&\n>> +\twrite_script test-bin/git-merge-test <<-\\EOF\n>> +\texec git-merge-recursive \"$@\"\n>> +\tEOF\n>>   '\n>>   \n>>   test_expect_success '--ignore-whitespace works with apply backend' '\n>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n>>   \tgit diff --exit-code side\n>>   '\n>>   \n>> +test_ctime_is_atime () {\n>> +\tgit log $1 --format=%ai >authortime &&\n>> +\tgit log $1 --format=%ci >committertime &&\n>> +\ttest_cmp authortime committertime\n>> +}\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with apply backend' '\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>> +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n>> +\ttest_ctime_is_atime -1\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with merge backend' '\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>> +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n>> +\ttest_ctime_is_atime -1\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>> +\tgit checkout side &&\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>> +\tgit rebase -r --root --committer-date-is-author-date &&\n>> +\ttest_ctime_is_atime\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n>> +\tgit checkout side &&\n>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>> +\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n>> +\t\t\t\t\t--committer-date-is-author-date &&\n>> +\ttest_ctime_is_atime\n>> +'\n>> +\n>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n>> +\tgit checkout commit2 &&\n>> +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n>> +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n>> +\t\t--onto HEAD^^ HEAD^ &&\n>> +\techo resolved > foo &&\n> \n> Nitpick: no space after \">\" :D\n> \n"},{"id":"401634","messageId":"20200716130603.GB7803@danh.dev","threadId":"53176","inReplyTo":"281d92d3-f901-bca1-6030-fd0c8761f214@gmail.com","subject":"Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-07-16T13:06:03Z","receivedAt":"2020-07-16T13:06:10Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"Hi Phillip,\n\nOn 2020-07-16 09:23:17+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> >> [...]\n> > > +\tif (opts->committer_date_is_author_date) {\n> > > +\t\tstruct ident_split ident;\n> > > +\t\tstruct strbuf date = STRBUF_INIT;\n> > > +\n> > > +\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n> > > +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n> > \n> > I've checked with the translation for my native language (vi).\n> > The translators seem to misread ident (as in identity) as\n> > indent (as in indentation).\n> > \n> > The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:\n> > \n> > \t#~ msgid \"malformed ident line\"\n> > \t#~ msgstr \"thụt đầu dòng dị hình\"\n> > \n> > Translating back to English, it reads: \"malformed indentation\".\n> > \n> > Hence, I think it would read better if we write:\n> > \n> > \tres = error(_(\"malformed identity line '%s'\"), author);\n> > \n> > 3 more characters is not that much :)\n> \n> Looking through the existing strings \"invalid ident line: %.*s\" is already\n> used by am so maybe we should reuse that (log.c also contains \"invalid ident\n> line: %s\"). Is the translation correct?\n> \n> #: builtin/am.c:1270\n> #, c-format\n> msgid \"invalid ident line: %.*s\"\n> msgstr \"dòng thụt lề không hợp lệ: %.*s\"\n\nThat translation isn't correct either.\nIt seems like it's recurring pattern.\nI'll take it to the Vietnamese translation team.\n\nAnyway, I've checked with other translation that I can understand\nin part. I think\n\n\tinvalid ident line: %s\n\nis better candidate for the message.\nSince Spanish translation also mis-translates the message:\n\n\tes.po:9836:msgid \"invalid ident line: %.*s\"\n\tes.po-9837-msgstr \"sangría no válida: %.*s\"\n\n\"sangría\" also means \"indentation\" in this context.\n\nThanks,\n-Danh\n\n> \n> Best Wishes\n> \n> Phillip\n> \n> > \n> > > +\t\t\tgoto out;\n> > > +\t\t}\n> > > +\t\tif (!ident.date_begin) {\n> > > +\t\t\tres = error(_(\"corrupted author without date information\"));\n> > > +\t\t\tgoto out;\n> > > +\t\t}\n> > > +\n> > > +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n> > > +\t\t\t    (int)(ident.date_end - ident.date_begin),\n> > > +\t\t\t    ident.date_begin,\n> > > +\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n> > > +\t\t\t    ident.tz_begin);\n> > > +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> > > +\t\tstrbuf_release(&date);\n> > > +\n> > > +\t\tif (res)\n> > > +\t\t\tgoto out;\n> > > +\t}\n> > > +\n> > >   \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n> > >   \t\tres = error(_(\"git write-tree failed to write a tree\"));\n> > >   \t\tgoto out;\n> > > @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n> > >   \t\t\topts->signoff = 1;\n> > >   \t\t}\n> > > +\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n> > > +\t\t\topts->allow_ff = 0;\n> > > +\t\t\topts->committer_date_is_author_date = 1;\n> > > +\t\t}\n> > > +\n> > >   \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n> > >   \t\t\topts->reschedule_failed_exec = 1;\n> > > @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n> > >   \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n> > >   \tif (opts->keep_redundant_commits)\n> > >   \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n> > > +\tif (opts->committer_date_is_author_date)\n> > > +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n> > >   \tif (opts->reschedule_failed_exec)\n> > >   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n> > > @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n> > >   \t\t\tgoto leave_merge;\n> > >   \t\t}\n> > > +\t\tif (opts->committer_date_is_author_date)\n> > > +\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> > > +\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> > > +\n> > >   \t\tcmd.git_cmd = 1;\n> > >   \t\targv_array_push(&cmd.args, \"merge\");\n> > >   \t\targv_array_push(&cmd.args, \"-s\");\n> > > @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n> > >   \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n> > >   \tif (opts->allow_ff)\n> > >   \t\tassert(!(opts->signoff || opts->no_commit ||\n> > > -\t\t\t\topts->record_origin || opts->edit));\n> > > +\t\t\t\topts->record_origin || opts->edit ||\n> > > +\t\t\t\topts->committer_date_is_author_date));\n> > >   \tif (read_and_refresh_cache(r, opts))\n> > >   \t\treturn -1;\n> > > diff --git a/sequencer.h b/sequencer.h\n> > > index 0bee85093e..4ab94119ae 100644\n> > > --- a/sequencer.h\n> > > +++ b/sequencer.h\n> > > @@ -45,6 +45,7 @@ struct replay_opts {\n> > >   \tint verbose;\n> > >   \tint quiet;\n> > >   \tint reschedule_failed_exec;\n> > > +\tint committer_date_is_author_date;\n> > >   \tint mainline;\n> > > diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> > > index 55ca46786d..c8234062c6 100755\n> > > --- a/t/t3422-rebase-incompatible-options.sh\n> > > +++ b/t/t3422-rebase-incompatible-options.sh\n> > > @@ -61,7 +61,6 @@ test_rebase_am_only () {\n> > >   }\n> > >   test_rebase_am_only --whitespace=fix\n> > > -test_rebase_am_only --committer-date-is-author-date\n> > >   test_rebase_am_only -C4\n> > >   test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n> > > diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> > > index 4f8a6e51c9..50a63d8ebe 100755\n> > > --- a/t/t3436-rebase-more-options.sh\n> > > +++ b/t/t3436-rebase-more-options.sh\n> > > @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n> > >   . \"$TEST_DIRECTORY\"/lib-rebase.sh\n> > > +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> > > +export GIT_AUTHOR_DATE\n> > > +\n> > >   # This is a special case in which both am and interactive backends\n> > >   # provide the same output. It was done intentionally because\n> > >   # both the backends fall short of optimal behaviour.\n> > > @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n> > >   \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n> > >   \tgit commit -am \"update file\" &&\n> > >   \tgit tag side &&\n> > > +\ttest_commit commit1 foo foo1 &&\n> > > +\ttest_commit commit2 foo foo2 &&\n> > > +\ttest_commit commit3 foo foo3 &&\n> > >   \tgit checkout --orphan master &&\n> > > +\trm foo &&\n> > >   \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n> > >   \tgit commit -am \"add file\" &&\n> > > -\tgit tag main\n> > > +\tgit tag main &&\n> > > +\n> > > +\tmkdir test-bin &&\n> > > +\twrite_script test-bin/git-merge-test <<-\\EOF\n> > > +\texec git-merge-recursive \"$@\"\n> > > +\tEOF\n> > >   '\n> > >   test_expect_success '--ignore-whitespace works with apply backend' '\n> > > @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n> > >   \tgit diff --exit-code side\n> > >   '\n> > > +test_ctime_is_atime () {\n> > > +\tgit log $1 --format=%ai >authortime &&\n> > > +\tgit log $1 --format=%ci >committertime &&\n> > > +\ttest_cmp authortime committertime\n> > > +}\n> > > +\n> > > +test_expect_success '--committer-date-is-author-date works with apply backend' '\n> > > +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> > > +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n> > > +\ttest_ctime_is_atime -1\n> > > +'\n> > > +\n> > > +test_expect_success '--committer-date-is-author-date works with merge backend' '\n> > > +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> > > +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n> > > +\ttest_ctime_is_atime -1\n> > > +'\n> > > +\n> > > +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n> > > +\tgit checkout side &&\n> > > +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> > > +\tgit rebase -r --root --committer-date-is-author-date &&\n> > > +\ttest_ctime_is_atime\n> > > +'\n> > > +\n> > > +test_expect_success '--committer-date-is-author-date works when forking merge' '\n> > > +\tgit checkout side &&\n> > > +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> > > +\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n> > > +\t\t\t\t\t--committer-date-is-author-date &&\n> > > +\ttest_ctime_is_atime\n> > > +'\n> > > +\n> > > +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n> > > +\tgit checkout commit2 &&\n> > > +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n> > > +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n> > > +\t\t--onto HEAD^^ HEAD^ &&\n> > > +\techo resolved > foo &&\n> > \n> > Nitpick: no space after \">\" :D\n> > \n\n-- \nDanh\n"},{"id":"401636","messageId":"6f818af7-78b9-d6c8-c0fe-bcb84a4ef8ff@gmail.com","threadId":"53176","inReplyTo":"20200716130603.GB7803@danh.dev","subject":"Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T15:17:57Z","receivedAt":"2020-07-16T15:18:04Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Danh\n\nOn 16/07/2020 14:06, Đoàn Trần Công Danh wrote:\n> Hi Phillip,\n> \n> On 2020-07-16 09:23:17+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>>> [...]\n>>>> +\tif (opts->committer_date_is_author_date) {\n>>>> +\t\tstruct ident_split ident;\n>>>> +\t\tstruct strbuf date = STRBUF_INIT;\n>>>> +\n>>>> +\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n>>>> +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n>>>\n>>> I've checked with the translation for my native language (vi).\n>>> The translators seem to misread ident (as in identity) as\n>>> indent (as in indentation).\n>>>\n>>> The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:\n>>>\n>>> \t#~ msgid \"malformed ident line\"\n>>> \t#~ msgstr \"thụt đầu dòng dị hình\"\n>>>\n>>> Translating back to English, it reads: \"malformed indentation\".\n>>>\n>>> Hence, I think it would read better if we write:\n>>>\n>>> \tres = error(_(\"malformed identity line '%s'\"), author);\n>>>\n>>> 3 more characters is not that much :)\n>>\n>> Looking through the existing strings \"invalid ident line: %.*s\" is already\n>> used by am so maybe we should reuse that (log.c also contains \"invalid ident\n>> line: %s\"). Is the translation correct?\n>>\n>> #: builtin/am.c:1270\n>> #, c-format\n>> msgid \"invalid ident line: %.*s\"\n>> msgstr \"dòng thụt lề không hợp lệ: %.*s\"\n> \n> That translation isn't correct either.\n> It seems like it's recurring pattern.\n> I'll take it to the Vietnamese translation team.\n> \n> Anyway, I've checked with other translation that I can understand\n> in part. I think\n> \n> \tinvalid ident line: %s\n> \n> is better candidate for the message.\n\nYes I realized after sending my email that the string we're printing is \nNUL terminated so we don't need to specify the length with '*'. I think \nthe best thing would be to change the message in this patch to 'invalid \nident line: %s' and then have a follow up after this is merged to change \nall the \"invalid ident line\" messages to use \"identity\" instead. Would \nyou be interested in taking on the follow up patch?\n\nBest Wishes\n\nPhillip\n\n> Since Spanish translation also mis-translates the message:\n> \n> \tes.po:9836:msgid \"invalid ident line: %.*s\"\n> \tes.po-9837-msgstr \"sangría no válida: %.*s\"\n> \n> \"sangría\" also means \"indentation\" in this context.\n> \n> Thanks,\n> -Danh\n> \n>>\n>> Best Wishes\n>>\n>> Phillip\n>>\n>>>\n>>>> +\t\t\tgoto out;\n>>>> +\t\t}\n>>>> +\t\tif (!ident.date_begin) {\n>>>> +\t\t\tres = error(_(\"corrupted author without date information\"));\n>>>> +\t\t\tgoto out;\n>>>> +\t\t}\n>>>> +\n>>>> +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n>>>> +\t\t\t    (int)(ident.date_end - ident.date_begin),\n>>>> +\t\t\t    ident.date_begin,\n>>>> +\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n>>>> +\t\t\t    ident.tz_begin);\n>>>> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n>>>> +\t\tstrbuf_release(&date);\n>>>> +\n>>>> +\t\tif (res)\n>>>> +\t\t\tgoto out;\n>>>> +\t}\n>>>> +\n>>>>    \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>>>>    \t\tres = error(_(\"git write-tree failed to write a tree\"));\n>>>>    \t\tgoto out;\n>>>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>>>>    \t\t\topts->signoff = 1;\n>>>>    \t\t}\n>>>> +\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n>>>> +\t\t\topts->allow_ff = 0;\n>>>> +\t\t\topts->committer_date_is_author_date = 1;\n>>>> +\t\t}\n>>>> +\n>>>>    \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n>>>>    \t\t\topts->reschedule_failed_exec = 1;\n>>>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>>>>    \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>>>>    \tif (opts->keep_redundant_commits)\n>>>>    \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n>>>> +\tif (opts->committer_date_is_author_date)\n>>>> +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>>>>    \tif (opts->reschedule_failed_exec)\n>>>>    \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>>>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n>>>>    \t\t\tgoto leave_merge;\n>>>>    \t\t}\n>>>> +\t\tif (opts->committer_date_is_author_date)\n>>>> +\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>>>> +\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n>>>> +\n>>>>    \t\tcmd.git_cmd = 1;\n>>>>    \t\targv_array_push(&cmd.args, \"merge\");\n>>>>    \t\targv_array_push(&cmd.args, \"-s\");\n>>>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n>>>>    \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>>>>    \tif (opts->allow_ff)\n>>>>    \t\tassert(!(opts->signoff || opts->no_commit ||\n>>>> -\t\t\t\topts->record_origin || opts->edit));\n>>>> +\t\t\t\topts->record_origin || opts->edit ||\n>>>> +\t\t\t\topts->committer_date_is_author_date));\n>>>>    \tif (read_and_refresh_cache(r, opts))\n>>>>    \t\treturn -1;\n>>>> diff --git a/sequencer.h b/sequencer.h\n>>>> index 0bee85093e..4ab94119ae 100644\n>>>> --- a/sequencer.h\n>>>> +++ b/sequencer.h\n>>>> @@ -45,6 +45,7 @@ struct replay_opts {\n>>>>    \tint verbose;\n>>>>    \tint quiet;\n>>>>    \tint reschedule_failed_exec;\n>>>> +\tint committer_date_is_author_date;\n>>>>    \tint mainline;\n>>>> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>>>> index 55ca46786d..c8234062c6 100755\n>>>> --- a/t/t3422-rebase-incompatible-options.sh\n>>>> +++ b/t/t3422-rebase-incompatible-options.sh\n>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>>>    }\n>>>>    test_rebase_am_only --whitespace=fix\n>>>> -test_rebase_am_only --committer-date-is-author-date\n>>>>    test_rebase_am_only -C4\n>>>>    test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n>>>> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n>>>> index 4f8a6e51c9..50a63d8ebe 100755\n>>>> --- a/t/t3436-rebase-more-options.sh\n>>>> +++ b/t/t3436-rebase-more-options.sh\n>>>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>>>>    . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>>>> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n>>>> +export GIT_AUTHOR_DATE\n>>>> +\n>>>>    # This is a special case in which both am and interactive backends\n>>>>    # provide the same output. It was done intentionally because\n>>>>    # both the backends fall short of optimal behaviour.\n>>>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n>>>>    \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>>>>    \tgit commit -am \"update file\" &&\n>>>>    \tgit tag side &&\n>>>> +\ttest_commit commit1 foo foo1 &&\n>>>> +\ttest_commit commit2 foo foo2 &&\n>>>> +\ttest_commit commit3 foo foo3 &&\n>>>>    \tgit checkout --orphan master &&\n>>>> +\trm foo &&\n>>>>    \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n>>>>    \tgit commit -am \"add file\" &&\n>>>> -\tgit tag main\n>>>> +\tgit tag main &&\n>>>> +\n>>>> +\tmkdir test-bin &&\n>>>> +\twrite_script test-bin/git-merge-test <<-\\EOF\n>>>> +\texec git-merge-recursive \"$@\"\n>>>> +\tEOF\n>>>>    '\n>>>>    test_expect_success '--ignore-whitespace works with apply backend' '\n>>>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n>>>>    \tgit diff --exit-code side\n>>>>    '\n>>>> +test_ctime_is_atime () {\n>>>> +\tgit log $1 --format=%ai >authortime &&\n>>>> +\tgit log $1 --format=%ci >committertime &&\n>>>> +\ttest_cmp authortime committertime\n>>>> +}\n>>>> +\n>>>> +test_expect_success '--committer-date-is-author-date works with apply backend' '\n>>>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>>>> +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n>>>> +\ttest_ctime_is_atime -1\n>>>> +'\n>>>> +\n>>>> +test_expect_success '--committer-date-is-author-date works with merge backend' '\n>>>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n>>>> +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n>>>> +\ttest_ctime_is_atime -1\n>>>> +'\n>>>> +\n>>>> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>>>> +\tgit checkout side &&\n>>>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>>>> +\tgit rebase -r --root --committer-date-is-author-date &&\n>>>> +\ttest_ctime_is_atime\n>>>> +'\n>>>> +\n>>>> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n>>>> +\tgit checkout side &&\n>>>> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>>>> +\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n>>>> +\t\t\t\t\t--committer-date-is-author-date &&\n>>>> +\ttest_ctime_is_atime\n>>>> +'\n>>>> +\n>>>> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n>>>> +\tgit checkout commit2 &&\n>>>> +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n>>>> +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n>>>> +\t\t--onto HEAD^^ HEAD^ &&\n>>>> +\techo resolved > foo &&\n>>>\n>>> Nitpick: no space after \">\" :D\n>>>\n> \n"},{"id":"401648","messageId":"20200716173221.103295-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH v7 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T17:32:16Z","receivedAt":"2020-07-16T17:32:31Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nDanh pointed out that the word \"ident\" gets misinterpreted by\ntranslators as \"indentation\" leading to incorrect translations so I've\nreworded an error message.\n\nformat-patch and am could do with having their similar messages\nupdated in the future\n\nPhillip Wood (2):\n  rebase -i: support --committer-date-is-author-date\n  rebase -i: support --ignore-date\n\nRohit Ashiwal (3):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: rename amend_author to author_to_free\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt           |  33 ++++-\n builtin/rebase.c                       |  47 +++++--\n sequencer.c                            | 112 ++++++++++++++-\n sequencer.h                            |   2 +\n t/t3422-rebase-incompatible-options.sh |   2 -\n t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++\n 6 files changed, 353 insertions(+), 23 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\nRange-diff against v6:\n1:  0fc90eaff1 ! 1:  3865fdf461 rebase -i: support --ignore-date\n    @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr\n     +\tstruct strbuf new_author = STRBUF_INIT;\n     +\n     +\tif (split_ident_line(&ident, author, strlen(author)) < 0) {\n    -+\t\terror(_(\"malformed ident line '%s'\"), author);\n    ++\t\terror(_(\"invalid author identity: %s\"), author);\n     +\t\treturn NULL;\n     +\t}\n     +\n2:  21cf5e5512 = 2:  0b6b19cb68 rebase: add --reset-author-date\n-- \n2.27.0\n\n"},{"id":"401649","messageId":"20200716173221.103295-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200716173221.103295-1-phillip.wood123@gmail.com","subject":"[PATCH v7 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T17:32:17Z","receivedAt":"2020-07-16T17:32:34Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--ignore-whitespace option to the merge backend. This option treats\nlines with only whitespace changes as unchanged and is implemented in\nthe merge backend by translating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 19 +++++++-\n builtin/rebase.c                       | 19 ++++++--\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++\n 4 files changed, 93 insertions(+), 6 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f7a6033607..b003784f01 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tIgnore whitespace differences when trying to reconcile\n+differences. Currently, each backend implements an approximation of\n+this behavior:\n++\n+apply backend: When applying a patch, ignore changes in whitespace in\n+context lines. Unfortunately, this means that if the \"old\" lines being\n+replaced by the patch differ only in whitespace from the existing\n+file, you will get a merge conflict instead of a successful patch\n+application.\n++\n+merge backend: Treat lines with only whitespace changes as unchanged\n+when merging. Unfortunately, this means that any patch hunks that were\n+intended to modify whitespace and nothing else will be dropped, even\n+if the other side had no changes that conflicted.\n+\n --whitespace=<option>::\n-\tThese flags are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n \tImplies --apply.\n +\n@@ -572,7 +587,6 @@ The following options:\n  * --apply\n  * --committer-date-is-author-date\n  * --ignore-date\n- * --ignore-whitespace\n  * --whitespace\n  * -C\n \n@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n+ * --preserve-merges and --ignore-whitespace\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 27a07d4e78..bd93e9742c 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n \n@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tstruct strbuf revisions = STRBUF_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct object_id merge_base;\n+\tint ignore_whitespace = 0;\n \tenum action action = ACTION_NONE;\n \tconst char *gpg_sign = NULL;\n \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\timply_merge(&options, \"--rebase-merges\");\n \t}\n \n+\tif (options.type == REBASE_APPLY) {\n+\t\tif (ignore_whitespace)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--ignore-whitespace\");\n+\t} else {\n+\t\t/* REBASE_MERGE and PRESERVE_MERGES */\n+\t\tif (ignore_whitespace) {\n+\t\t\tstring_list_append(&strategy_options,\n+\t\t\t\t\t   \"ignore-space-change\");\n+\t\t}\n+\t}\n+\n \tif (strategy_options.nr) {\n \t\tint i;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..55ca46786d 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nnew file mode 100755\nindex 0000000000..4f8a6e51c9\n--- /dev/null\n+++ b/t/t3436-rebase-more-options.sh\n@@ -0,0 +1,60 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\n+\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\n+\tgit checkout --orphan master &&\n+\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n+\tgit commit -am \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with apply backend' '\n+\ttest_must_fail git rebase --apply main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --apply --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace works with merge backend' '\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n+\t\t\tmain side &&\n+\t\tgit rebase --continue\n+\t) &&\n+\tgit diff --exit-code side\n+'\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n+test_done\n-- \n2.27.0\n\n"},{"id":"401650","messageId":"20200716173221.103295-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200716173221.103295-1-phillip.wood123@gmail.com","subject":"[PATCH v7 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T17:32:18Z","receivedAt":"2020-07-16T17:32:35Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--committer-date-is-author-date option to the merge backend. This\noption uses the author date of the commit that is being rewritten as\nthe committer date when the new commit is created.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 10 +++--\n builtin/rebase.c                       | 17 +++++---\n sequencer.c                            | 60 +++++++++++++++++++++++++-\n sequencer.h                            |  1 +\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++++++++++-\n 6 files changed, 136 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex b003784f01..dfa70263e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of using the current time as the committer date, use\n+\tthe author date of the commit being rebased as the committer\n+\tdate. This option implies --force-rebase.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tThis flag is passed to 'git am' to change the author date\n+\tof each rebased commit (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex bd93e9742c..2579380729 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -88,6 +88,7 @@ struct rebase_options {\n \tint autosquash;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n+\tif (options.committer_date_is_author_date)\n+\t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n+\t\tif (!strcmp(option, \"--ignore-date\") ||\n \t\t    !strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (ignore_whitespace)\n \t\t\targv_array_push(&options.git_am_opts,\n \t\t\t\t\t\"--ignore-whitespace\");\n+\t\tif (options.committer_date_is_author_date)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--committer-date-is-author-date\");\n \t} else {\n \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n \t\tif (ignore_whitespace) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 6fd2674632..368d397970 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -872,6 +873,22 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+static const char *author_date_from_env_array(const struct argv_array *env)\n+{\n+\tint i;\n+\tconst char *date;\n+\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -938,6 +955,10 @@ static int run_git_commit(struct repository *r,\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n \n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \targv_array_push(&cmd.args, \"commit\");\n \n \tif (!(flags & VERIFY_MSG))\n@@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,\n \t\tcommit_list_insert(current_head, &parents);\n \t}\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tstruct ident_split ident;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n+\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!ident.date_begin) {\n+\t\t\tres = error(_(\"corrupted author without date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(ident.date_end - ident.date_begin),\n+\t\t\t    ident.date_begin,\n+\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n+\t\t\t    ident.tz_begin);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&date);\n+\n+\t\tif (res)\n+\t\t\tgoto out;\n+\t}\n+\n \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n \t\tres = error(_(\"git write-tree failed to write a tree\"));\n \t\tgoto out;\n@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n \tif (opts->keep_redundant_commits)\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n \t\t\tgoto leave_merge;\n \t\t}\n \n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n \t\targv_array_push(&cmd.args, \"-s\");\n@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t\topts->record_origin || opts->edit ||\n+\t\t\t\topts->committer_date_is_author_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 0bee85093e..4ab94119ae 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -45,6 +45,7 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n \n \tint mainline;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 55ca46786d..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 4f8a6e51c9..50a63d8ebe 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n # This is a special case in which both am and interactive backends\n # provide the same output. It was done intentionally because\n # both the backends fall short of optimal behaviour.\n@@ -21,11 +24,20 @@ test_expect_success 'setup' '\n \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n \tgit commit -am \"update file\" &&\n \tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n \n \tgit checkout --orphan master &&\n+\trm foo &&\n \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n \tgit commit -am \"add file\" &&\n-\tgit tag main\n+\tgit tag main &&\n+\n+\tmkdir test-bin &&\n+\twrite_script test-bin/git-merge-test <<-\\EOF\n+\texec git-merge-recursive \"$@\"\n+\tEOF\n '\n \n test_expect_success '--ignore-whitespace works with apply backend' '\n@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n \tgit diff --exit-code side\n '\n \n+test_ctime_is_atime () {\n+\tgit log $1 --format=%ai >authortime &&\n+\tgit log $1 --format=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+}\n+\n+test_expect_success '--committer-date-is-author-date works with apply backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with merge backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n+\t\t\t\t\t--committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -1\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"401651","messageId":"20200716173221.103295-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200716173221.103295-1-phillip.wood123@gmail.com","subject":"[PATCH v7 3/5] sequencer: rename amend_author to author_to_free","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T17:32:19Z","receivedAt":"2020-07-16T17:32:38Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() when amending a commit. But we can\nalso use the variable to free() the author at our convenience.\nRename it to convey this meaning.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 368d397970..29f6d1bc39 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1335,7 +1335,7 @@ static int try_to_commit(struct repository *r,\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n-\tchar *amend_author = NULL;\n+\tchar *author_to_free = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n@@ -1357,7 +1357,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tstrbuf_addstr(msg, orig_message);\n \t\t\thook_commit = \"HEAD\";\n \t\t}\n-\t\tauthor = amend_author = get_author(message);\n+\t\tauthor = author_to_free = get_author(message);\n \t\tunuse_commit_buffer(current_head, message);\n \t\tif (!author) {\n \t\t\tres = error(_(\"unable to parse commit author\"));\n@@ -1474,7 +1474,7 @@ static int try_to_commit(struct repository *r,\n \tfree_commit_extra_headers(extra);\n \tstrbuf_release(&err);\n \tstrbuf_release(&commit_msg);\n-\tfree(amend_author);\n+\tfree(author_to_free);\n \n \treturn res;\n }\n-- \n2.27.0\n\n"},{"id":"401652","messageId":"20200716173221.103295-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200716173221.103295-1-phillip.wood123@gmail.com","subject":"[PATCH v7 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T17:32:21Z","receivedAt":"2020-07-16T17:32:40Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe previous commit introduced --ignore-date flag to rebase -i, but the\nname is rather vague as it does not say whether the author date or the\ncommitter date is ignored. Add an alias to convey the precise purpose.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt   |  1 +\n builtin/rebase.c               |  4 +++-\n t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------\n 3 files changed, 25 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e2717e20e6..a5f82913fb 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the author date of the original commit, use\n \tthe current time as the\tauthor date of the rebased commit.  This\n \toption implies `--force-rebase`.\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 583ac96fc7..b126fbe940 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n \t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 0ede2b8900..5b8963272a 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -117,53 +117,61 @@ test_ctime_is_ignored () {\n \t! grep -v +0000 authortime\n }\n \n-test_expect_success '--ignore-date works with apply backend' '\n+test_expect_success '--reset-author-date works with apply backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit rebase --apply --reset-author-date HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with merge backend' '\n+test_expect_success '--reset-author-date works with merge backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit rebase --reset-author-date -m HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works after conflict resolution' '\n-\ttest_must_fail git rebase --ignore-date -m \\\n+test_expect_success '--reset-author-date works after conflict resolution' '\n+\ttest_must_fail git rebase --reset-author-date -m \\\n \t\t--onto commit2^^ commit2^ commit2 &&\n \techo resolved >foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with rebase -r' '\n+test_expect_success '--reset-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n-\tgit rebase -r --root --ignore-date &&\n+\tgit rebase -r --root --reset-author-date &&\n \ttest_ctime_is_ignored\n '\n \n-test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '\n \ttest_must_fail git rebase -m --committer-date-is-author-date \\\n-\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\t\t--reset-author-date --onto commit2^^ commit2^ commit3 &&\n \tgit checkout --theirs foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_atime -2 &&\n \ttest_ctime_is_ignored -2\n '\n \n-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n \t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n-\t\t\t\t--ignore-date --committer-date-is-author-date \\\n-\t\t\t\tside side &&\n+\t\t\t\t--reset-author-date \\\n+\t\t\t\t--committer-date-is-author-date side side &&\n \ttest_ctime_is_atime -1 &&\n \ttest_ctime_is_ignored -1\n  '\n \n+test_expect_success '--ignore-date is an alias for --reset-author-date' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase -m --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"401653","messageId":"20200716173221.103295-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200716173221.103295-1-phillip.wood123@gmail.com","subject":"[PATCH v7 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T17:32:20Z","receivedAt":"2020-07-16T17:32:40Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the --ignore-date\noption to the merge backend. This option uses the current time as the\nauthor date rather than reusing the original author date when\nrewriting commits. We take care to handle the combination of\n--ignore-date and --committer-date-is-author-date in the same way as\nthe apply backend.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt   |  7 +++--\n builtin/rebase.c               | 13 +++++---\n sequencer.c                    | 50 ++++++++++++++++++++++++++++--\n sequencer.h                    |  1 +\n t/t3436-rebase-more-options.sh | 56 ++++++++++++++++++++++++++++++++++\n 5 files changed, 117 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex dfa70263e6..e2717e20e6 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof each rebased commit (see linkgit:git-am[1]).\n+\tInstead of using the author date of the original commit, use\n+\tthe current time as the\tauthor date of the rebased commit.  This\n+\toption implies `--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n  * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 2579380729..583ac96fc7 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -89,6 +89,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.committer_date_is_author_date =\n \t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n-\tif (options.committer_date_is_author_date)\n+\tif (options.committer_date_is_author_date || options.ignore_date)\n \t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\n@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (options.committer_date_is_author_date)\n \t\t\targv_array_push(&options.git_am_opts,\n \t\t\t\t\t\"--committer-date-is-author-date\");\n+\t\tif (options.ignore_date)\n+\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n \t} else {\n \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n \t\tif (ignore_whitespace) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 29f6d1bc39..878fafdc41 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -889,6 +890,24 @@ static const char *author_date_from_env_array(const struct argv_array *env)\n \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n }\n \n+/* Construct a free()able author string with current time as the author date */\n+static char *ignore_author_date(const char *author)\n+{\n+\tint len;\n+\tstruct ident_split ident;\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\n+\tif (split_ident_line(&ident, author, strlen(author)) < 0) {\n+\t\terror(_(\"invalid author identity: %s\"), author);\n+\t\treturn NULL;\n+\t}\n+\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n \n \tif (opts->committer_date_is_author_date)\n \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n \t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,\n \t\t\t    ident.date_begin,\n \t\t\t    (int)(ident.tz_end - ident.tz_begin),\n \t\t\t    ident.tz_begin);\n-\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n \t\tstrbuf_release(&date);\n \n \t\tif (res)\n@@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tauthor = ignore_author_date(author);\n+\t\tif (!author) {\n+\t\t\tres = -1;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tfree(author_to_free);\n+\t\tauthor_to_free = (char *)author;\n+\t}\n+\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->committer_date_is_author_date = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n \tif (opts->committer_date_is_author_date)\n \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,\n \n \t\tif (opts->committer_date_is_author_date)\n \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n \t\t\t\topts->record_origin || opts->edit ||\n-\t\t\t\topts->committer_date_is_author_date));\n+\t\t\t\topts->committer_date_is_author_date ||\n+\t\t\t\topts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 4ab94119ae..3587878e3b 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -46,6 +46,7 @@ struct replay_opts {\n \tint quiet;\n \tint reschedule_failed_exec;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 50a63d8ebe..0ede2b8900 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n \ttest_ctime_is_atime -1\n '\n \n+# Checking for +0000 in the author date is sufficient since the\n+# default timezone is UTC but the timezone used while committing is\n+# +0530. The inverted logic in the grep is necessary to check all the\n+# author dates in the file.\n+test_ctime_is_ignored () {\n+\tgit log $1 --format=%ai >authortime &&\n+\t! grep -v +0000 authortime\n+}\n+\n+test_expect_success '--ignore-date works with apply backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with merge backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -m HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -m \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\ttest_ctime_is_ignored\n+'\n+\n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -2 &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n+\t\t\t\t--ignore-date --committer-date-is-author-date \\\n+\t\t\t\tside side &&\n+\ttest_ctime_is_atime -1 &&\n+\ttest_ctime_is_ignored -1\n+ '\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.27.0\n\n"},{"id":"401654","messageId":"640a3f1b-4e00-4b8a-9a9f-207ea76c648a@gmail.com","threadId":"53176","inReplyTo":"6f818af7-78b9-d6c8-c0fe-bcb84a4ef8ff@gmail.com","subject":"Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-07-16T17:34:51Z","receivedAt":"2020-07-16T17:34:57Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 16/07/2020 16:17, Phillip Wood wrote:\n> Hi Danh\n> \n> On 16/07/2020 14:06, Đoàn Trần Công Danh wrote:\n>> Hi Phillip,\n>>\n>> On 2020-07-16 09:23:17+0100, Phillip Wood <phillip.wood123@gmail.com>\n>> wrote:\n>>>>> [...]\n>>>>> +    if (opts->committer_date_is_author_date) {\n>>>>> +        struct ident_split ident;\n>>>>> +        struct strbuf date = STRBUF_INIT;\n>>>>> +\n>>>>> +        if (split_ident_line(&ident, author, (int)strlen(author))\n>>>>> < 0) {\n>>>>> +            res = error(_(\"malformed ident line '%s'\"), author);\n>>>>\n>>>> I've checked with the translation for my native language (vi).\n>>>> The translators seem to misread ident (as in identity) as\n>>>> indent (as in indentation).\n>>>>\n>>>> The translation in po/vi.po:25045 (of v2.28.0-rc0) reads:\n>>>>\n>>>>     #~ msgid \"malformed ident line\"\n>>>>     #~ msgstr \"thụt đầu dòng dị hình\"\n>>>>\n>>>> Translating back to English, it reads: \"malformed indentation\".\n>>>>\n>>>> Hence, I think it would read better if we write:\n>>>>\n>>>>     res = error(_(\"malformed identity line '%s'\"), author);\n>>>>\n>>>> 3 more characters is not that much :)\n>>>\n>>> Looking through the existing strings \"invalid ident line: %.*s\" is\n>>> already\n>>> used by am so maybe we should reuse that (log.c also contains\n>>> \"invalid ident\n>>> line: %s\"). Is the translation correct?\n>>>\n>>> #: builtin/am.c:1270\n>>> #, c-format\n>>> msgid \"invalid ident line: %.*s\"\n>>> msgstr \"dòng thụt lề không hợp lệ: %.*s\"\n>>\n>> That translation isn't correct either.\n>> It seems like it's recurring pattern.\n>> I'll take it to the Vietnamese translation team.\n>>\n>> Anyway, I've checked with other translation that I can understand\n>> in part. I think\n>>\n>>     invalid ident line: %s\n>>\n>> is better candidate for the message.\n> \n> Yes I realized after sending my email that the string we're printing is\n> NUL terminated so we don't need to specify the length with '*'. I think\n> the best thing would be to change the message in this patch to 'invalid\n> ident line: %s' and then have a follow up after this is merged to change\n> all the \"invalid ident line\" messages to use \"identity\" instead. Would\n> you be interested in taking on the follow up patch?\n\nIn the end I decided it was better just to change the message in this\npatch to something more descriptive. We can update the other commands\nseparately. For format-patch we should probably update the option\ndescription for `--from` as well as the error message.\n\nBest Wishes\n\nPhillip\n\n> \n> Best Wishes\n> \n> Phillip\n> \n>> Since Spanish translation also mis-translates the message:\n>>\n>>     es.po:9836:msgid \"invalid ident line: %.*s\"\n>>     es.po-9837-msgstr \"sangría no válida: %.*s\"\n>>\n>> \"sangría\" also means \"indentation\" in this context.\n>>\n>> Thanks,\n>> -Danh\n>>\n>>>\n>>> Best Wishes\n>>>\n>>> Phillip\n>>>\n>>>>\n>>>>> +            goto out;\n>>>>> +        }\n>>>>> +        if (!ident.date_begin) {\n>>>>> +            res = error(_(\"corrupted author without date\n>>>>> information\"));\n>>>>> +            goto out;\n>>>>> +        }\n>>>>> +\n>>>>> +        strbuf_addf(&date, \"@%.*s %.*s\",\n>>>>> +                (int)(ident.date_end - ident.date_begin),\n>>>>> +                ident.date_begin,\n>>>>> +                (int)(ident.tz_end - ident.tz_begin),\n>>>>> +                ident.tz_begin);\n>>>>> +        res = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n>>>>> +        strbuf_release(&date);\n>>>>> +\n>>>>> +        if (res)\n>>>>> +            goto out;\n>>>>> +    }\n>>>>> +\n>>>>>        if (write_index_as_tree(&tree, r->index, r->index_file, 0,\n>>>>> NULL)) {\n>>>>>            res = error(_(\"git write-tree failed to write a tree\"));\n>>>>>            goto out;\n>>>>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct\n>>>>> replay_opts *opts)\n>>>>>                opts->signoff = 1;\n>>>>>            }\n>>>>> +        if (file_exists(rebase_path_cdate_is_adate())) {\n>>>>> +            opts->allow_ff = 0;\n>>>>> +            opts->committer_date_is_author_date = 1;\n>>>>> +        }\n>>>>> +\n>>>>>            if (file_exists(rebase_path_reschedule_failed_exec()))\n>>>>>                opts->reschedule_failed_exec = 1;\n>>>>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts\n>>>>> *opts, const char *head_name,\n>>>>>            write_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>>>>>        if (opts->keep_redundant_commits)\n>>>>>            write_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n>>>>> +    if (opts->committer_date_is_author_date)\n>>>>> +        write_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>>>>>        if (opts->reschedule_failed_exec)\n>>>>>            write_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>>>>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n>>>>>                goto leave_merge;\n>>>>>            }\n>>>>> +        if (opts->committer_date_is_author_date)\n>>>>> +            argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n>>>>> +                     author_date_from_env_array(&cmd.env_array));\n>>>>> +\n>>>>>            cmd.git_cmd = 1;\n>>>>>            argv_array_push(&cmd.args, \"merge\");\n>>>>>            argv_array_push(&cmd.args, \"-s\");\n>>>>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n>>>>>        setenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>>>>>        if (opts->allow_ff)\n>>>>>            assert(!(opts->signoff || opts->no_commit ||\n>>>>> -                opts->record_origin || opts->edit));\n>>>>> +                opts->record_origin || opts->edit ||\n>>>>> +                opts->committer_date_is_author_date));\n>>>>>        if (read_and_refresh_cache(r, opts))\n>>>>>            return -1;\n>>>>> diff --git a/sequencer.h b/sequencer.h\n>>>>> index 0bee85093e..4ab94119ae 100644\n>>>>> --- a/sequencer.h\n>>>>> +++ b/sequencer.h\n>>>>> @@ -45,6 +45,7 @@ struct replay_opts {\n>>>>>        int verbose;\n>>>>>        int quiet;\n>>>>>        int reschedule_failed_exec;\n>>>>> +    int committer_date_is_author_date;\n>>>>>        int mainline;\n>>>>> diff --git a/t/t3422-rebase-incompatible-options.sh\n>>>>> b/t/t3422-rebase-incompatible-options.sh\n>>>>> index 55ca46786d..c8234062c6 100755\n>>>>> --- a/t/t3422-rebase-incompatible-options.sh\n>>>>> +++ b/t/t3422-rebase-incompatible-options.sh\n>>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>>>>>    }\n>>>>>    test_rebase_am_only --whitespace=fix\n>>>>> -test_rebase_am_only --committer-date-is-author-date\n>>>>>    test_rebase_am_only -C4\n>>>>>    test_expect_success REBASE_P '--preserve-merges incompatible\n>>>>> with --signoff' '\n>>>>> diff --git a/t/t3436-rebase-more-options.sh\n>>>>> b/t/t3436-rebase-more-options.sh\n>>>>> index 4f8a6e51c9..50a63d8ebe 100755\n>>>>> --- a/t/t3436-rebase-more-options.sh\n>>>>> +++ b/t/t3436-rebase-more-options.sh\n>>>>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility\n>>>>> between am and interactive backe\n>>>>>    . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>>>>> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n>>>>> +export GIT_AUTHOR_DATE\n>>>>> +\n>>>>>    # This is a special case in which both am and interactive backends\n>>>>>    # provide the same output. It was done intentionally because\n>>>>>    # both the backends fall short of optimal behaviour.\n>>>>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n>>>>>        test_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>>>>>        git commit -am \"update file\" &&\n>>>>>        git tag side &&\n>>>>> +    test_commit commit1 foo foo1 &&\n>>>>> +    test_commit commit2 foo foo2 &&\n>>>>> +    test_commit commit3 foo foo3 &&\n>>>>>        git checkout --orphan master &&\n>>>>> +    rm foo &&\n>>>>>        test_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n>>>>>        git commit -am \"add file\" &&\n>>>>> -    git tag main\n>>>>> +    git tag main &&\n>>>>> +\n>>>>> +    mkdir test-bin &&\n>>>>> +    write_script test-bin/git-merge-test <<-\\EOF\n>>>>> +    exec git-merge-recursive \"$@\"\n>>>>> +    EOF\n>>>>>    '\n>>>>>    test_expect_success '--ignore-whitespace works with apply\n>>>>> backend' '\n>>>>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is\n>>>>> remembered when continuing' '\n>>>>>        git diff --exit-code side\n>>>>>    '\n>>>>> +test_ctime_is_atime () {\n>>>>> +    git log $1 --format=%ai >authortime &&\n>>>>> +    git log $1 --format=%ci >committertime &&\n>>>>> +    test_cmp authortime committertime\n>>>>> +}\n>>>>> +\n>>>>> +test_expect_success '--committer-date-is-author-date works with\n>>>>> apply backend' '\n>>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend\n>>>>> --reset-author &&\n>>>>> +    git rebase --apply --committer-date-is-author-date HEAD^ &&\n>>>>> +    test_ctime_is_atime -1\n>>>>> +'\n>>>>> +\n>>>>> +test_expect_success '--committer-date-is-author-date works with\n>>>>> merge backend' '\n>>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend\n>>>>> --reset-author &&\n>>>>> +    git rebase -m --committer-date-is-author-date HEAD^ &&\n>>>>> +    test_ctime_is_atime -1\n>>>>> +'\n>>>>> +\n>>>>> +test_expect_success '--committer-date-is-author-date works with\n>>>>> rebase -r' '\n>>>>> +    git checkout side &&\n>>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>>>>> +    git rebase -r --root --committer-date-is-author-date &&\n>>>>> +    test_ctime_is_atime\n>>>>> +'\n>>>>> +\n>>>>> +test_expect_success '--committer-date-is-author-date works when\n>>>>> forking merge' '\n>>>>> +    git checkout side &&\n>>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n>>>>> +    PATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n>>>>> +                    --committer-date-is-author-date &&\n>>>>> +    test_ctime_is_atime\n>>>>> +'\n>>>>> +\n>>>>> +test_expect_success '--committer-date-is-author-date works when\n>>>>> committing conflict resolution' '\n>>>>> +    git checkout commit2 &&\n>>>>> +    GIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only\n>>>>> --reset-author &&\n>>>>> +    test_must_fail git rebase -m --committer-date-is-author-date \\\n>>>>> +        --onto HEAD^^ HEAD^ &&\n>>>>> +    echo resolved > foo &&\n>>>>\n>>>> Nitpick: no space after \">\" :D\n>>>>\n>>\n\n"},{"id":"401656","messageId":"xmqqft9rgy0v.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200716173221.103295-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-07-16T17:39:12Z","receivedAt":"2020-07-16T17:39:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> format-patch and am could do with having their similar messages\n> updated in the future\n\nThat's a good #leftoverbits topic.\n"},{"id":"401673","messageId":"20200717002500.GA20467@danh.dev","threadId":"53176","inReplyTo":"640a3f1b-4e00-4b8a-9a9f-207ea76c648a@gmail.com","subject":"Re: [PATCH v6 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2020-07-17T00:25:00Z","receivedAt":"2020-07-17T00:25:06Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"On 2020-07-16 18:34:51+0100, Phillip Wood <phillip.wood123@gmail.com> wrote:\n> >> That translation isn't correct either.\n> >> It seems like it's recurring pattern.\n> >> I'll take it to the Vietnamese translation team.\n> >>\n> >> Anyway, I've checked with other translation that I can understand\n> >> in part. I think\n> >>\n> >>     invalid ident line: %s\n> >>\n> >> is better candidate for the message.\n> > \n> > Yes I realized after sending my email that the string we're printing is\n> > NUL terminated so we don't need to specify the length with '*'. I think\n> > the best thing would be to change the message in this patch to 'invalid\n> > ident line: %s' and then have a follow up after this is merged to change\n> > all the \"invalid ident line\" messages to use \"identity\" instead. Would\n> > you be interested in taking on the follow up patch?\n> \n> In the end I decided it was better just to change the message in this\n> patch to something more descriptive. We can update the other commands\n> separately. For format-patch we should probably update the option\n> description for `--from` as well as the error message.\n\nYes, I also think we should leave the other messages there for now.\nWhen this topic get merged, we will come back to see which one should\nbe updated/changed.\n\nAll other parts look sane to me.\n\nI don't mind get my hand wet if noone steps in.\n\nThanks,\nDanh\n\n> \n> Best Wishes\n> \n> Phillip\n> \n> > \n> > Best Wishes\n> > \n> > Phillip\n> > \n> >> Since Spanish translation also mis-translates the message:\n> >>\n> >>     es.po:9836:msgid \"invalid ident line: %.*s\"\n> >>     es.po-9837-msgstr \"sangría no válida: %.*s\"\n> >>\n> >> \"sangría\" also means \"indentation\" in this context.\n> >>\n> >> Thanks,\n> >> -Danh\n> >>\n> >>>\n> >>> Best Wishes\n> >>>\n> >>> Phillip\n> >>>\n> >>>>\n> >>>>> +            goto out;\n> >>>>> +        }\n> >>>>> +        if (!ident.date_begin) {\n> >>>>> +            res = error(_(\"corrupted author without date\n> >>>>> information\"));\n> >>>>> +            goto out;\n> >>>>> +        }\n> >>>>> +\n> >>>>> +        strbuf_addf(&date, \"@%.*s %.*s\",\n> >>>>> +                (int)(ident.date_end - ident.date_begin),\n> >>>>> +                ident.date_begin,\n> >>>>> +                (int)(ident.tz_end - ident.tz_begin),\n> >>>>> +                ident.tz_begin);\n> >>>>> +        res = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> >>>>> +        strbuf_release(&date);\n> >>>>> +\n> >>>>> +        if (res)\n> >>>>> +            goto out;\n> >>>>> +    }\n> >>>>> +\n> >>>>>        if (write_index_as_tree(&tree, r->index, r->index_file, 0,\n> >>>>> NULL)) {\n> >>>>>            res = error(_(\"git write-tree failed to write a tree\"));\n> >>>>>            goto out;\n> >>>>> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct\n> >>>>> replay_opts *opts)\n> >>>>>                opts->signoff = 1;\n> >>>>>            }\n> >>>>> +        if (file_exists(rebase_path_cdate_is_adate())) {\n> >>>>> +            opts->allow_ff = 0;\n> >>>>> +            opts->committer_date_is_author_date = 1;\n> >>>>> +        }\n> >>>>> +\n> >>>>>            if (file_exists(rebase_path_reschedule_failed_exec()))\n> >>>>>                opts->reschedule_failed_exec = 1;\n> >>>>> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts\n> >>>>> *opts, const char *head_name,\n> >>>>>            write_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n> >>>>>        if (opts->keep_redundant_commits)\n> >>>>>            write_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n> >>>>> +    if (opts->committer_date_is_author_date)\n> >>>>> +        write_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n> >>>>>        if (opts->reschedule_failed_exec)\n> >>>>>            write_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n> >>>>> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n> >>>>>                goto leave_merge;\n> >>>>>            }\n> >>>>> +        if (opts->committer_date_is_author_date)\n> >>>>> +            argv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> >>>>> +                     author_date_from_env_array(&cmd.env_array));\n> >>>>> +\n> >>>>>            cmd.git_cmd = 1;\n> >>>>>            argv_array_push(&cmd.args, \"merge\");\n> >>>>>            argv_array_push(&cmd.args, \"-s\");\n> >>>>> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n> >>>>>        setenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n> >>>>>        if (opts->allow_ff)\n> >>>>>            assert(!(opts->signoff || opts->no_commit ||\n> >>>>> -                opts->record_origin || opts->edit));\n> >>>>> +                opts->record_origin || opts->edit ||\n> >>>>> +                opts->committer_date_is_author_date));\n> >>>>>        if (read_and_refresh_cache(r, opts))\n> >>>>>            return -1;\n> >>>>> diff --git a/sequencer.h b/sequencer.h\n> >>>>> index 0bee85093e..4ab94119ae 100644\n> >>>>> --- a/sequencer.h\n> >>>>> +++ b/sequencer.h\n> >>>>> @@ -45,6 +45,7 @@ struct replay_opts {\n> >>>>>        int verbose;\n> >>>>>        int quiet;\n> >>>>>        int reschedule_failed_exec;\n> >>>>> +    int committer_date_is_author_date;\n> >>>>>        int mainline;\n> >>>>> diff --git a/t/t3422-rebase-incompatible-options.sh\n> >>>>> b/t/t3422-rebase-incompatible-options.sh\n> >>>>> index 55ca46786d..c8234062c6 100755\n> >>>>> --- a/t/t3422-rebase-incompatible-options.sh\n> >>>>> +++ b/t/t3422-rebase-incompatible-options.sh\n> >>>>> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n> >>>>>    }\n> >>>>>    test_rebase_am_only --whitespace=fix\n> >>>>> -test_rebase_am_only --committer-date-is-author-date\n> >>>>>    test_rebase_am_only -C4\n> >>>>>    test_expect_success REBASE_P '--preserve-merges incompatible\n> >>>>> with --signoff' '\n> >>>>> diff --git a/t/t3436-rebase-more-options.sh\n> >>>>> b/t/t3436-rebase-more-options.sh\n> >>>>> index 4f8a6e51c9..50a63d8ebe 100755\n> >>>>> --- a/t/t3436-rebase-more-options.sh\n> >>>>> +++ b/t/t3436-rebase-more-options.sh\n> >>>>> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility\n> >>>>> between am and interactive backe\n> >>>>>    . \"$TEST_DIRECTORY\"/lib-rebase.sh\n> >>>>> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> >>>>> +export GIT_AUTHOR_DATE\n> >>>>> +\n> >>>>>    # This is a special case in which both am and interactive backends\n> >>>>>    # provide the same output. It was done intentionally because\n> >>>>>    # both the backends fall short of optimal behaviour.\n> >>>>> @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n> >>>>>        test_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n> >>>>>        git commit -am \"update file\" &&\n> >>>>>        git tag side &&\n> >>>>> +    test_commit commit1 foo foo1 &&\n> >>>>> +    test_commit commit2 foo foo2 &&\n> >>>>> +    test_commit commit3 foo foo3 &&\n> >>>>>        git checkout --orphan master &&\n> >>>>> +    rm foo &&\n> >>>>>        test_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n> >>>>>        git commit -am \"add file\" &&\n> >>>>> -    git tag main\n> >>>>> +    git tag main &&\n> >>>>> +\n> >>>>> +    mkdir test-bin &&\n> >>>>> +    write_script test-bin/git-merge-test <<-\\EOF\n> >>>>> +    exec git-merge-recursive \"$@\"\n> >>>>> +    EOF\n> >>>>>    '\n> >>>>>    test_expect_success '--ignore-whitespace works with apply\n> >>>>> backend' '\n> >>>>> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is\n> >>>>> remembered when continuing' '\n> >>>>>        git diff --exit-code side\n> >>>>>    '\n> >>>>> +test_ctime_is_atime () {\n> >>>>> +    git log $1 --format=%ai >authortime &&\n> >>>>> +    git log $1 --format=%ci >committertime &&\n> >>>>> +    test_cmp authortime committertime\n> >>>>> +}\n> >>>>> +\n> >>>>> +test_expect_success '--committer-date-is-author-date works with\n> >>>>> apply backend' '\n> >>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend\n> >>>>> --reset-author &&\n> >>>>> +    git rebase --apply --committer-date-is-author-date HEAD^ &&\n> >>>>> +    test_ctime_is_atime -1\n> >>>>> +'\n> >>>>> +\n> >>>>> +test_expect_success '--committer-date-is-author-date works with\n> >>>>> merge backend' '\n> >>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend\n> >>>>> --reset-author &&\n> >>>>> +    git rebase -m --committer-date-is-author-date HEAD^ &&\n> >>>>> +    test_ctime_is_atime -1\n> >>>>> +'\n> >>>>> +\n> >>>>> +test_expect_success '--committer-date-is-author-date works with\n> >>>>> rebase -r' '\n> >>>>> +    git checkout side &&\n> >>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> >>>>> +    git rebase -r --root --committer-date-is-author-date &&\n> >>>>> +    test_ctime_is_atime\n> >>>>> +'\n> >>>>> +\n> >>>>> +test_expect_success '--committer-date-is-author-date works when\n> >>>>> forking merge' '\n> >>>>> +    git checkout side &&\n> >>>>> +    GIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> >>>>> +    PATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n> >>>>> +                    --committer-date-is-author-date &&\n> >>>>> +    test_ctime_is_atime\n> >>>>> +'\n> >>>>> +\n> >>>>> +test_expect_success '--committer-date-is-author-date works when\n> >>>>> committing conflict resolution' '\n> >>>>> +    git checkout commit2 &&\n> >>>>> +    GIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only\n> >>>>> --reset-author &&\n> >>>>> +    test_must_fail git rebase -m --committer-date-is-author-date \\\n> >>>>> +        --onto HEAD^^ HEAD^ &&\n> >>>>> +    echo resolved > foo &&\n> >>>>\n> >>>> Nitpick: no space after \">\" :D\n> >>>>\n> >>\n> \n\n-- \nDanh\n"},{"id":"403542","messageId":"nycvar.QRO.7.76.6.2008131535370.54@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"20200716173221.103295-3-phillip.wood123@gmail.com","subject":"Re: [PATCH v7 2/5] rebase -i: support --committer-date-is-author-date","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-08-13T13:46:45Z","receivedAt":"2020-08-13T13:47:01Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Thu, 16 Jul 2020, Phillip Wood wrote:\n\n> @@ -1349,6 +1370,31 @@ static int try_to_commit(struct repository *r,\n>  \t\tcommit_list_insert(current_head, &parents);\n>  \t}\n>\n> +\tif (opts->committer_date_is_author_date) {\n> +\t\tstruct ident_split ident;\n> +\t\tstruct strbuf date = STRBUF_INIT;\n> +\n> +\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n> +\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n> +\t\t\tgoto out;\n> +\t\t}\n> +\t\tif (!ident.date_begin) {\n> +\t\t\tres = error(_(\"corrupted author without date information\"));\n> +\t\t\tgoto out;\n> +\t\t}\n> +\n> +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n> +\t\t\t    (int)(ident.date_end - ident.date_begin),\n> +\t\t\t    ident.date_begin,\n> +\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n> +\t\t\t    ident.tz_begin);\n> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n\nI am slightly worried that we do not unset this environment variable (or\nrevert to its previous value, if it had any).\n\nI had a brief look and it seems that there are only two callers of\n`commit_tree_extended()` (which uses `git_committer_info(IDENT_STRICT)` to\nfill in the committer date), so it _should_ be possible to extend the\nsignature of `commit_tree_extended()` to specify the committer information\nexplicitly.\n\nThe bigger question is whether we _actually_ need this, and I _think_ that\nthe answer is \"not right now\", so I would be fine with the patch as-is.\nJust thought that I point it out (and thereby demonstrate that I actually\nlooked at the patch ;-)).\n\nCiao,\nDscho\n\n> +\t\tstrbuf_release(&date);\n> +\n> +\t\tif (res)\n> +\t\t\tgoto out;\n> +\t}\n> +\n>  \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n>  \t\tres = error(_(\"git write-tree failed to write a tree\"));\n>  \t\tgoto out;\n> @@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>  \t\t\topts->signoff = 1;\n>  \t\t}\n>\n> +\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n> +\t\t\topts->allow_ff = 0;\n> +\t\t\topts->committer_date_is_author_date = 1;\n> +\t\t}\n> +\n>  \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n>  \t\t\topts->reschedule_failed_exec = 1;\n>\n> @@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>  \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n>  \tif (opts->keep_redundant_commits)\n>  \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n> +\tif (opts->committer_date_is_author_date)\n> +\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n>  \tif (opts->reschedule_failed_exec)\n>  \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>\n> @@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n>  \t\t\tgoto leave_merge;\n>  \t\t}\n>\n> +\t\tif (opts->committer_date_is_author_date)\n> +\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\n>  \t\tcmd.git_cmd = 1;\n>  \t\targv_array_push(&cmd.args, \"merge\");\n>  \t\targv_array_push(&cmd.args, \"-s\");\n> @@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n>  \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n>  \tif (opts->allow_ff)\n>  \t\tassert(!(opts->signoff || opts->no_commit ||\n> -\t\t\t\topts->record_origin || opts->edit));\n> +\t\t\t\topts->record_origin || opts->edit ||\n> +\t\t\t\topts->committer_date_is_author_date));\n>  \tif (read_and_refresh_cache(r, opts))\n>  \t\treturn -1;\n>\n> diff --git a/sequencer.h b/sequencer.h\n> index 0bee85093e..4ab94119ae 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -45,6 +45,7 @@ struct replay_opts {\n>  \tint verbose;\n>  \tint quiet;\n>  \tint reschedule_failed_exec;\n> +\tint committer_date_is_author_date;\n>\n>  \tint mainline;\n>\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index 55ca46786d..c8234062c6 100755\n> --- a/t/t3422-rebase-incompatible-options.sh\n> +++ b/t/t3422-rebase-incompatible-options.sh\n> @@ -61,7 +61,6 @@ test_rebase_am_only () {\n>  }\n>\n>  test_rebase_am_only --whitespace=fix\n> -test_rebase_am_only --committer-date-is-author-date\n>  test_rebase_am_only -C4\n>\n>  test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 4f8a6e51c9..50a63d8ebe 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>\n>  . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>\n> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> +export GIT_AUTHOR_DATE\n> +\n>  # This is a special case in which both am and interactive backends\n>  # provide the same output. It was done intentionally because\n>  # both the backends fall short of optimal behaviour.\n> @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n>  \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>  \tgit commit -am \"update file\" &&\n>  \tgit tag side &&\n> +\ttest_commit commit1 foo foo1 &&\n> +\ttest_commit commit2 foo foo2 &&\n> +\ttest_commit commit3 foo foo3 &&\n>\n>  \tgit checkout --orphan master &&\n> +\trm foo &&\n>  \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n>  \tgit commit -am \"add file\" &&\n> -\tgit tag main\n> +\tgit tag main &&\n> +\n> +\tmkdir test-bin &&\n> +\twrite_script test-bin/git-merge-test <<-\\EOF\n> +\texec git-merge-recursive \"$@\"\n> +\tEOF\n>  '\n>\n>  test_expect_success '--ignore-whitespace works with apply backend' '\n> @@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n>  \tgit diff --exit-code side\n>  '\n>\n> +test_ctime_is_atime () {\n> +\tgit log $1 --format=%ai >authortime &&\n> +\tgit log $1 --format=%ci >committertime &&\n> +\ttest_cmp authortime committertime\n> +}\n> +\n> +test_expect_success '--committer-date-is-author-date works with apply backend' '\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n> +\ttest_ctime_is_atime -1\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with merge backend' '\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n> +\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n> +\ttest_ctime_is_atime -1\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n> +\tgit checkout side &&\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +\tgit rebase -r --root --committer-date-is-author-date &&\n> +\ttest_ctime_is_atime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when forking merge' '\n> +\tgit checkout side &&\n> +\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n> +\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n> +\t\t\t\t\t--committer-date-is-author-date &&\n> +\ttest_ctime_is_atime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n> +\tgit checkout commit2 &&\n> +\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n> +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n> +\t\t--onto HEAD^^ HEAD^ &&\n> +\techo resolved > foo &&\n> +\tgit add foo &&\n> +\tgit rebase --continue &&\n> +\ttest_ctime_is_atime -1\n> +'\n> +\n>  # This must be the last test in this file\n>  test_expect_success '$EDITOR and friends are unchanged' '\n>  \ttest_editor_unchanged\n> --\n> 2.27.0\n>\n>\n"},{"id":"403544","messageId":"nycvar.QRO.7.76.6.2008131554180.54@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"20200716173221.103295-5-phillip.wood123@gmail.com","subject":"Re: [PATCH v7 4/5] rebase -i: support --ignore-date","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-08-13T14:07:41Z","receivedAt":"2020-08-13T14:07:54Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Thu, 16 Jul 2020, Phillip Wood wrote:\n\n> @@ -957,7 +976,11 @@ static int run_git_commit(struct repository *r,\n>\n>  \tif (opts->committer_date_is_author_date)\n>  \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t opts->ignore_date ?\n> +\t\t\t\t \"\" :\n>  \t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\tif (opts->ignore_date)\n> +\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n\nTechnically, if we switched those two `if` blocks, we would not have to\nedit the committer date one. But this way is much clearer.\n\n>\n>  \targv_array_push(&cmd.args, \"commit\");\n>\n> @@ -1388,7 +1411,8 @@ static int try_to_commit(struct repository *r,\n>  \t\t\t    ident.date_begin,\n>  \t\t\t    (int)(ident.tz_end - ident.tz_begin),\n>  \t\t\t    ident.tz_begin);\n> -\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n> +\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n\nIsn't this constructing the `date` string for nothing, if\n`opts->ignore_date` is set?\n\nI would much rather see it done this way:\n\n-\tif (opts->committer_date_is_author_date) {\n+\tif (opts->committer_date_is_author_date && opts->ignore_date)\n+\t\tsetenv(\"GIT_COMMITTER_DATE\", \"\", 1);\n+\telse if (opts->committer_date_is_author_date) {\n\nNot enough of a reason to re-roll, though.\n\n>  \t\tstrbuf_release(&date);\n>\n>  \t\tif (res)\n> @@ -1454,6 +1478,16 @@ static int try_to_commit(struct repository *r,\n>\n>  \treset_ident_date();\n>\n> +\tif (opts->ignore_date) {\n> +\t\tauthor = ignore_author_date(author);\n> +\t\tif (!author) {\n> +\t\t\tres = -1;\n> +\t\t\tgoto out;\n> +\t\t}\n> +\t\tfree(author_to_free);\n\nA better cadence might be to first `free(author_to_free)`, then assign\n`author = author_to_free = ignore_author_date(author);` (at least in my\nperspective, it reads more naturally).\n\nBut again, not a big reason for a re-roll.\n\nThe rest of the patch looks good to me.\n\nThank you,\nDscho\n\n> +\t\tauthor_to_free = (char *)author;\n\n> +\t}\n> +\n>  \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n>  \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n>  \t\tres = error(_(\"failed to write commit object\"));\n> @@ -2583,6 +2617,11 @@ static int read_populate_opts(struct replay_opts *opts)\n>  \t\t\topts->committer_date_is_author_date = 1;\n>  \t\t}\n>\n> +\t\tif (file_exists(rebase_path_ignore_date())) {\n> +\t\t\topts->allow_ff = 0;\n> +\t\t\topts->ignore_date = 1;\n> +\t\t}\n> +\n>  \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n>  \t\t\topts->reschedule_failed_exec = 1;\n>\n> @@ -2675,6 +2714,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n>  \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n>  \tif (opts->committer_date_is_author_date)\n>  \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n> +\tif (opts->ignore_date)\n> +\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n>  \tif (opts->reschedule_failed_exec)\n>  \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>\n> @@ -3597,7 +3638,11 @@ static int do_merge(struct repository *r,\n>\n>  \t\tif (opts->committer_date_is_author_date)\n>  \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n> +\t\t\t\t\t opts->ignore_date ?\n> +\t\t\t\t\t \"\" :\n>  \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n> +\t\tif (opts->ignore_date)\n> +\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n>\n>  \t\tcmd.git_cmd = 1;\n>  \t\targv_array_push(&cmd.args, \"merge\");\n> @@ -3877,7 +3922,8 @@ static int pick_commits(struct repository *r,\n>  \tif (opts->allow_ff)\n>  \t\tassert(!(opts->signoff || opts->no_commit ||\n>  \t\t\t\topts->record_origin || opts->edit ||\n> -\t\t\t\topts->committer_date_is_author_date));\n> +\t\t\t\topts->committer_date_is_author_date ||\n> +\t\t\t\topts->ignore_date));\n>  \tif (read_and_refresh_cache(r, opts))\n>  \t\treturn -1;\n>\n> diff --git a/sequencer.h b/sequencer.h\n> index 4ab94119ae..3587878e3b 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -46,6 +46,7 @@ struct replay_opts {\n>  \tint quiet;\n>  \tint reschedule_failed_exec;\n>  \tint committer_date_is_author_date;\n> +\tint ignore_date;\n>\n>  \tint mainline;\n>\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 50a63d8ebe..0ede2b8900 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n>  \ttest_ctime_is_atime -1\n>  '\n>\n> +# Checking for +0000 in the author date is sufficient since the\n> +# default timezone is UTC but the timezone used while committing is\n> +# +0530. The inverted logic in the grep is necessary to check all the\n> +# author dates in the file.\n> +test_ctime_is_ignored () {\n> +\tgit log $1 --format=%ai >authortime &&\n> +\t! grep -v +0000 authortime\n> +}\n> +\n> +test_expect_success '--ignore-date works with apply backend' '\n> +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +\tgit rebase --apply --ignore-date HEAD^ &&\n> +\ttest_ctime_is_ignored -1\n> +'\n> +\n> +test_expect_success '--ignore-date works with merge backend' '\n> +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n> +\tgit rebase --ignore-date -m HEAD^ &&\n> +\ttest_ctime_is_ignored -1\n> +'\n> +\n> +test_expect_success '--ignore-date works after conflict resolution' '\n> +\ttest_must_fail git rebase --ignore-date -m \\\n> +\t\t--onto commit2^^ commit2^ commit2 &&\n> +\techo resolved >foo &&\n> +\tgit add foo &&\n> +\tgit rebase --continue &&\n> +\ttest_ctime_is_ignored -1\n> +'\n> +\n> +test_expect_success '--ignore-date works with rebase -r' '\n> +\tgit checkout side &&\n> +\tgit merge --no-ff commit3 &&\n> +\tgit rebase -r --root --ignore-date &&\n> +\ttest_ctime_is_ignored\n> +'\n> +\n> +test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n> +\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n> +\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n> +\tgit checkout --theirs foo &&\n> +\tgit add foo &&\n> +\tgit rebase --continue &&\n> +\ttest_ctime_is_atime -2 &&\n> +\ttest_ctime_is_ignored -2\n> +'\n> +\n> +test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n> +\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n> +\t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n> +\t\t\t\t--ignore-date --committer-date-is-author-date \\\n> +\t\t\t\tside side &&\n> +\ttest_ctime_is_atime -1 &&\n> +\ttest_ctime_is_ignored -1\n> + '\n> +\n>  # This must be the last test in this file\n>  test_expect_success '$EDITOR and friends are unchanged' '\n>  \ttest_editor_unchanged\n> --\n> 2.27.0\n>\n>\n"},{"id":"403545","messageId":"nycvar.QRO.7.76.6.2008131608240.54@tvgsbejvaqbjf.bet","threadId":"53176","inReplyTo":"20200716173221.103295-1-phillip.wood123@gmail.com","subject":"Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2020-08-13T14:24:45Z","receivedAt":"2020-08-13T14:25:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Phillip,\n\nOn Thu, 16 Jul 2020, Phillip Wood wrote:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> Danh pointed out that the word \"ident\" gets misinterpreted by\n> translators as \"indentation\" leading to incorrect translations so I've\n> reworded an error message.\n>\n> format-patch and am could do with having their similar messages\n> updated in the future\n\nThank you for this patch series!\n\nTo be honest, my hope was that I would get support for `git rebase -i\n--whitespace=fix` out of that GSoC project... but I take what I can get,\nand this patch series is in a pretty good shape.\n\nI offered three small suggestions how I think it could be improved, still,\nbut I would be pretty happy with seeing the patches moving to `next`\nas-are.\n\nThank you,\nDscho\n\n>\n> Phillip Wood (2):\n>   rebase -i: support --committer-date-is-author-date\n>   rebase -i: support --ignore-date\n>\n> Rohit Ashiwal (3):\n>   rebase -i: add --ignore-whitespace flag\n>   sequencer: rename amend_author to author_to_free\n>   rebase: add --reset-author-date\n>\n>  Documentation/git-rebase.txt           |  33 ++++-\n>  builtin/rebase.c                       |  47 +++++--\n>  sequencer.c                            | 112 ++++++++++++++-\n>  sequencer.h                            |   2 +\n>  t/t3422-rebase-incompatible-options.sh |   2 -\n>  t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++\n>  6 files changed, 353 insertions(+), 23 deletions(-)\n>  create mode 100755 t/t3436-rebase-more-options.sh\n>\n> Range-diff against v6:\n> 1:  0fc90eaff1 ! 1:  3865fdf461 rebase -i: support --ignore-date\n>     @@ sequencer.c: static const char *author_date_from_env_array(const struct argv_arr\n>      +\tstruct strbuf new_author = STRBUF_INIT;\n>      +\n>      +\tif (split_ident_line(&ident, author, strlen(author)) < 0) {\n>     -+\t\terror(_(\"malformed ident line '%s'\"), author);\n>     ++\t\terror(_(\"invalid author identity: %s\"), author);\n>      +\t\treturn NULL;\n>      +\t}\n>      +\n> 2:  21cf5e5512 = 2:  0b6b19cb68 rebase: add --reset-author-date\n> --\n> 2.27.0\n>\n>\n"},{"id":"403578","messageId":"xmqqzh6y30cf.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"nycvar.QRO.7.76.6.2008131608240.54@tvgsbejvaqbjf.bet","subject":"Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-08-13T17:46:40Z","receivedAt":"2020-08-13T17:46:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> I offered three small suggestions how I think it could be improved, still,\n> but I would be pretty happy with seeing the patches moving to `next`\n> as-are.\n\nI tend to agree with those points I saw you mentioned.\n\nThe unconditional exporting of the committer-date without undoing\nlooked like a bad pattern waiting to be copied and pasted.  I\nhave not yet fully followed the codepath but I tend to agree with\nyour suspicion that commit_tree_extended() might be a better place\nto do this.\n\nThanks.\n"},{"id":"403591","messageId":"7874298b-3c48-0849-2ee3-8912a410287d@gmail.com","threadId":"53176","inReplyTo":"xmqqzh6y30cf.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v7 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-13T19:51:50Z","receivedAt":"2020-08-13T19:51:55Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/08/2020 18:46, Junio C Hamano wrote:\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n>> I offered three small suggestions how I think it could be improved, still,\n>> but I would be pretty happy with seeing the patches moving to `next`\n>> as-are.\n> \n> I tend to agree with those points I saw you mentioned.\n> \n> The unconditional exporting of the committer-date without undoing\n> looked like a bad pattern waiting to be copied and pasted. \n\nI think it is copied and pasted from builtin/am.c\n\n> I have not yet fully followed the codepath but I tend to agree with\n> your suspicion that commit_tree_extended() might be a better place\n> to do this.\n\nIt looks like it should be simple enough to do that, I'll reroll\n\nThanks for your comments dscho\n\nPhillip\n\n> Thanks.\n> \n"},{"id":"403846","messageId":"20200817174004.92455-3-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200817174004.92455-1-phillip.wood123@gmail.com","subject":"[PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-17T17:40:01Z","receivedAt":"2020-08-17T17:40:43Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThe implementation of --committer-date-is-author-date exports\nGIT_COMMITTER_DATE to override the default committer date but does not\nreset GIT_COMMITTER_DATE in the environment after creating the commit\nso it is set in the environment of any hooks that get run. We're about\nto add the same functionality to the sequencer and do not want to have\nGIT_COMMITTER_DATE set when running hooks or exec commands so lets\nupdate commit_tree_extended() to take an explicit committer so we\noverride the default date without setting GIT_COMMITTER_DATE in the\nenvironment.\n\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n builtin/am.c     | 28 +++++++++++++++++++++++-----\n builtin/commit.c |  4 ++--\n commit.c         | 11 +++++++----\n commit.h         |  7 +++----\n ident.c          | 24 ++++++++++++++----------\n sequencer.c      |  4 ++--\n 6 files changed, 51 insertions(+), 27 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex e3dfd93c25..896cd0f827 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -98,6 +98,8 @@ struct am_state {\n \tchar *author_name;\n \tchar *author_email;\n \tchar *author_date;\n+\tchar *committer_name;\n+\tchar *committer_email;\n \tchar *msg;\n \tsize_t msg_len;\n \n@@ -130,6 +132,8 @@ struct am_state {\n  */\n static void am_state_init(struct am_state *state)\n {\n+\tconst char *committer;\n+\tstruct ident_split id;\n \tint gpgsign;\n \n \tmemset(state, 0, sizeof(*state));\n@@ -150,6 +154,14 @@ static void am_state_init(struct am_state *state)\n \n \tif (!git_config_get_bool(\"commit.gpgsign\", &gpgsign))\n \t\tstate->sign_commit = gpgsign ? \"\" : NULL;\n+\n+\tcommitter = git_committer_info(IDENT_STRICT);\n+\tif (split_ident_line(&id, committer, strlen(committer)) < 0)\n+\t\tdie(_(\"invalid committer: %s\"), committer);\n+\tstate->committer_name =\n+\t\txmemdupz(id.name_begin, id.name_end - id.name_begin);\n+\tstate->committer_email =\n+\t\txmemdupz(id.mail_begin, id.mail_end - id.mail_end);\n }\n \n /**\n@@ -161,6 +173,8 @@ static void am_state_release(struct am_state *state)\n \tfree(state->author_name);\n \tfree(state->author_email);\n \tfree(state->author_date);\n+\tfree(state->committer_name);\n+\tfree(state->committer_email);\n \tfree(state->msg);\n \targv_array_clear(&state->git_apply_opts);\n }\n@@ -1556,7 +1570,7 @@ static void do_commit(const struct am_state *state)\n \tstruct object_id tree, parent, commit;\n \tconst struct object_id *old_oid;\n \tstruct commit_list *parents = NULL;\n-\tconst char *reflog_msg, *author;\n+\tconst char *reflog_msg, *author, *committer = NULL;\n \tstruct strbuf sb = STRBUF_INIT;\n \n \tif (run_hook_le(NULL, \"pre-applypatch\", NULL))\n@@ -1580,11 +1594,15 @@ static void do_commit(const struct am_state *state)\n \t\t\tIDENT_STRICT);\n \n \tif (state->committer_date_is_author_date)\n-\t\tsetenv(\"GIT_COMMITTER_DATE\",\n-\t\t\tstate->ignore_date ? \"\" : state->author_date, 1);\n+\t\tcommitter = fmt_ident(state->committer_name,\n+\t\t\t\t      state->author_email, WANT_COMMITTER_IDENT,\n+\t\t\t\t      state->ignore_date ? NULL\n+\t\t\t\t\t\t\t : state->author_date,\n+\t\t\t\t      IDENT_STRICT);\n \n-\tif (commit_tree(state->msg, state->msg_len, &tree, parents, &commit,\n-\t\t\tauthor, state->sign_commit))\n+\tif (commit_tree_extended(state->msg, state->msg_len, &tree, parents,\n+\t\t\t\t &commit, author, committer, state->sign_commit,\n+\t\t\t\t NULL))\n \t\tdie(_(\"failed to write commit object\"));\n \n \treflog_msg = getenv(\"GIT_REFLOG_ACTION\");\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d3e7781e65..2785344fed 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1675,8 +1675,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (commit_tree_extended(sb.buf, sb.len, &active_cache_tree->oid,\n-\t\t\t\t parents, &oid, author_ident.buf, sign_commit,\n-\t\t\t\t extra)) {\n+\t\t\t\t parents, &oid, author_ident.buf, NULL,\n+\t\t\t\t sign_commit, extra)) {\n \t\trollback_index_files();\n \t\tdie(_(\"failed to write commit object\"));\n \t}\ndiff --git a/commit.c b/commit.c\nindex c7099daeac..fb63c22cc1 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1324,8 +1324,8 @@ int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,\n \tint result;\n \n \tappend_merge_tag_headers(parents, &tail);\n-\tresult = commit_tree_extended(msg, msg_len, tree, parents, ret,\n-\t\t\t\t      author, sign_commit, extra);\n+\tresult = commit_tree_extended(msg, msg_len, tree, parents, ret, author,\n+\t\t\t\t      NULL, sign_commit, extra);\n \tfree_commit_extra_headers(extra);\n \treturn result;\n }\n@@ -1448,7 +1448,8 @@ N_(\"Warning: commit message did not conform to UTF-8.\\n\"\n int commit_tree_extended(const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n \t\t\t struct commit_list *parents, struct object_id *ret,\n-\t\t\t const char *author, const char *sign_commit,\n+\t\t\t const char *author, const char *committer,\n+\t\t\t const char *sign_commit,\n \t\t\t struct commit_extra_header *extra)\n {\n \tint result;\n@@ -1481,7 +1482,9 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \tif (!author)\n \t\tauthor = git_author_info(IDENT_STRICT);\n \tstrbuf_addf(&buffer, \"author %s\\n\", author);\n-\tstrbuf_addf(&buffer, \"committer %s\\n\", git_committer_info(IDENT_STRICT));\n+\tif (!committer)\n+\t\tcommitter = git_committer_info(IDENT_STRICT);\n+\tstrbuf_addf(&buffer, \"committer %s\\n\", committer);\n \tif (!encoding_is_utf8)\n \t\tstrbuf_addf(&buffer, \"encoding %s\\n\", git_commit_encoding);\n \ndiff --git a/commit.h b/commit.h\nindex 008a0fa4a0..8f4227ae5c 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -316,10 +316,9 @@ int commit_tree(const char *msg, size_t msg_len,\n \n int commit_tree_extended(const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n-\t\t\t struct commit_list *parents,\n-\t\t\t struct object_id *ret, const char *author,\n-\t\t\t const char *sign_commit,\n-\t\t\t struct commit_extra_header *);\n+\t\t\t struct commit_list *parents, struct object_id *ret,\n+\t\t\t const char *author, const char *committer,\n+\t\t\t const char *sign_commit, struct commit_extra_header *);\n \n struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);\n \ndiff --git a/ident.c b/ident.c\nindex e666ee4e59..7cbf223350 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -361,11 +361,15 @@ N_(\"\\n\"\n const char *fmt_ident(const char *name, const char *email,\n \t\t      enum want_ident whose_ident, const char *date_str, int flag)\n {\n-\tstatic struct strbuf ident = STRBUF_INIT;\n+\tstatic int index;\n+\tstatic struct strbuf ident_pool[2] = { STRBUF_INIT, STRBUF_INIT };\n \tint strict = (flag & IDENT_STRICT);\n \tint want_date = !(flag & IDENT_NO_DATE);\n \tint want_name = !(flag & IDENT_NO_NAME);\n \n+\tstruct strbuf *ident = &ident_pool[index];\n+\tindex = (index + 1) % ARRAY_SIZE(ident_pool);\n+\n \tif (!email) {\n \t\tif (whose_ident == WANT_AUTHOR_IDENT && git_author_email.len)\n \t\t\temail = git_author_email.buf;\n@@ -421,25 +425,25 @@ const char *fmt_ident(const char *name, const char *email,\n \t\t\tdie(_(\"name consists only of disallowed characters: %s\"), name);\n \t}\n \n-\tstrbuf_reset(&ident);\n+\tstrbuf_reset(ident);\n \tif (want_name) {\n-\t\tstrbuf_addstr_without_crud(&ident, name);\n-\t\tstrbuf_addstr(&ident, \" <\");\n+\t\tstrbuf_addstr_without_crud(ident, name);\n+\t\tstrbuf_addstr(ident, \" <\");\n \t}\n-\tstrbuf_addstr_without_crud(&ident, email);\n+\tstrbuf_addstr_without_crud(ident, email);\n \tif (want_name)\n-\t\t\tstrbuf_addch(&ident, '>');\n+\t\tstrbuf_addch(ident, '>');\n \tif (want_date) {\n-\t\tstrbuf_addch(&ident, ' ');\n+\t\tstrbuf_addch(ident, ' ');\n \t\tif (date_str && date_str[0]) {\n-\t\t\tif (parse_date(date_str, &ident) < 0)\n+\t\t\tif (parse_date(date_str, ident) < 0)\n \t\t\t\tdie(_(\"invalid date format: %s\"), date_str);\n \t\t}\n \t\telse\n-\t\t\tstrbuf_addstr(&ident, ident_default_date());\n+\t\t\tstrbuf_addstr(ident, ident_default_date());\n \t}\n \n-\treturn ident.buf;\n+\treturn ident->buf;\n }\n \n const char *fmt_name(enum want_ident whose_ident)\ndiff --git a/sequencer.c b/sequencer.c\nindex 6fd2674632..968a2d4ef3 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1408,8 +1408,8 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n-\tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n-\t\t\t\t oid, author, opts->gpg_sign, extra)) {\n+\tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n+\t\t\t\t author, NULL, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n \t\tgoto out;\n \t}\n-- \n2.28.0\n\n"},{"id":"403847","messageId":"20200817174004.92455-5-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200817174004.92455-1-phillip.wood123@gmail.com","subject":"[PATCH v8 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-17T17:40:03Z","receivedAt":"2020-08-17T17:40:54Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the --ignore-date\noption to the merge backend. This option uses the current time as the\nauthor date rather than reusing the original author date when\nrewriting commits. We take care to handle the combination of\n--ignore-date and --committer-date-is-author-date in the same way as\nthe apply backend.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt   |  7 ++--\n builtin/rebase.c               | 13 ++++---\n sequencer.c                    | 66 +++++++++++++++++++++++++++-------\n sequencer.h                    |  1 +\n t/t3436-rebase-more-options.sh | 56 +++++++++++++++++++++++++++++\n 5 files changed, 123 insertions(+), 20 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f9ddfe2e77..79cecd2929 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies `--force-rebase`.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof each rebased commit (see linkgit:git-am[1]).\n+\tInstead of using the author date of the original commit, use\n+\tthe current time as the\tauthor date of the rebased commit.  This\n+\toption implies `--force-rebase`.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n  * --preserve-merges and --committer-date-is-author-date\n+ * --preserve-merges and --ignore-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 2579380729..583ac96fc7 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -89,6 +89,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.committer_date_is_author_date =\n \t\t\t\t\topts->committer_date_is_author_date;\n+\treplay.ignore_date = opts->ignore_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t N_(\"ignore author date and use current date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n-\tif (options.committer_date_is_author_date)\n+\tif (options.committer_date_is_author_date || options.ignore_date)\n \t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--ignore-date\") ||\n-\t\t    !strcmp(option, \"--whitespace=fix\") ||\n+\t\tif (!strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n \t\telse if (skip_prefix(option, \"-C\", &p)) {\n@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (options.committer_date_is_author_date)\n \t\t\targv_array_push(&options.git_am_opts,\n \t\t\t\t\t\"--committer-date-is-author-date\");\n+\t\tif (options.ignore_date)\n+\t\t\targv_array_push(&options.git_am_opts, \"--ignore-date\");\n \t} else {\n \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n \t\tif (ignore_whitespace) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 78d09f9252..4ccb5451a9 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n+static GIT_PATH_FUNC(rebase_path_ignore_date, \"rebase-merge/ignore_date\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -959,7 +960,11 @@ static int run_git_commit(struct repository *r,\n \n \tif (opts->committer_date_is_author_date)\n \t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t opts->ignore_date ?\n+\t\t\t\t \"\" :\n \t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\tif (opts->ignore_date)\n+\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \targv_array_push(&cmd.args, \"commit\");\n \n@@ -1434,26 +1439,51 @@ static int try_to_commit(struct repository *r,\n \t\tstruct ident_split id;\n \t\tstruct strbuf date = STRBUF_INIT;\n \n-\t\tif (split_ident_line(&id, author, (int)strlen(author)) < 0) {\n-\t\t\tres = error(_(\"invalid author identity '%s'\"), author);\n-\t\t\tgoto out;\n+\t\tif (!opts->ignore_date) {\n+\t\t\tif (split_ident_line(&id, author, (int)strlen(author)) < 0) {\n+\t\t\t\tres = error(_(\"invalid author identity '%s'\"),\n+\t\t\t\t\t    author);\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\t\t\tif (!id.date_begin) {\n+\t\t\t\tres = error(_(\n+\t\t\t\t\t\"corrupt author: missing date information\"));\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\t\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t\t    (int)(id.date_end - id.date_begin),\n+\t\t\t\t    id.date_begin,\n+\t\t\t\t    (int)(id.tz_end - id.tz_begin),\n+\t\t\t\t    id.tz_begin);\n+\t\t} else {\n+\t\t\treset_ident_date();\n \t\t}\n-\t\tif (!id.date_begin) {\n-\t\t\tres = error(_(\"corrupt author: missing date information\"));\n-\t\t\tgoto out;\n-\t\t}\n-\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n-\t\t\t    (int)(id.date_end - id.date_begin), id.date_begin,\n-\t\t\t    (int)(id.tz_end - id.tz_begin), id.tz_begin);\n \t\tcommitter = fmt_ident(opts->committer_name,\n \t\t\t\t      opts->committer_email,\n-\t\t\t\t      WANT_COMMITTER_IDENT, date.buf,\n+\t\t\t\t      WANT_COMMITTER_IDENT,\n+\t\t\t\t      opts->ignore_date ? NULL : date.buf,\n \t\t\t\t      IDENT_STRICT);\n \t\tstrbuf_release(&date);\n \t} else {\n \t\treset_ident_date();\n \t}\n \n+\tif (opts->ignore_date) {\n+\t\tstruct ident_split id;\n+\t\tchar *name, *email;\n+\n+\t\tif (split_ident_line(&id, author, strlen(author)) < 0) {\n+\t\t\terror(_(\"invalid author identity '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tname = xmemdupz(id.name_begin, id.name_end - id.name_begin);\n+\t\temail = xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);\n+\t\tauthor = fmt_ident(name, email, WANT_AUTHOR_IDENT, NULL,\n+\t\t\t\t   IDENT_STRICT);\n+\t\tfree(name);\n+\t\tfree(email);\n+\t}\n+\n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n \t\t\t\t author, committer, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n@@ -2583,6 +2613,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->committer_date_is_author_date = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_ignore_date())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->ignore_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2675,6 +2710,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n \tif (opts->committer_date_is_author_date)\n \t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n+\tif (opts->ignore_date)\n+\t\twrite_file(rebase_path_ignore_date(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3597,7 +3634,11 @@ static int do_merge(struct repository *r,\n \n \t\tif (opts->committer_date_is_author_date)\n \t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t opts->ignore_date ?\n+\t\t\t\t\t \"\" :\n \t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\t\tif (opts->ignore_date)\n+\t\t\targv_array_push(&cmd.env_array, \"GIT_AUTHOR_DATE=\");\n \n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n@@ -3877,7 +3918,8 @@ static int pick_commits(struct repository *r,\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n \t\t\t opts->record_origin || opts->edit ||\n-\t\t\t opts->committer_date_is_author_date));\n+\t\t\t opts->committer_date_is_author_date ||\n+\t\t\t opts->ignore_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 7ca657fe2c..20493a2be2 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -46,6 +46,7 @@ struct replay_opts {\n \tint quiet;\n \tint reschedule_failed_exec;\n \tint committer_date_is_author_date;\n+\tint ignore_date;\n \n \tint mainline;\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 50a63d8ebe..0ede2b8900 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n \ttest_ctime_is_atime -1\n '\n \n+# Checking for +0000 in the author date is sufficient since the\n+# default timezone is UTC but the timezone used while committing is\n+# +0530. The inverted logic in the grep is necessary to check all the\n+# author dates in the file.\n+test_ctime_is_ignored () {\n+\tgit log $1 --format=%ai >authortime &&\n+\t! grep -v +0000 authortime\n+}\n+\n+test_expect_success '--ignore-date works with apply backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with merge backend' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --ignore-date -m HEAD^ &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works after conflict resolution' '\n+\ttest_must_fail git rebase --ignore-date -m \\\n+\t\t--onto commit2^^ commit2^ commit2 &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_ignored -1\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge --no-ff commit3 &&\n+\tgit rebase -r --root --ignore-date &&\n+\ttest_ctime_is_ignored\n+'\n+\n+test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\tgit checkout --theirs foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -2 &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n+test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+\tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n+\t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n+\t\t\t\t--ignore-date --committer-date-is-author-date \\\n+\t\t\t\tside side &&\n+\ttest_ctime_is_atime -1 &&\n+\ttest_ctime_is_ignored -1\n+ '\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.28.0\n\n"},{"id":"403848","messageId":"20200817174004.92455-6-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200817174004.92455-1-phillip.wood123@gmail.com","subject":"[PATCH v8 5/5] rebase: add --reset-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-17T17:40:04Z","receivedAt":"2020-08-17T17:41:03Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nThe previous commit introduced --ignore-date flag to rebase -i, but the\nname is rather vague as it does not say whether the author date or the\ncommitter date is ignored. Add an alias to convey the precise purpose.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt   |  1 +\n builtin/rebase.c               |  4 +++-\n t/t3436-rebase-more-options.sh | 34 +++++++++++++++++++++-------------\n 3 files changed, 25 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 79cecd2929..1ee3bb4fac 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -450,6 +450,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tdate. This option implies `--force-rebase`.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the author date of the original commit, use\n \tthe current time as the\tauthor date of the rebased commit.  This\n \toption implies `--force-rebase`.\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 583ac96fc7..b126fbe940 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1505,8 +1505,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n \t\t\t &options.committer_date_is_author_date,\n \t\t\t N_(\"make committer date match author date\")),\n-\t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n \t\t\t N_(\"ignore author date and use current date\")),\n+\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-author-date\")),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 0ede2b8900..5b8963272a 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -117,53 +117,61 @@ test_ctime_is_ignored () {\n \t! grep -v +0000 authortime\n }\n \n-test_expect_success '--ignore-date works with apply backend' '\n+test_expect_success '--reset-author-date works with apply backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit rebase --apply --reset-author-date HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with merge backend' '\n+test_expect_success '--reset-author-date works with merge backend' '\n \tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n-\tgit rebase --ignore-date -m HEAD^ &&\n+\tgit rebase --reset-author-date -m HEAD^ &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works after conflict resolution' '\n-\ttest_must_fail git rebase --ignore-date -m \\\n+test_expect_success '--reset-author-date works after conflict resolution' '\n+\ttest_must_fail git rebase --reset-author-date -m \\\n \t\t--onto commit2^^ commit2^ commit2 &&\n \techo resolved >foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_ignored -1\n '\n \n-test_expect_success '--ignore-date works with rebase -r' '\n+test_expect_success '--reset-author-date works with rebase -r' '\n \tgit checkout side &&\n \tgit merge --no-ff commit3 &&\n-\tgit rebase -r --root --ignore-date &&\n+\tgit rebase -r --root --reset-author-date &&\n \ttest_ctime_is_ignored\n '\n \n-test_expect_success '--ignore-date with --committer-date-is-author-date works' '\n+test_expect_success '--reset-author-date with --committer-date-is-author-date works' '\n \ttest_must_fail git rebase -m --committer-date-is-author-date \\\n-\t\t--ignore-date --onto commit2^^ commit2^ commit3 &&\n+\t\t--reset-author-date --onto commit2^^ commit2^ commit3 &&\n \tgit checkout --theirs foo &&\n \tgit add foo &&\n \tgit rebase --continue &&\n \ttest_ctime_is_atime -2 &&\n \ttest_ctime_is_ignored -2\n '\n \n-test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '\n+test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '\n \tGIT_SEQUENCE_EDITOR=\"echo \\\"merge -C $(git rev-parse HEAD) commit3\\\">\" \\\n \t\tPATH=\"./test-bin:$PATH\" git rebase -i --strategy=test \\\n-\t\t\t\t--ignore-date --committer-date-is-author-date \\\n-\t\t\t\tside side &&\n+\t\t\t\t--reset-author-date \\\n+\t\t\t\t--committer-date-is-author-date side side &&\n \ttest_ctime_is_atime -1 &&\n \ttest_ctime_is_ignored -1\n  '\n \n+test_expect_success '--ignore-date is an alias for --reset-author-date' '\n+\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase --apply --ignore-date HEAD^ &&\n+\tgit commit --allow-empty -m empty --date=\"$GIT_AUTHOR_DATE\" &&\n+\tgit rebase -m --ignore-date HEAD^ &&\n+\ttest_ctime_is_ignored -2\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.28.0\n\n"},{"id":"403849","messageId":"20200817174004.92455-4-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200817174004.92455-1-phillip.wood123@gmail.com","subject":"[PATCH v8 3/5] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-17T17:40:02Z","receivedAt":"2020-08-17T17:41:04Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--committer-date-is-author-date option to the merge backend. This\noption uses the author date of the commit that is being rewritten as\nthe committer date when the new commit is created.\n\nOriginal-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 10 ++-\n builtin/rebase.c                       | 17 +++--\n sequencer.c                            | 86 +++++++++++++++++++++++++-\n sequencer.h                            |  3 +\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 58 ++++++++++++++++-\n 6 files changed, 162 insertions(+), 13 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex b003784f01..f9ddfe2e77 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -445,9 +445,13 @@ if the other side had no changes that conflicted.\n See also INCOMPATIBLE OPTIONS below.\n \n --committer-date-is-author-date::\n+\tInstead of using the current time as the committer date, use\n+\tthe author date of the commit being rebased as the committer\n+\tdate. This option implies `--force-rebase`.\n+\n --ignore-date::\n-\tThese flags are passed to 'git am' to easily change the dates\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tThis flag is passed to 'git am' to change the author date\n+\tof each rebased commit (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -585,7 +589,6 @@ INCOMPATIBLE OPTIONS\n The following options:\n \n  * --apply\n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -613,6 +616,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n  * --preserve-merges and --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex bd93e9742c..2579380729 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -88,6 +88,7 @@ struct rebase_options {\n \tint autosquash;\n \tchar *gpg_sign_opt;\n \tint autostash;\n+\tint committer_date_is_author_date;\n \tchar *cmd;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n@@ -124,6 +125,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.quiet = !(opts->flags & REBASE_NO_QUIET);\n \treplay.verbose = opts->flags & REBASE_VERBOSE;\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n+\treplay.committer_date_is_author_date =\n+\t\t\t\t\topts->committer_date_is_author_date;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -1497,9 +1500,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n-\t\t\t\t  &options.git_am_opts, NULL,\n-\t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\",\n+\t\t\t &options.committer_date_is_author_date,\n+\t\t\t N_(\"make committer date match author date\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n@@ -1794,11 +1797,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t    options.autosquash) {\n \t\tallow_preemptive_ff = 0;\n \t}\n+\tif (options.committer_date_is_author_date)\n+\t\toptions.flags |= REBASE_FORCE;\n \n \tfor (i = 0; i < options.git_am_opts.argc; i++) {\n \t\tconst char *option = options.git_am_opts.argv[i], *p;\n-\t\tif (!strcmp(option, \"--committer-date-is-author-date\") ||\n-\t\t    !strcmp(option, \"--ignore-date\") ||\n+\t\tif (!strcmp(option, \"--ignore-date\") ||\n \t\t    !strcmp(option, \"--whitespace=fix\") ||\n \t\t    !strcmp(option, \"--whitespace=strip\"))\n \t\t\tallow_preemptive_ff = 0;\n@@ -1855,6 +1859,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tif (ignore_whitespace)\n \t\t\targv_array_push(&options.git_am_opts,\n \t\t\t\t\t\"--ignore-whitespace\");\n+\t\tif (options.committer_date_is_author_date)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--committer-date-is-author-date\");\n \t} else {\n \t\t/* REBASE_MERGE and PRESERVE_MERGES */\n \t\tif (ignore_whitespace) {\ndiff --git a/sequencer.c b/sequencer.c\nindex 968a2d4ef3..78d09f9252 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -149,6 +149,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs-to-delete\")\n  * command-line.\n  */\n static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, \"rebase-merge/gpg_sign_opt\")\n+static GIT_PATH_FUNC(rebase_path_cdate_is_adate, \"rebase-merge/cdate_is_adate\")\n static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n@@ -302,6 +303,8 @@ int sequencer_remove_state(struct replay_opts *opts)\n \t\t}\n \t}\n \n+\tfree(opts->committer_name);\n+\tfree(opts->committer_email);\n \tfree(opts->gpg_sign);\n \tfree(opts->strategy);\n \tfor (i = 0; i < opts->xopts_nr; i++)\n@@ -872,6 +875,22 @@ static char *get_author(const char *message)\n \treturn NULL;\n }\n \n+static const char *author_date_from_env_array(const struct argv_array *env)\n+{\n+\tint i;\n+\tconst char *date;\n+\n+\tfor (i = 0; i < env->argc; i++)\n+\t\tif (skip_prefix(env->argv[i],\n+\t\t\t\t\"GIT_AUTHOR_DATE=\", &date))\n+\t\t\treturn date;\n+\t/*\n+\t * If GIT_AUTHOR_DATE is missing we should have already errored out when\n+\t * reading the script\n+\t */\n+\tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n+}\n+\n static const char staged_changes_advice[] =\n N_(\"you have staged changes in your working tree\\n\"\n \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n@@ -938,6 +957,10 @@ static int run_git_commit(struct repository *r,\n \t\t\t     gpg_opt, gpg_opt);\n \t}\n \n+\tif (opts->committer_date_is_author_date)\n+\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \targv_array_push(&cmd.args, \"commit\");\n \n \tif (!(flags & VERIFY_MSG))\n@@ -1315,6 +1338,7 @@ static int try_to_commit(struct repository *r,\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct strbuf commit_msg = STRBUF_INIT;\n \tchar *amend_author = NULL;\n+\tconst char *committer = NULL;\n \tconst char *hook_commit = NULL;\n \tenum commit_msg_cleanup_mode cleanup;\n \tint res = 0;\n@@ -1406,10 +1430,32 @@ static int try_to_commit(struct repository *r,\n \t\tgoto out;\n \t}\n \n-\treset_ident_date();\n+\tif (opts->committer_date_is_author_date) {\n+\t\tstruct ident_split id;\n+\t\tstruct strbuf date = STRBUF_INIT;\n+\n+\t\tif (split_ident_line(&id, author, (int)strlen(author)) < 0) {\n+\t\t\tres = error(_(\"invalid author identity '%s'\"), author);\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (!id.date_begin) {\n+\t\t\tres = error(_(\"corrupt author: missing date information\"));\n+\t\t\tgoto out;\n+\t\t}\n+\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n+\t\t\t    (int)(id.date_end - id.date_begin), id.date_begin,\n+\t\t\t    (int)(id.tz_end - id.tz_begin), id.tz_begin);\n+\t\tcommitter = fmt_ident(opts->committer_name,\n+\t\t\t\t      opts->committer_email,\n+\t\t\t\t      WANT_COMMITTER_IDENT, date.buf,\n+\t\t\t\t      IDENT_STRICT);\n+\t\tstrbuf_release(&date);\n+\t} else {\n+\t\treset_ident_date();\n+\t}\n \n \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n-\t\t\t\t author, NULL, opts->gpg_sign, extra)) {\n+\t\t\t\t author, committer, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n \t\tgoto out;\n \t}\n@@ -2532,6 +2578,11 @@ static int read_populate_opts(struct replay_opts *opts)\n \t\t\topts->signoff = 1;\n \t\t}\n \n+\t\tif (file_exists(rebase_path_cdate_is_adate())) {\n+\t\t\topts->allow_ff = 0;\n+\t\t\topts->committer_date_is_author_date = 1;\n+\t\t}\n+\n \t\tif (file_exists(rebase_path_reschedule_failed_exec()))\n \t\t\topts->reschedule_failed_exec = 1;\n \n@@ -2622,6 +2673,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \t\twrite_file(rebase_path_drop_redundant_commits(), \"%s\", \"\");\n \tif (opts->keep_redundant_commits)\n \t\twrite_file(rebase_path_keep_redundant_commits(), \"%s\", \"\");\n+\tif (opts->committer_date_is_author_date)\n+\t\twrite_file(rebase_path_cdate_is_adate(), \"%s\", \"\");\n \tif (opts->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3542,6 +3595,10 @@ static int do_merge(struct repository *r,\n \t\t\tgoto leave_merge;\n \t\t}\n \n+\t\tif (opts->committer_date_is_author_date)\n+\t\t\targv_array_pushf(&cmd.env_array, \"GIT_COMMITTER_DATE=%s\",\n+\t\t\t\t\t author_date_from_env_array(&cmd.env_array));\n+\n \t\tcmd.git_cmd = 1;\n \t\targv_array_push(&cmd.args, \"merge\");\n \t\targv_array_push(&cmd.args, \"-s\");\n@@ -3819,7 +3876,8 @@ static int pick_commits(struct repository *r,\n \tsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);\n \tif (opts->allow_ff)\n \t\tassert(!(opts->signoff || opts->no_commit ||\n-\t\t\t\topts->record_origin || opts->edit));\n+\t\t\t opts->record_origin || opts->edit ||\n+\t\t\t opts->committer_date_is_author_date));\n \tif (read_and_refresh_cache(r, opts))\n \t\treturn -1;\n \n@@ -4258,6 +4316,22 @@ static int commit_staged_changes(struct repository *r,\n \treturn 0;\n }\n \n+static int init_committer(struct replay_opts *opts)\n+{\n+\tstruct ident_split id;\n+\tconst char *committer;\n+\n+\tcommitter = git_committer_info(IDENT_STRICT);\n+\tif (split_ident_line(&id, committer, strlen(committer)) < 0)\n+\t\treturn error(_(\"invalid committer '%s'\"), committer);\n+\topts->committer_name =\n+\t\txmemdupz(id.name_begin, id.name_end - id.name_begin);\n+\topts->committer_email =\n+\t\txmemdupz(id.mail_begin, id.mail_end - id.mail_end);\n+\n+\treturn 0;\n+}\n+\n int sequencer_continue(struct repository *r, struct replay_opts *opts)\n {\n \tstruct todo_list todo_list = TODO_LIST_INIT;\n@@ -4269,6 +4343,9 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)\n \tif (read_populate_opts(opts))\n \t\treturn -1;\n \tif (is_rebase_i(opts)) {\n+\t\tif (opts->committer_date_is_author_date && init_committer(opts))\n+\t\t\treturn -1;\n+\n \t\tif ((res = read_populate_todo(r, &todo_list, opts)))\n \t\t\tgoto release_todo_list;\n \n@@ -5145,6 +5222,9 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla\n \n \tres = -1;\n \n+\tif (opts->committer_date_is_author_date && init_committer(opts))\n+\t\tgoto cleanup;\n+\n \tif (checkout_onto(r, opts, onto_name, &oid, orig_head))\n \t\tgoto cleanup;\n \ndiff --git a/sequencer.h b/sequencer.h\nindex 0bee85093e..7ca657fe2c 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -45,9 +45,12 @@ struct replay_opts {\n \tint verbose;\n \tint quiet;\n \tint reschedule_failed_exec;\n+\tint committer_date_is_author_date;\n \n \tint mainline;\n \n+\tchar *committer_name;\n+\tchar *committer_email;\n \tchar *gpg_sign;\n \tenum commit_msg_cleanup_mode default_msg_cleanup;\n \tint explicit_cleanup;\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 55ca46786d..c8234062c6 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \n test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' '\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 4f8a6e51c9..50a63d8ebe 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n+GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n+export GIT_AUTHOR_DATE\n+\n # This is a special case in which both am and interactive backends\n # provide the same output. It was done intentionally because\n # both the backends fall short of optimal behaviour.\n@@ -21,11 +24,20 @@ test_expect_success 'setup' '\n \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n \tgit commit -am \"update file\" &&\n \tgit tag side &&\n+\ttest_commit commit1 foo foo1 &&\n+\ttest_commit commit2 foo foo2 &&\n+\ttest_commit commit3 foo foo3 &&\n \n \tgit checkout --orphan master &&\n+\trm foo &&\n \ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n \tgit commit -am \"add file\" &&\n-\tgit tag main\n+\tgit tag main &&\n+\n+\tmkdir test-bin &&\n+\twrite_script test-bin/git-merge-test <<-\\EOF\n+\texec git-merge-recursive \"$@\"\n+\tEOF\n '\n \n test_expect_success '--ignore-whitespace works with apply backend' '\n@@ -52,6 +64,50 @@ test_expect_success '--ignore-whitespace is remembered when continuing' '\n \tgit diff --exit-code side\n '\n \n+test_ctime_is_atime () {\n+\tgit log $1 --format=%ai >authortime &&\n+\tgit log $1 --format=%ci >committertime &&\n+\ttest_cmp authortime committertime\n+}\n+\n+test_expect_success '--committer-date-is-author-date works with apply backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase --apply --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with merge backend' '\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git commit --amend --reset-author &&\n+\tgit rebase -m --committer-date-is-author-date HEAD^ &&\n+\ttest_ctime_is_atime -1\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with rebase -r' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tgit rebase -r --root --committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when forking merge' '\n+\tgit checkout side &&\n+\tGIT_AUTHOR_DATE=\"@1234 +0300\" git merge --no-ff commit3 &&\n+\tPATH=\"./test-bin:$PATH\" git rebase -r --root --strategy=test \\\n+\t\t\t\t\t--committer-date-is-author-date &&\n+\ttest_ctime_is_atime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '\n+\tgit checkout commit2 &&\n+\tGIT_AUTHOR_DATE=\"@1980 +0000\" git commit --amend --only --reset-author &&\n+\ttest_must_fail git rebase -m --committer-date-is-author-date \\\n+\t\t--onto HEAD^^ HEAD^ &&\n+\techo resolved > foo &&\n+\tgit add foo &&\n+\tgit rebase --continue &&\n+\ttest_ctime_is_atime -1\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.28.0\n\n"},{"id":"403850","messageId":"20200817174004.92455-2-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200817174004.92455-1-phillip.wood123@gmail.com","subject":"[PATCH v8 1/5] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-17T17:40:00Z","receivedAt":"2020-08-17T17:41:08Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n\nRebase is implemented with two different backends - 'apply' and\n'merge' each of which support a different set of options. In\nparticular the apply backend supports a number of options implemented\nby 'git am' that are not implemented in the merge backend. This means\nthat the available options are different depending on which backend is\nused which is confusing. This patch adds support for the\n--ignore-whitespace option to the merge backend. This option treats\nlines with only whitespace changes as unchanged and is implemented in\nthe merge backend by translating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\nSigned-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n---\n Documentation/git-rebase.txt           | 19 +++++++-\n builtin/rebase.c                       | 19 ++++++--\n t/t3422-rebase-incompatible-options.sh |  1 -\n t/t3436-rebase-more-options.sh         | 60 ++++++++++++++++++++++++++\n 4 files changed, 93 insertions(+), 6 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex f7a6033607..b003784f01 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used\n with `--keep-base` in order to drop those commits from your branch.\n \n --ignore-whitespace::\n+\tIgnore whitespace differences when trying to reconcile\n+differences. Currently, each backend implements an approximation of\n+this behavior:\n++\n+apply backend: When applying a patch, ignore changes in whitespace in\n+context lines. Unfortunately, this means that if the \"old\" lines being\n+replaced by the patch differ only in whitespace from the existing\n+file, you will get a merge conflict instead of a successful patch\n+application.\n++\n+merge backend: Treat lines with only whitespace changes as unchanged\n+when merging. Unfortunately, this means that any patch hunks that were\n+intended to modify whitespace and nothing else will be dropped, even\n+if the other side had no changes that conflicted.\n+\n --whitespace=<option>::\n-\tThese flags are passed to the 'git apply' program\n+\tThis flag is passed to the 'git apply' program\n \t(see linkgit:git-apply[1]) that applies the patch.\n \tImplies --apply.\n +\n@@ -572,7 +587,6 @@ The following options:\n  * --apply\n  * --committer-date-is-author-date\n  * --ignore-date\n- * --ignore-whitespace\n  * --whitespace\n  * -C\n \n@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:\n  * --preserve-merges and --signoff\n  * --preserve-merges and --rebase-merges\n  * --preserve-merges and --empty=\n+ * --preserve-merges and --ignore-whitespace\n  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 27a07d4e78..bd93e9742c 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \treplay.reschedule_failed_exec = opts->reschedule_failed_exec;\n \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n+\n \tif (opts->strategy_opts)\n \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n \n@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \tstruct strbuf revisions = STRBUF_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct object_id merge_base;\n+\tint ignore_whitespace = 0;\n \tenum action action = ACTION_NONE;\n \tconst char *gpg_sign = NULL;\n \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\tPARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },\n \t\tOPT_BOOL(0, \"signoff\", &options.signoff,\n \t\t\t N_(\"add a Signed-off-by: line to each commit\")),\n-\t\tOPT_PASSTHRU_ARGV(0, \"ignore-whitespace\", &options.git_am_opts,\n-\t\t\t\t  NULL, N_(\"passed to 'git am'\"),\n-\t\t\t\t  PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"committer-date-is-author-date\",\n \t\t\t\t  &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV(0, \"ignore-date\", &options.git_am_opts, NULL,\n \t\t\t\t  N_(\"passed to 'git am'\"), PARSE_OPT_NOARG),\n \t\tOPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n \t\t\t\t  N_(\"passed to 'git apply'\"), 0),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace\")),\n \t\tOPT_PASSTHRU_ARGV(0, \"whitespace\", &options.git_am_opts,\n \t\t\t\t  N_(\"action\"), N_(\"passed to 'git apply'\"), 0),\n \t\tOPT_BIT('f', \"force-rebase\", &options.flags,\n@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\timply_merge(&options, \"--rebase-merges\");\n \t}\n \n+\tif (options.type == REBASE_APPLY) {\n+\t\tif (ignore_whitespace)\n+\t\t\targv_array_push(&options.git_am_opts,\n+\t\t\t\t\t\"--ignore-whitespace\");\n+\t} else {\n+\t\t/* REBASE_MERGE and PRESERVE_MERGES */\n+\t\tif (ignore_whitespace) {\n+\t\t\tstring_list_append(&strategy_options,\n+\t\t\t\t\t   \"ignore-space-change\");\n+\t\t}\n+\t}\n+\n \tif (strategy_options.nr) {\n \t\tint i;\n \ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex 50e7960702..55ca46786d 100755\n--- a/t/t3422-rebase-incompatible-options.sh\n+++ b/t/t3422-rebase-incompatible-options.sh\n@@ -61,7 +61,6 @@ test_rebase_am_only () {\n }\n \n test_rebase_am_only --whitespace=fix\n-test_rebase_am_only --ignore-whitespace\n test_rebase_am_only --committer-date-is-author-date\n test_rebase_am_only -C4\n \ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nnew file mode 100755\nindex 0000000000..4f8a6e51c9\n--- /dev/null\n+++ b/t/t3436-rebase-more-options.sh\n@@ -0,0 +1,60 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Rohit Ashiwal\n+#\n+\n+test_description='tests to ensure compatibility between am and interactive backends'\n+\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+# This is a special case in which both am and interactive backends\n+# provide the same output. It was done intentionally because\n+# both the backends fall short of optimal behaviour.\n+test_expect_success 'setup' '\n+\tgit checkout -b topic &&\n+\ttest_write_lines \"line 1\" \"\tline 2\" \"line 3\" >file &&\n+\tgit add file &&\n+\tgit commit -m \"add file\" &&\n+\n+\ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n+\tgit commit -am \"update file\" &&\n+\tgit tag side &&\n+\n+\tgit checkout --orphan master &&\n+\ttest_write_lines \"line 1\" \"        line 2\" \"line 3\" >file &&\n+\tgit commit -am \"add file\" &&\n+\tgit tag main\n+'\n+\n+test_expect_success '--ignore-whitespace works with apply backend' '\n+\ttest_must_fail git rebase --apply main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --apply --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace works with merge backend' '\n+\ttest_must_fail git rebase --merge main side &&\n+\tgit rebase --abort &&\n+\tgit rebase --merge --ignore-whitespace main side &&\n+\tgit diff --exit-code side\n+'\n+\n+test_expect_success '--ignore-whitespace is remembered when continuing' '\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_LINES=\"break 1\" git rebase -i --ignore-whitespace \\\n+\t\t\tmain side &&\n+\t\tgit rebase --continue\n+\t) &&\n+\tgit diff --exit-code side\n+'\n+\n+# This must be the last test in this file\n+test_expect_success '$EDITOR and friends are unchanged' '\n+\ttest_editor_unchanged\n+'\n+\n+test_done\n-- \n2.28.0\n\n"},{"id":"403851","messageId":"20200817174004.92455-1-phillip.wood123@gmail.com","threadId":"53176","inReplyTo":"20200407141125.30872-1-phillip.wood123@gmail.com","subject":"[PATCH v8 0/5] cleanup ra/rebase-i-more-options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-17T17:39:59Z","receivedAt":"2020-08-17T17:41:18Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"From: Phillip Wood <phillip.wood@dunelm.org.uk>\n\nThanks to dscho for his comments on v7. Patch 2 is new, it extends\ncommit_tree_extended() to take an explicit committer and changes am to\nuse that rather than exporting GIT_COMMITTER_DATE. The old patch 3 is\ngone as it renamed a variable in preparation for repurposing it in the\nnext patch but it is no longer repurposed. The changes in patches 3 &\n4 use the new argument to commit_tree_extended() rather than exporting\nGIT_COMMITTER_DATE in try_to_commit().\n\nPhillip Wood (3):\n  am: stop exporting GIT_COMMITTER_DATE\n  rebase -i: support --committer-date-is-author-date\n  rebase -i: support --ignore-date\n\nRohit Ashiwal (2):\n  rebase -i: add --ignore-whitespace flag\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt           |  33 ++++-\n builtin/am.c                           |  28 +++-\n builtin/commit.c                       |   4 +-\n builtin/rebase.c                       |  47 +++++--\n commit.c                               |  11 +-\n commit.h                               |   7 +-\n ident.c                                |  24 ++--\n sequencer.c                            | 130 +++++++++++++++++-\n sequencer.h                            |   4 +\n t/t3422-rebase-incompatible-options.sh |   2 -\n t/t3436-rebase-more-options.sh         | 180 +++++++++++++++++++++++++\n 11 files changed, 422 insertions(+), 48 deletions(-)\n create mode 100755 t/t3436-rebase-more-options.sh\n\nRange-diff against v7:\n1:  5bb4226007 = 1:  5bb4226007 rebase -i: add --ignore-whitespace flag\n-:  ---------- > 2:  33f62dd2a0 am: stop exporting GIT_COMMITTER_DATE\n2:  e5fdb574ed ! 3:  34431945c8 rebase -i: support --committer-date-is-author-date\n    @@ Documentation/git-rebase.txt: if the other side had no changes that conflicted.\n      --committer-date-is-author-date::\n     +\tInstead of using the current time as the committer date, use\n     +\tthe author date of the commit being rebased as the committer\n    -+\tdate. This option implies --force-rebase.\n    ++\tdate. This option implies `--force-rebase`.\n     +\n      --ignore-date::\n     -\tThese flags are passed to 'git am' to easily change the dates\n    @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs\n      static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n      static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n      static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n    +@@ sequencer.c: int sequencer_remove_state(struct replay_opts *opts)\n    + \t\t}\n    + \t}\n    + \n    ++\tfree(opts->committer_name);\n    ++\tfree(opts->committer_email);\n    + \tfree(opts->gpg_sign);\n    + \tfree(opts->strategy);\n    + \tfor (i = 0; i < opts->xopts_nr; i++)\n     @@ sequencer.c: static char *get_author(const char *message)\n      \treturn NULL;\n      }\n    @@ sequencer.c: static int run_git_commit(struct repository *r,\n      \n      \tif (!(flags & VERIFY_MSG))\n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n    - \t\tcommit_list_insert(current_head, &parents);\n    + \tstruct strbuf err = STRBUF_INIT;\n    + \tstruct strbuf commit_msg = STRBUF_INIT;\n    + \tchar *amend_author = NULL;\n    ++\tconst char *committer = NULL;\n    + \tconst char *hook_commit = NULL;\n    + \tenum commit_msg_cleanup_mode cleanup;\n    + \tint res = 0;\n    +@@ sequencer.c: static int try_to_commit(struct repository *r,\n    + \t\tgoto out;\n      \t}\n      \n    +-\treset_ident_date();\n     +\tif (opts->committer_date_is_author_date) {\n    -+\t\tstruct ident_split ident;\n    ++\t\tstruct ident_split id;\n     +\t\tstruct strbuf date = STRBUF_INIT;\n     +\n    -+\t\tif (split_ident_line(&ident, author, (int)strlen(author)) < 0) {\n    -+\t\t\tres = error(_(\"malformed ident line '%s'\"), author);\n    ++\t\tif (split_ident_line(&id, author, (int)strlen(author)) < 0) {\n    ++\t\t\tres = error(_(\"invalid author identity '%s'\"), author);\n     +\t\t\tgoto out;\n     +\t\t}\n    -+\t\tif (!ident.date_begin) {\n    -+\t\t\tres = error(_(\"corrupted author without date information\"));\n    ++\t\tif (!id.date_begin) {\n    ++\t\t\tres = error(_(\"corrupt author: missing date information\"));\n     +\t\t\tgoto out;\n     +\t\t}\n    -+\n     +\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n    -+\t\t\t    (int)(ident.date_end - ident.date_begin),\n    -+\t\t\t    ident.date_begin,\n    -+\t\t\t    (int)(ident.tz_end - ident.tz_begin),\n    -+\t\t\t    ident.tz_begin);\n    -+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n    ++\t\t\t    (int)(id.date_end - id.date_begin), id.date_begin,\n    ++\t\t\t    (int)(id.tz_end - id.tz_begin), id.tz_begin);\n    ++\t\tcommitter = fmt_ident(opts->committer_name,\n    ++\t\t\t\t      opts->committer_email,\n    ++\t\t\t\t      WANT_COMMITTER_IDENT, date.buf,\n    ++\t\t\t\t      IDENT_STRICT);\n     +\t\tstrbuf_release(&date);\n    -+\n    -+\t\tif (res)\n    -+\t\t\tgoto out;\n    ++\t} else {\n    ++\t\treset_ident_date();\n     +\t}\n    -+\n    - \tif (write_index_as_tree(&tree, r->index, r->index_file, 0, NULL)) {\n    - \t\tres = error(_(\"git write-tree failed to write a tree\"));\n    + \n    + \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n    +-\t\t\t\t author, NULL, opts->gpg_sign, extra)) {\n    ++\t\t\t\t author, committer, opts->gpg_sign, extra)) {\n    + \t\tres = error(_(\"failed to write commit object\"));\n      \t\tgoto out;\n    + \t}\n     @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)\n      \t\t\topts->signoff = 1;\n      \t\t}\n    @@ sequencer.c: static int pick_commits(struct repository *r,\n      \tif (opts->allow_ff)\n      \t\tassert(!(opts->signoff || opts->no_commit ||\n     -\t\t\t\topts->record_origin || opts->edit));\n    -+\t\t\t\topts->record_origin || opts->edit ||\n    -+\t\t\t\topts->committer_date_is_author_date));\n    ++\t\t\t opts->record_origin || opts->edit ||\n    ++\t\t\t opts->committer_date_is_author_date));\n      \tif (read_and_refresh_cache(r, opts))\n      \t\treturn -1;\n      \n    +@@ sequencer.c: static int commit_staged_changes(struct repository *r,\n    + \treturn 0;\n    + }\n    + \n    ++static int init_committer(struct replay_opts *opts)\n    ++{\n    ++\tstruct ident_split id;\n    ++\tconst char *committer;\n    ++\n    ++\tcommitter = git_committer_info(IDENT_STRICT);\n    ++\tif (split_ident_line(&id, committer, strlen(committer)) < 0)\n    ++\t\treturn error(_(\"invalid committer '%s'\"), committer);\n    ++\topts->committer_name =\n    ++\t\txmemdupz(id.name_begin, id.name_end - id.name_begin);\n    ++\topts->committer_email =\n    ++\t\txmemdupz(id.mail_begin, id.mail_end - id.mail_end);\n    ++\n    ++\treturn 0;\n    ++}\n    ++\n    + int sequencer_continue(struct repository *r, struct replay_opts *opts)\n    + {\n    + \tstruct todo_list todo_list = TODO_LIST_INIT;\n    +@@ sequencer.c: int sequencer_continue(struct repository *r, struct replay_opts *opts)\n    + \tif (read_populate_opts(opts))\n    + \t\treturn -1;\n    + \tif (is_rebase_i(opts)) {\n    ++\t\tif (opts->committer_date_is_author_date && init_committer(opts))\n    ++\t\t\treturn -1;\n    ++\n    + \t\tif ((res = read_populate_todo(r, &todo_list, opts)))\n    + \t\t\tgoto release_todo_list;\n    + \n    +@@ sequencer.c: int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla\n    + \n    + \tres = -1;\n    + \n    ++\tif (opts->committer_date_is_author_date && init_committer(opts))\n    ++\t\tgoto cleanup;\n    ++\n    + \tif (checkout_onto(r, opts, onto_name, &oid, orig_head))\n    + \t\tgoto cleanup;\n    + \n     \n      ## sequencer.h ##\n     @@ sequencer.h: struct replay_opts {\n    @@ sequencer.h: struct replay_opts {\n      \n      \tint mainline;\n      \n    ++\tchar *committer_name;\n    ++\tchar *committer_email;\n    + \tchar *gpg_sign;\n    + \tenum commit_msg_cleanup_mode default_msg_cleanup;\n    + \tint explicit_cleanup;\n     \n      ## t/t3422-rebase-incompatible-options.sh ##\n     @@ t/t3422-rebase-incompatible-options.sh: test_rebase_am_only () {\n3:  cf5c9a2456 < -:  ---------- sequencer: rename amend_author to author_to_free\n4:  3865fdf461 ! 4:  060c0ea2d0 rebase -i: support --ignore-date\n    @@ Commit message\n     \n      ## Documentation/git-rebase.txt ##\n     @@ Documentation/git-rebase.txt: See also INCOMPATIBLE OPTIONS below.\n    - \tdate. This option implies --force-rebase.\n    + \tdate. This option implies `--force-rebase`.\n      \n      --ignore-date::\n     -\tThis flag is passed to 'git am' to change the author date\n    @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_refs_to_delete, \"rebase-merge/refs\n      static GIT_PATH_FUNC(rebase_path_orig_head, \"rebase-merge/orig-head\")\n      static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n      static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n    -@@ sequencer.c: static const char *author_date_from_env_array(const struct argv_array *env)\n    - \tBUG(\"GIT_AUTHOR_DATE missing from author script\");\n    - }\n    - \n    -+/* Construct a free()able author string with current time as the author date */\n    -+static char *ignore_author_date(const char *author)\n    -+{\n    -+\tint len;\n    -+\tstruct ident_split ident;\n    -+\tstruct strbuf new_author = STRBUF_INIT;\n    -+\n    -+\tif (split_ident_line(&ident, author, strlen(author)) < 0) {\n    -+\t\terror(_(\"invalid author identity: %s\"), author);\n    -+\t\treturn NULL;\n    -+\t}\n    -+\n    -+\tlen = ident.mail_end - ident.name_begin + 1;\n    -+\tstrbuf_addf(&new_author, \"%.*s \", len, ident.name_begin);\n    -+\tdatestamp(&new_author);\n    -+\treturn strbuf_detach(&new_author, NULL);\n    -+}\n    -+\n    - static const char staged_changes_advice[] =\n    - N_(\"you have staged changes in your working tree\\n\"\n    - \"If these changes are meant to be squashed into the previous commit, run:\\n\"\n     @@ sequencer.c: static int run_git_commit(struct repository *r,\n      \n      \tif (opts->committer_date_is_author_date)\n    @@ sequencer.c: static int run_git_commit(struct repository *r,\n      \targv_array_push(&cmd.args, \"commit\");\n      \n     @@ sequencer.c: static int try_to_commit(struct repository *r,\n    - \t\t\t    ident.date_begin,\n    - \t\t\t    (int)(ident.tz_end - ident.tz_begin),\n    - \t\t\t    ident.tz_begin);\n    --\t\tres = setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n    -+\t\tres = setenv(\"GIT_COMMITTER_DATE\",\n    -+\t\t\t     opts->ignore_date ? \"\" : date.buf, 1);\n    + \t\tstruct ident_split id;\n    + \t\tstruct strbuf date = STRBUF_INIT;\n    + \n    +-\t\tif (split_ident_line(&id, author, (int)strlen(author)) < 0) {\n    +-\t\t\tres = error(_(\"invalid author identity '%s'\"), author);\n    +-\t\t\tgoto out;\n    ++\t\tif (!opts->ignore_date) {\n    ++\t\t\tif (split_ident_line(&id, author, (int)strlen(author)) < 0) {\n    ++\t\t\t\tres = error(_(\"invalid author identity '%s'\"),\n    ++\t\t\t\t\t    author);\n    ++\t\t\t\tgoto out;\n    ++\t\t\t}\n    ++\t\t\tif (!id.date_begin) {\n    ++\t\t\t\tres = error(_(\n    ++\t\t\t\t\t\"corrupt author: missing date information\"));\n    ++\t\t\t\tgoto out;\n    ++\t\t\t}\n    ++\t\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n    ++\t\t\t\t    (int)(id.date_end - id.date_begin),\n    ++\t\t\t\t    id.date_begin,\n    ++\t\t\t\t    (int)(id.tz_end - id.tz_begin),\n    ++\t\t\t\t    id.tz_begin);\n    ++\t\t} else {\n    ++\t\t\treset_ident_date();\n    + \t\t}\n    +-\t\tif (!id.date_begin) {\n    +-\t\t\tres = error(_(\"corrupt author: missing date information\"));\n    +-\t\t\tgoto out;\n    +-\t\t}\n    +-\t\tstrbuf_addf(&date, \"@%.*s %.*s\",\n    +-\t\t\t    (int)(id.date_end - id.date_begin), id.date_begin,\n    +-\t\t\t    (int)(id.tz_end - id.tz_begin), id.tz_begin);\n    + \t\tcommitter = fmt_ident(opts->committer_name,\n    + \t\t\t\t      opts->committer_email,\n    +-\t\t\t\t      WANT_COMMITTER_IDENT, date.buf,\n    ++\t\t\t\t      WANT_COMMITTER_IDENT,\n    ++\t\t\t\t      opts->ignore_date ? NULL : date.buf,\n    + \t\t\t\t      IDENT_STRICT);\n      \t\tstrbuf_release(&date);\n    - \n    - \t\tif (res)\n    -@@ sequencer.c: static int try_to_commit(struct repository *r,\n    - \n    - \treset_ident_date();\n    + \t} else {\n    + \t\treset_ident_date();\n    + \t}\n      \n     +\tif (opts->ignore_date) {\n    -+\t\tauthor = ignore_author_date(author);\n    -+\t\tif (!author) {\n    -+\t\t\tres = -1;\n    ++\t\tstruct ident_split id;\n    ++\t\tchar *name, *email;\n    ++\n    ++\t\tif (split_ident_line(&id, author, strlen(author)) < 0) {\n    ++\t\t\terror(_(\"invalid author identity '%s'\"), author);\n     +\t\t\tgoto out;\n     +\t\t}\n    -+\t\tfree(author_to_free);\n    -+\t\tauthor_to_free = (char *)author;\n    ++\t\tname = xmemdupz(id.name_begin, id.name_end - id.name_begin);\n    ++\t\temail = xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);\n    ++\t\tauthor = fmt_ident(name, email, WANT_AUTHOR_IDENT, NULL,\n    ++\t\t\t\t   IDENT_STRICT);\n    ++\t\tfree(name);\n    ++\t\tfree(email);\n     +\t}\n     +\n    - \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents,\n    - \t\t\t\t oid, author, opts->gpg_sign, extra)) {\n    + \tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n    + \t\t\t\t author, committer, opts->gpg_sign, extra)) {\n      \t\tres = error(_(\"failed to write commit object\"));\n     @@ sequencer.c: static int read_populate_opts(struct replay_opts *opts)\n      \t\t\topts->committer_date_is_author_date = 1;\n    @@ sequencer.c: static int do_merge(struct repository *r,\n     @@ sequencer.c: static int pick_commits(struct repository *r,\n      \tif (opts->allow_ff)\n      \t\tassert(!(opts->signoff || opts->no_commit ||\n    - \t\t\t\topts->record_origin || opts->edit ||\n    --\t\t\t\topts->committer_date_is_author_date));\n    -+\t\t\t\topts->committer_date_is_author_date ||\n    -+\t\t\t\topts->ignore_date));\n    + \t\t\t opts->record_origin || opts->edit ||\n    +-\t\t\t opts->committer_date_is_author_date));\n    ++\t\t\t opts->committer_date_is_author_date ||\n    ++\t\t\t opts->ignore_date));\n      \tif (read_and_refresh_cache(r, opts))\n      \t\treturn -1;\n      \n5:  0b6b19cb68 ! 5:  92ed3bed9f rebase: add --reset-author-date\n    @@ Commit message\n     \n      ## Documentation/git-rebase.txt ##\n     @@ Documentation/git-rebase.txt: See also INCOMPATIBLE OPTIONS below.\n    - \tdate. This option implies --force-rebase.\n    + \tdate. This option implies `--force-rebase`.\n      \n      --ignore-date::\n     +--reset-author-date::\n-- \n2.28.0\n\n"},{"id":"403869","messageId":"xmqqtux113z6.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200817174004.92455-3-phillip.wood123@gmail.com","subject":"Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-08-17T19:12:29Z","receivedAt":"2020-08-17T19:13:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>\n> The implementation of --committer-date-is-author-date exports\n> GIT_COMMITTER_DATE to override the default committer date but does not\n> reset GIT_COMMITTER_DATE in the environment after creating the commit\n> so it is set in the environment of any hooks that get run. We're about\n> to add the same functionality to the sequencer and do not want to have\n> GIT_COMMITTER_DATE set when running hooks or exec commands so lets\n> update commit_tree_extended() to take an explicit committer so we\n> override the default date without setting GIT_COMMITTER_DATE in the\n> environment.\n>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  builtin/am.c     | 28 +++++++++++++++++++++++-----\n>  builtin/commit.c |  4 ++--\n>  commit.c         | 11 +++++++----\n>  commit.h         |  7 +++----\n>  ident.c          | 24 ++++++++++++++----------\n>  sequencer.c      |  4 ++--\n>  6 files changed, 51 insertions(+), 27 deletions(-)\n\nNice.\n\nObviously this would affect the environment while am is running, and\nthe change is observable by post-applypatch hook.  I am not sure if\nthis change-in-behaviour would negatively affect people's hooks, but\ngiven the large end-user population we have, somebody somewhere will\nget hit.\n\n> diff --git a/ident.c b/ident.c\n> index e666ee4e59..7cbf223350 100644\n> --- a/ident.c\n> +++ b/ident.c\n> @@ -361,11 +361,15 @@ N_(\"\\n\"\n>  const char *fmt_ident(const char *name, const char *email,\n>  \t\t      enum want_ident whose_ident, const char *date_str, int flag)\n>  {\n> -\tstatic struct strbuf ident = STRBUF_INIT;\n> +\tstatic int index;\n> +\tstatic struct strbuf ident_pool[2] = { STRBUF_INIT, STRBUF_INIT };\n>  \tint strict = (flag & IDENT_STRICT);\n>  \tint want_date = !(flag & IDENT_NO_DATE);\n>  \tint want_name = !(flag & IDENT_NO_NAME);\n>  \n> +\tstruct strbuf *ident = &ident_pool[index];\n> +\tindex = (index + 1) % ARRAY_SIZE(ident_pool);\n\n2-element rotating buffer because we happen to care at most two\nidents at the same time, author's and committer's?\n\nHow many callers of fmt_ident() do we have these days?  I wonder if\nwe can introduce a new API that lets/forces the caller to prepare a\nstrbuf and migrate the current callers of this function to it, of if\nit is too large a churn for the purpose of this series.\n\nThanks.\n"},{"id":"403999","messageId":"2ad142e6-5f2c-7e05-c8d3-ab6efcfc7058@gmail.com","threadId":"53176","inReplyTo":"xmqqtux113z6.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-19T10:20:30Z","receivedAt":"2020-08-19T10:20:42Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 17/08/2020 20:12, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n>>\n>> The implementation of --committer-date-is-author-date exports\n>> GIT_COMMITTER_DATE to override the default committer date but does not\n>> reset GIT_COMMITTER_DATE in the environment after creating the commit\n>> so it is set in the environment of any hooks that get run. We're about\n>> to add the same functionality to the sequencer and do not want to have\n>> GIT_COMMITTER_DATE set when running hooks or exec commands so lets\n>> update commit_tree_extended() to take an explicit committer so we\n>> override the default date without setting GIT_COMMITTER_DATE in the\n>> environment.\n>>\n>> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n>> ---\n>>  builtin/am.c     | 28 +++++++++++++++++++++++-----\n>>  builtin/commit.c |  4 ++--\n>>  commit.c         | 11 +++++++----\n>>  commit.h         |  7 +++----\n>>  ident.c          | 24 ++++++++++++++----------\n>>  sequencer.c      |  4 ++--\n>>  6 files changed, 51 insertions(+), 27 deletions(-)\n> \n> Nice.\n> \n> Obviously this would affect the environment while am is running, and\n> the change is observable by post-applypatch hook.  I am not sure if\n> this change-in-behaviour would negatively affect people's hooks, but\n> given the large end-user population we have, somebody somewhere will\n> get hit.\n\nYes I did think about that but decided it was probably better to fix it.\nAt the moment the pre-applypatch gets GIT_COMMITTER_DATE set to the date\nof the last commit which does not make much sense. If anyone does need\nthe committer date in the post-applypatch hook they can look at HEAD. We\nshould perhaps mention that in the release notes\n\n>> diff --git a/ident.c b/ident.c\n>> index e666ee4e59..7cbf223350 100644\n>> --- a/ident.c\n>> +++ b/ident.c\n>> @@ -361,11 +361,15 @@ N_(\"\\n\"\n>>  const char *fmt_ident(const char *name, const char *email,\n>>  \t\t      enum want_ident whose_ident, const char *date_str, int flag)\n>>  {\n>> -\tstatic struct strbuf ident = STRBUF_INIT;\n>> +\tstatic int index;\n>> +\tstatic struct strbuf ident_pool[2] = { STRBUF_INIT, STRBUF_INIT };\n>>  \tint strict = (flag & IDENT_STRICT);\n>>  \tint want_date = !(flag & IDENT_NO_DATE);\n>>  \tint want_name = !(flag & IDENT_NO_NAME);\n>>  \n>> +\tstruct strbuf *ident = &ident_pool[index];\n>> +\tindex = (index + 1) % ARRAY_SIZE(ident_pool);\n> \n> 2-element rotating buffer because we happen to care at most two\n> idents at the same time, author's and committer's?\n> \n> How many callers of fmt_ident() do we have these days?  I wonder if\n> we can introduce a new API that lets/forces the caller to prepare a\n> strbuf and migrate the current callers of this function to it, of if\n> it is too large a churn for the purpose of this series.\n\nAfter this series is applied there are the following callers\n\nblame.c:207: ident = fmt_ident(\"Not Committed Yet\", \"not.committed.yet\",\nbuiltin/am.c:1591: author = fmt_ident(state->author_name,\nstate->author_email,\nbuiltin/am.c:1597: committer = fmt_ident(state->committer_name,\nbuiltin/commit.c:638: strbuf_addstr(author_ident, fmt_ident(name, email,\nWANT_AUTHOR_IDENT, date,\nident.c:466: return fmt_ident(name, email, whose_ident, NULL,\nident.c:476: return fmt_ident(getenv(\"GIT_AUTHOR_NAME\"),\nident.c:489: return fmt_ident(getenv(\"GIT_COMMITTER_NAME\"),\nsequencer.c:1461: committer = fmt_ident(opts->committer_name,\nsequencer.c:1481: author = fmt_ident(name, email, WANT_AUTHOR_IDENT, NULL,\n\nIn blame.c we'd have to add an strbuf to pass in,\n\nThe caller in builtin/commit.c would obviously be easy to convert as it\nis stuffing the result into an strbuf already.\n\nFor am and the sequencer fmt_ident() is in a function which is called\nfrom a loop and it is convenient not to have to worry about passing an\nstrbuf around or allocating and freeing it on each function call\n\nThe callers in ident (fmt_name(), git_author_info() and\ngit_committer_info()) return the string so they would need their own\nstrbuf or have to be changed so the caller passed one in. There are\nquite a few callers of those functions and they seem to either\nimmediately call split_ident_line() or duplicate the returned string\n(mostly the latter).\n\nSo it would be a bit of work to do it but not an enormous amount\n(assuming we don't change the signature of git_author_info() etc in\nident.c, although given the pattern of callers it might be worth doing\nthat if they are mostly duplicating the returned string anyway)\n\nI'm going to be off line for 10-14 days from the beginning of next week,\nI could take a look at it after that, or we could leave it for a future\nimprovement - what do you think?\n\nBest Wishes\n\nPhillip\n\n\n> \n> Thanks.\n> \n\n"},{"id":"404000","messageId":"88535175-0540-c96d-24b5-c4d407422a8c@gmail.com","threadId":"53176","inReplyTo":"20200817174004.92455-5-phillip.wood123@gmail.com","subject":"Re: [PATCH v8 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-19T10:22:46Z","receivedAt":"2020-08-19T10:22:56Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 17/08/2020 18:40, Phillip Wood wrote:\n> From: Phillip Wood <phillip.wood@dunelm.org.uk>\n> \n> Rebase is implemented with two different backends - 'apply' and\n> 'merge' each of which support a different set of options. In\n> particular the apply backend supports a number of options implemented\n> by 'git am' that are not implemented in the merge backend. This means\n> that the available options are different depending on which backend is\n> used which is confusing. This patch adds support for the --ignore-date\n> option to the merge backend. This option uses the current time as the\n> author date rather than reusing the original author date when\n> rewriting commits. We take care to handle the combination of\n> --ignore-date and --committer-date-is-author-date in the same way as\n> the apply backend.\n> \n> Original-patch-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>\n> ---\n>  Documentation/git-rebase.txt   |  7 ++--\n>  builtin/rebase.c               | 13 ++++---\n>  sequencer.c                    | 66 +++++++++++++++++++++++++++-------\n>  sequencer.h                    |  1 +\n>  t/t3436-rebase-more-options.sh | 56 +++++++++++++++++++++++++++++\n>  5 files changed, 123 insertions(+), 20 deletions(-)\n> \n>  [...]\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 50a63d8ebe..0ede2b8900 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl\n>  \ttest_ctime_is_atime -1\n>  '\n>  \n> +# Checking for +0000 in the author date is sufficient since the\n> +# default timezone is UTC but the timezone used while committing is\n> +# +0530. The inverted logic in the grep is necessary to check all the\n> +# author dates in the file.\n> +test_ctime_is_ignored () {\n> +\tgit log $1 --format=%ai >authortime &&\n> +\t! grep -v +0000 authortime\n> +}\n\n\nI don't know what I was thinking when I wrote that - it should be called\ntest_atime_is_ignored() as it's testing the author date\n\nBest Wishes\n\nPhillip\n"},{"id":"404028","messageId":"xmqqr1s2vdkq.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"2ad142e6-5f2c-7e05-c8d3-ab6efcfc7058@gmail.com","subject":"Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-08-19T15:51:33Z","receivedAt":"2020-08-19T15:51:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> For am and the sequencer fmt_ident() is in a function which is called\n> from a loop and it is convenient not to have to worry about passing an\n> strbuf around or allocating and freeing it on each function call\n\nThat's strbuf on caller's stack, right?  The actual string pointed\nby the strbuf's buf pointer will be needed and on the heap with or\nwithout the clean-up on top of the patch we are discussing, so I do\nnot think alloc/free would be in the picture when considering the\npros-and-cons.\n\n> The callers in ident (fmt_name(), git_author_info() and\n> git_committer_info()) return the string so they would need their own\n> strbuf or have to be changed so the caller passed one in. There are\n> quite a few callers of those functions and they seem to either\n> immediately call split_ident_line() or duplicate the returned string\n> (mostly the latter).\n>\n> So it would be a bit of work to do it but not an enormous amount\n> (assuming we don't change the signature of git_author_info() etc in\n> ident.c, although given the pattern of callers it might be worth doing\n> that if they are mostly duplicating the returned string anyway)\n\nI'd say that is more than \"while at it\" clean-up.  It would be\neasier to review and slightly easier to do if done before this patch\nintroduces rotating strbuf, but ...\n\n> I'm going to be off line for 10-14 days from the beginning of next week,\n> I could take a look at it after that, or we could leave it for a future\n> improvement - what do you think?\n\n... I can be talked into punting it for later, at least for now.\n\nThanks.\n"},{"id":"404072","messageId":"xmqqo8n6s2fu.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"88535175-0540-c96d-24b5-c4d407422a8c@gmail.com","subject":"Re: [PATCH v8 4/5] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-08-19T22:20:21Z","receivedAt":"2020-08-19T22:20:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>> +# Checking for +0000 in the author date is sufficient since the\n>> +# default timezone is UTC but the timezone used while committing is\n>> +# +0530. The inverted logic in the grep is necessary to check all the\n>> +# author dates in the file.\n>> +test_ctime_is_ignored () {\n>> +\tgit log $1 --format=%ai >authortime &&\n>> +\t! grep -v +0000 authortime\n>> +}\n>\n>\n> I don't know what I was thinking when I wrote that - it should be called\n> test_atime_is_ignored() as it's testing the author date\n\nWill tweak locally.  No need to resend.\n\nThanks.\n"},{"id":"404099","messageId":"975d49a0-de4c-c38f-7928-454c00c90ca2@gmail.com","threadId":"53176","inReplyTo":"xmqqo8n6s2fu.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v8 4/5] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-20T15:16:26Z","receivedAt":"2020-08-20T15:16:35Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 19/08/2020 23:20, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>>> +# Checking for +0000 in the author date is sufficient since the\n>>> +# default timezone is UTC but the timezone used while committing is\n>>> +# +0530. The inverted logic in the grep is necessary to check all the\n>>> +# author dates in the file.\n>>> +test_ctime_is_ignored () {\n>>> +\tgit log $1 --format=%ai >authortime &&\n>>> +\t! grep -v +0000 authortime\n>>> +}\n>>\n>>\n>> I don't know what I was thinking when I wrote that - it should be called\n>> test_atime_is_ignored() as it's testing the author date\n> \n> Will tweak locally.  No need to resend.\n\nThanks for doing that\n\nBest wishes\n\nPhillip\n\n> Thanks.\n> \n"},{"id":"404100","messageId":"8f43c23e-8472-385a-eba7-cafd24505e84@gmail.com","threadId":"53176","inReplyTo":"xmqqr1s2vdkq.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v8 2/5] am: stop exporting GIT_COMMITTER_DATE","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2020-08-20T15:23:33Z","receivedAt":"2020-08-20T15:23:41Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 19/08/2020 16:51, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> For am and the sequencer fmt_ident() is in a function which is called\n>> from a loop and it is convenient not to have to worry about passing an\n>> strbuf around or allocating and freeing it on each function call\n> \n> That's strbuf on caller's stack, right?  The actual string pointed\n> by the strbuf's buf pointer will be needed and on the heap with or\n> without the clean-up on top of the patch we are discussing, so I do\n> not think alloc/free would be in the picture when considering the\n> pros-and-cons.\n\nAt the moment we use the same allocation for the whole program (ignoring \nreallocation if the string grows). If we were to add an strbuf as a \nlocal variable in the function that gets called by the commit picking \nloop we either need to make it static and accept the leak or alloc and \nfree the string each time the function is called. Either way I'd be \namazed if it has any effect on the performance given we're performing a \nmerge with each loop iteration.\n\n>> The callers in ident (fmt_name(), git_author_info() and\n>> git_committer_info()) return the string so they would need their own\n>> strbuf or have to be changed so the caller passed one in. There are\n>> quite a few callers of those functions and they seem to either\n>> immediately call split_ident_line() or duplicate the returned string\n>> (mostly the latter).\n>>\n>> So it would be a bit of work to do it but not an enormous amount\n>> (assuming we don't change the signature of git_author_info() etc in\n>> ident.c, although given the pattern of callers it might be worth doing\n>> that if they are mostly duplicating the returned string anyway)\n> \n> I'd say that is more than \"while at it\" clean-up.  It would be\n> easier to review and slightly easier to do if done before this patch\n> introduces rotating strbuf, but ...\n> \n>> I'm going to be off line for 10-14 days from the beginning of next week,\n>> I could take a look at it after that, or we could leave it for a future\n>> improvement - what do you think?\n> \n> ... I can be talked into punting it for later, at least for now.\n\nI'm tempted to say leave it for now but if this isn't in next by the \ntime I'm back online I'll look at rerolling.\n\nBest Wishes\n\nPhillip\n> \n> Thanks.\n> \n"},{"id":"404554","messageId":"xmqqv9h5t79c.fsf@gitster.c.googlers.com","threadId":"53176","inReplyTo":"20200817174004.92455-4-phillip.wood123@gmail.com","subject":"Re: [PATCH v8 3/5] rebase -i: support --committer-date-is-author-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-08-26T21:41:19Z","receivedAt":"2020-08-26T21:41:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\n> index 4f8a6e51c9..50a63d8ebe 100755\n> --- a/t/t3436-rebase-more-options.sh\n> +++ b/t/t3436-rebase-more-options.sh\n> @@ -9,6 +9,9 @@ test_description='tests to ensure compatibility between am and interactive backe\n>  \n>  . \"$TEST_DIRECTORY\"/lib-rebase.sh\n>  \n> +GIT_AUTHOR_DATE=\"1999-04-02T08:03:20+05:30\"\n> +export GIT_AUTHOR_DATE\n> +\n>  # This is a special case in which both am and interactive backends\n>  # provide the same output. It was done intentionally because\n>  # both the backends fall short of optimal behaviour.\n> @@ -21,11 +24,20 @@ test_expect_success 'setup' '\n>  \ttest_write_lines \"line 1\" \"new line 2\" \"line 3\" >file &&\n>  \tgit commit -am \"update file\" &&\n> + ...\n> +\tmkdir test-bin &&\n> +\twrite_script test-bin/git-merge-test <<-\\EOF\n> +\texec git-merge-recursive \"$@\"\n\nThis should be\n\n\texec git merge-recursive \"$@\"\n\n> +\tEOF\n>  '\n"}]}