{"thread":{"id":"51596","subject":"[GSoC][PATCHl 0/6] rebase -i: support more options","startedAt":"2019-08-06T17:39:50Z","lastAt":"2019-11-28T11:14:29Z","messageCount":96,"participants":["Rohit Ashiwal","Junio C Hamano","Johannes Schindelin","Phillip Wood","Elijah Newren","Alban Gruin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"380023","messageId":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":null,"subject":"[GSoC][PATCHl 0/6] rebase -i: support more options","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-06T17:36:32Z","receivedAt":"2019-08-06T17:39:50Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The previous versions of this patch series were sent here[1]. This patch\naccounts for all the suggestions mentioned there and also introduces a flag\n--ignore-date (also aliased --author-date-is-committer-date).\n\nCaveat:\n\n        The flag --ignore-date (of rebase -am) silently overrides the\n        --committer-date-is-author-date flag. This behaviour is not actually\n        documented. I've made rebase -i to replicate this behaviour anyway.\n\nThanks\nRohit\n\n[1]: https://public-inbox.org/git/20190712185015.20585-1-rohit.ashiwal265@gmail.com/\n\nRohit Ashiwal (6):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: add NULL checks under read_author_script\n  rebase -i: support --committer-date-is-author-date\n  sequencer: rename amend_author to author_to_rename\n  rebase -i: support --ignore-date\n  rebase: add --author-date-is-committer-date\n\n Documentation/git-rebase.txt            |  23 +++--\n builtin/rebase.c                        |  59 +++++++++---\n sequencer.c                             | 114 ++++++++++++++++++++++--\n sequencer.h                             |   2 +\n t/t3422-rebase-incompatible-options.sh  |   2 -\n t/t3433-rebase-options-compatibility.sh | 100 +++++++++++++++++++++\n 6 files changed, 271 insertions(+), 29 deletions(-)\n create mode 100755 t/t3433-rebase-options-compatibility.sh\n\n-- \n2.21.0\n\n"},{"id":"380024","messageId":"20190806173638.17510-2-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-06T17:36:33Z","receivedAt":"2019-08-06T17:39:58Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"There are two backends available for rebasing, viz, the am and the\ninteractive. Naturally, there shall be some features that are\nimplemented in one but not in the other. One such flag is\n--ignore-whitespace which indicates merge mechanism to treat lines\nwith only whitespace changes as unchanged. Wire the interactive\nrebase to also understand the --ignore-whitespace flag by\ntranslating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 10 +++-\n builtin/rebase.c                        | 26 ++++++++--\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n 4 files changed, 95 insertions(+), 7 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 5e4e927647..85404fea52 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -371,8 +371,13 @@ 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 \n --ignore-whitespace::\n+\tThis flag is either passed to the 'git apply' program\n+\t(see linkgit:git-apply[1]), or to 'git merge' program\n+\t(see linkgit:git-merge[1]) as `-Xignore-space-change`,\n+\tdepending on which backend is selected by other options.\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@@ -520,7 +525,6 @@ The following options:\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@@ -543,6 +547,8 @@ 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+ * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex db6ca9bd7d..3c195ddc73 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -79,6 +79,7 @@ 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 \tchar *cmd;\n@@ -97,7 +98,7 @@ struct rebase_options {\n \t\t.git_format_patch_opt = STRBUF_INIT\t\\\n \t}\n \n-static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n+static struct replay_opts get_replay_opts(struct rebase_options *opts)\n {\n \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n \n@@ -114,6 +115,17 @@ 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->ignore_whitespace) {\n+\t\tstruct strbuf buf = STRBUF_INIT;\n+\n+\t\tif (opts->strategy_opts)\n+\t\t\tstrbuf_addstr(&buf, opts->strategy_opts);\n+\n+\t\tstrbuf_addstr(&buf, \" --ignore-space-change\");\n+\t\tfree(opts->strategy_opts);\n+\t\topts->strategy_opts = strbuf_detach(&buf, NULL);\n+\t}\n \tif (opts->strategy_opts)\n \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n \n@@ -511,6 +523,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, NULL, 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@@ -954,6 +968,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@@ -1401,9 +1417,6 @@ 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@@ -1411,6 +1424,8 @@ 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\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@@ -1821,6 +1836,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (options.rebase_merges) {\n+\t\tif (options.ignore_whitespace)\n+\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n+\t\t\t      \"'--ignore-whitespace'\"));\n \t\tif (strategy_options.nr)\n \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n \t\t\t      \"'--strategy-option'\"));\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nnew file mode 100755\nindex 0000000000..e617d3150e\n--- /dev/null\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -0,0 +1,65 @@\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+# 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+\tcat >file <<-EOF &&\n+\tline 1\n+\t        line 2\n+\tline 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_done\n-- \n2.21.0\n\n"},{"id":"380025","messageId":"20190806173638.17510-4-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-06T17:36:35Z","receivedAt":"2019-08-06T17:40:04Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the committer date\nby changing it to the author date. Let's add the same for\ninteractive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            |  8 +++-\n builtin/rebase.c                        | 20 +++++++---\n sequencer.c                             | 52 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 19 +++++++++\n 6 files changed, 91 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 85404fea52..83c5bbe06c 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.\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+\tThis flag is passed to 'git am' to change the author date\n \tof the rebased commits (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n@@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -548,6 +551,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 --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 3c195ddc73..41fe9ebff8 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -82,6 +82,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@@ -113,6 +114,8 @@ static struct replay_opts get_replay_opts(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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -532,6 +535,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n \t\t\t  \"--rebase-merges\"));\n \n+\tif (opts.committer_date_is_author_date)\n+\t\topts.flags |= REBASE_FORCE;\n+\n \treturn !!run_rebase_interactive(&opts, command);\n }\n \n@@ -970,6 +976,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@@ -1417,9 +1425,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@@ -1686,10 +1694,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\ndiff --git a/sequencer.c b/sequencer.c\nindex a2d7b0925e..65adf79222 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -147,6 +147,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@@ -876,6 +877,17 @@ 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 /* Read author-script and return an ident line (author <email> timestamp) */\n static const char *read_author_ident(struct strbuf *buf)\n {\n@@ -904,6 +916,18 @@ static const char *read_author_ident(struct strbuf *buf)\n \treturn buf->buf;\n }\n \n+static int setenv_committer_date_to_author_date(void)\n+{\n+\tint res = 1;\n+\tchar *date = read_author_date_or_null();\n+\n+\tif (date)\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n+\n+\tfree(date);\n+\treturn res;\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@@ -961,6 +985,9 @@ static int run_git_commit(struct repository *r,\n {\n \tstruct child_process cmd = CHILD_PROCESS_INIT;\n \n+\tif (opts->committer_date_is_author_date &&\n+\t    setenv_committer_date_to_author_date())\n+\t\treturn 1;\n \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n \t\tconst char *author = NULL;\n@@ -1397,7 +1424,9 @@ 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) && opts->committer_date_is_author_date &&\n+\t    setenv_committer_date_to_author_date())\n+\t\treturn -1;\n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n \t\tconst char *out_enc = get_commit_output_encoding();\n@@ -1418,6 +1447,17 @@ static int try_to_commit(struct repository *r,\n \t\t\tres = error(_(\"unable to parse commit author\"));\n \t\t\tgoto out;\n \t\t}\n+\t\tif (opts->committer_date_is_author_date) {\n+\t\t\tchar *date;\n+\t\t\tint len = strlen(author);\n+\t\t\tchar *idx = memchr(author, '>', len);\n+\n+\t\t\t++idx;\n+\t\t\tdate = malloc(author + len - idx);\n+\t\t\tmemcpy(date, idx, author + len - idx);\n+\t\t\tsetenv(\"GIT_COMMITTER_DATE\", date, 1);\n+\t\t\tfree(date);\n+\t\t}\n \t\tparents = copy_commit_list(current_head->parents);\n \t\textra = read_commit_extra_headers(current_head, exclude_gpgsig);\n \t} else if (current_head) {\n@@ -2538,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@@ -2620,6 +2665,8 @@ 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->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3708,7 +3755,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 0c494b83d4..e6cba468db 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex e617d3150e..ceab48a831 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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@@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n \ttest_cmp expect file\n '\n \n+test_expect_success '--committer-date-is-author-date works with am backend' '\n+\tgit rebase -f HEAD^ &&\n+\tgit rebase --committer-date-is-author-date HEAD^ &&\n+\tgit show HEAD --pretty=\"format:%at\" >authortime &&\n+\tgit show HEAD --pretty=\"format:%ct\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n+test_expect_success '--committer-date-is-author-date works with interactive backend' '\n+\tgit rebase -f HEAD^ &&\n+\tgit rebase -i --committer-date-is-author-date HEAD^ &&\n+\tgit show HEAD --pretty=\"format:%at\" >authortime &&\n+\tgit show HEAD --pretty=\"format:%ct\" >committertime &&\n+\ttest_cmp authortime committertime\n+'\n+\n test_done\n-- \n2.21.0\n\n"},{"id":"380026","messageId":"20190806173638.17510-3-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCHl 2/6] sequencer: add NULL checks under read_author_script","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-06T17:36:34Z","receivedAt":"2019-08-06T17:40:06Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"read_author_script reads name, email and author date from the author\nscript. However, it does not check if the arguments are NULL. Adding\nNULL checks will allow us to selectively get the required value, for\nexample:\n\n    char *date;\n    if (read_author_script(_path_, NULL, NULL, &date, _int_))\n\t    die(_(\"failed to read author date\"));\n    /* needs to be free()'d */\n    return date;\n\nAdd NULL checks for better control over the information retrieved.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 16 +++++++++++++---\n 1 file changed, 13 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex f88a97fb10..a2d7b0925e 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -821,9 +821,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-- \n2.21.0\n\n"},{"id":"380027","messageId":"20190806173638.17510-5-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-06T17:36:36Z","receivedAt":"2019-08-06T17:40:09Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The purpose of amend_author was to free() the malloc()'d string\nobtained from get_author(). But the name does not actually convey\nthis purpose. Rename it to something meaningful.\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 65adf79222..d24a6fd585 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1417,7 +1417,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@@ -1441,7 +1441,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@@ -1526,7 +1526,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.21.0\n\n"},{"id":"380028","messageId":"20190806173638.17510-6-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCHl 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-06T17:36:37Z","receivedAt":"2019-08-06T17:40:14Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the author date\nby changing it to the committer (current) date. Let's add the same\nfor interactive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            |  6 ++--\n builtin/rebase.c                        | 17 +++++----\n sequencer.c                             | 48 ++++++++++++++++++++++---\n sequencer.h                             |  1 +\n t/t3433-rebase-options-compatibility.sh | 16 +++++++++\n 5 files changed, 74 insertions(+), 14 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 83c5bbe06c..a5cdf8518b 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tLie about the author date by re-setting it to the value\n+\tsame as committer (current) date. This implies --force-rebase.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:\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  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 41fe9ebff8..7f464fc9ba 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -83,6 +83,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@@ -116,6 +117,7 @@ static struct replay_opts get_replay_opts(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@@ -535,7 +537,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n \t\t\t  \"--rebase-merges\"));\n \n-\tif (opts.committer_date_is_author_date)\n+\tif (opts.committer_date_is_author_date ||\n+\t    opts.ignore_date)\n \t\topts.flags |= REBASE_FORCE;\n \n \treturn !!run_rebase_interactive(&opts, command);\n@@ -978,6 +981,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@@ -1428,8 +1433,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@@ -1694,13 +1699,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+\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, \"--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 d24a6fd585..c882dc5d5f 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -148,6 +148,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@@ -928,6 +929,17 @@ static int setenv_committer_date_to_author_date(void)\n \treturn res;\n }\n \n+static void ignore_author_date(const char **author)\n+{\n+\tstruct strbuf new_author = STRBUF_INIT;\n+\tchar *idx = memchr(*author, '>', strlen(*author));\n+\n+\tstrbuf_add(&new_author, *author, idx - *author);\n+\tstrbuf_addstr(&new_author, \"> \");\n+\tdatestamp(&new_author);\n+\t*author = 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@@ -985,7 +997,7 @@ static int run_git_commit(struct repository *r,\n {\n \tstruct child_process cmd = CHILD_PROCESS_INIT;\n \n-\tif (opts->committer_date_is_author_date &&\n+\tif (opts->committer_date_is_author_date && !opts->ignore_date &&\n \t    setenv_committer_date_to_author_date())\n \t\treturn 1;\n \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n@@ -1013,10 +1025,18 @@ static int run_git_commit(struct repository *r,\n \n \t\tif (res <= 0)\n \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n-\t\telse\n+\t\telse {\n+\t\t\tif (opts->ignore_date) {\n+\t\t\t\tif (!author)\n+\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n+\t\t\t\t\t    \"rebase -i, which must set the \"\n+\t\t\t\t\t    \"author before committing the tree\");\n+\t\t\t\tignore_author_date(&author);\n+\t\t\t}\n \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n \t\t\t\t\t  NULL, &root_commit, author,\n \t\t\t\t\t  opts->gpg_sign);\n+\t\t}\n \n \t\tstrbuf_release(&msg);\n \t\tstrbuf_release(&script);\n@@ -1046,6 +1066,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\targv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n \tif (defmsg)\n \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n \telse if (!(flags & EDIT_MSG))\n@@ -1425,7 +1447,7 @@ static int try_to_commit(struct repository *r,\n \tif (parse_head(r, &current_head))\n \t\treturn -1;\n \tif (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&\n-\t    setenv_committer_date_to_author_date())\n+\t    !opts->ignore_date && setenv_committer_date_to_author_date())\n \t\treturn -1;\n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n@@ -1447,7 +1469,7 @@ static int try_to_commit(struct repository *r,\n \t\t\tres = error(_(\"unable to parse commit author\"));\n \t\t\tgoto out;\n \t\t}\n-\t\tif (opts->committer_date_is_author_date) {\n+\t\tif (opts->committer_date_is_author_date && !opts->ignore_date) {\n \t\t\tchar *date;\n \t\t\tint len = strlen(author);\n \t\t\tchar *idx = memchr(author, '>', len);\n@@ -1507,6 +1529,11 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tignore_author_date(&author);\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@@ -2583,6 +2610,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@@ -2667,6 +2699,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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@@ -3484,6 +3518,9 @@ 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\targv_array_pushf(&cmd.args,\n+\t\t\t\t\t \"GIT_AUTHOR_DATE=%ld\", time(NULL));\n \n \t\t/* Add the tips to be merged */\n \t\tfor (j = to_merge; j; j = j->next)\n@@ -3756,7 +3793,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 e6cba468db..73d0515a3e 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex ceab48a831..95d99c4b7b 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n \ttest_cmp authortime committertime\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 test_done\n-- \n2.21.0\n\n"},{"id":"380029","messageId":"20190806173638.17510-7-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-06T17:36:38Z","receivedAt":"2019-08-06T17:40:18Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The previous commit introduced --ignore-date flag to interactive\nrebase, but the name is actually very vague in context of rebase -i\nsince there are two dates we can work with. Add an alias to convey\nthe precise purpose.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt | 1 +\n builtin/rebase.c             | 2 ++\n 2 files changed, 3 insertions(+)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex a5cdf8518b..bb60426911 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -388,6 +388,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n+--author-date-is-committer-date::\n \tLie about the author date by re-setting it to the value\n \tsame as committer (current) date. This implies --force-rebase.\n +\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 7f464fc9ba..a9a42f9ee4 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1433,6 +1433,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_BOOL(0, \"author-date-is-committer-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current 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_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n-- \n2.21.0\n\n"},{"id":"380058","messageId":"xmqqimr9ilha.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20190806173638.17510-2-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-07T05:38:09Z","receivedAt":"2019-08-07T05:38:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index db6ca9bd7d..3c195ddc73 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> ...\n> @@ -511,6 +523,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>  \targc = parse_options(argc, argv, NULL, options,\n>  \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n\nCurious.  Did you rebase onto an older codebase?  I think the round\ncurrently queued in my tree already has c0e78f7e46 which merged the\njk/unused-params-final-batch topic that updated this call to\nparse_options() to pass prefix.  Perhaps you want to fetch from me\nwhat has been on 'pu' (it should be \"log master..10827432\") and\ncompare what you had?  Unless there is no compelling reason not to,\nit would be a good idea to base the reroll on the same commit as\nthe commit on which the previous version has been queued, which in\nthis case is 9c9b961d (\"The sixth batch\", 2019-07-19).\n\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..e617d3150e\n> --- /dev/null\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -0,0 +1,65 @@\n> ...\n> +\n> +\tgit checkout --orphan master &&\n> +\tcat >file <<-EOF &&\n> +\tline 1\n> +\t        line 2\n> +\tline 3\n> +\tEOF\n\nThe second line triggers \"indent with spaces\" whitespace error; you\ncan protect these spaces in the leading indent like so:\n\n\tsed -e \"s/^|//\" <<-\\EOF &&\n\t|line 1\n\t|        line 2\n\t|line 3\n\tEOF\n\nAlso make it a habit to always quote the EOF token that begins the\nhere document (i.e. <<-\\EOF) when the here document does not need\nvariable interpolation.  I suspect (but I did not read all of the\ntests) that there may be many other instances of here document in\nthis patch that can use the same improvement.\n\nThanks.\n"},{"id":"380093","messageId":"nycvar.QRO.7.76.6.1908072139190.46@tvgsbejvaqbjf.bet","threadId":"51596","inReplyTo":"20190806173638.17510-6-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-08-07T19:41:31Z","receivedAt":"2019-08-07T19:41:56Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Rohit,\n\nOn Tue, 6 Aug 2019, Rohit Ashiwal wrote:\n\n> @@ -1046,6 +1066,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\targv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n>  \tif (defmsg)\n>  \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>  \telse if (!(flags & EDIT_MSG))\n\nI need this patch to make the code _at least_ compile on Windows again\n(I don't know whether it breaks the test suite yet):\n\n-- snipsnap --\nSubject: [PATCH] fixup! rebase -i: support --ignore-date\n\nIt is a mistake to believe that the return value of `time()` is always\nan `unsigned long`.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n sequencer.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 539c0ef601b..a4c932d3407 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1070,7 +1070,8 @@ static int run_git_commit(struct repository *r,\n \tif (opts->gpg_sign)\n \t\targv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n \tif (opts->ignore_date)\n-\t\targv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n+\t\targv_array_pushf(&cmd.args, \"--date=%\"PRIuMAX,\n+\t\t\t\t (uintmax_t)time(NULL));\n \tif (defmsg)\n \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n \telse if (!(flags & EDIT_MSG))\n@@ -3642,7 +3643,8 @@ static int do_merge(struct repository *r,\n \t\t\targv_array_push(&cmd.args, opts->gpg_sign);\n \t\tif (opts->ignore_date)\n \t\t\targv_array_pushf(&cmd.args,\n-\t\t\t\t\t \"GIT_AUTHOR_DATE=%ld\", time(NULL));\n+\t\t\t\t\t \"GIT_AUTHOR_DATE=%\"PRIuMAX,\n+\t\t\t\t\t (uintmax_t)time(NULL));\n\n \t\t/* Add the tips to be merged */\n \t\tfor (j = to_merge; j; j = j->next)\n--\n2.22.0.windows.1.6.g271c090e89\n\n"},{"id":"380094","messageId":"xmqqimr8hgjl.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"nycvar.QRO.7.76.6.1908072139190.46@tvgsbejvaqbjf.bet","subject":"Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-07T20:22:22Z","receivedAt":"2019-08-07T20:22:28Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Tue, 6 Aug 2019, Rohit Ashiwal wrote:\n>\n>> @@ -1046,6 +1066,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\targv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n>>  \tif (defmsg)\n>>  \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>>  \telse if (!(flags & EDIT_MSG))\n>\n> I need this patch to make the code _at least_ compile on Windows again\n> (I don't know whether it breaks the test suite yet):\n>\n> -- snipsnap --\n> Subject: [PATCH] fixup! rebase -i: support --ignore-date\n>\n> It is a mistake to believe that the return value of `time()` is always\n> an `unsigned long`.\n\nGood catch.  We can at least expect it to be some integral type ;-)\n\nWith or without this fix-up, I think the patch is still not quite\nright.  Output from time() formatted as an integer is a string of\ndigits, and the side that reads that string and interprets it as a\ntimestamp does so by calling parse_date(); it is up to that function\nto decide what datestring format it is in, and it does not\nnecessarily take it as seconds since epoch.  It is safer to force\nthe \"seconds since epoch\" interpretation by writing the timestamp\nstring like so:\n\n\targv_array_pushf(&args, \"--date=@%ld\", time(NULL));\n\nSee 14ac2864 (\"commit: accept more date formats for \"--date\"\",\n2014-05-01), which gives a good hint on how to do this right, and\n2c733fb2 (\"parse_date(): '@' prefix forces git-timestamp\",\n2012-02-02) for a backstory.\n\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n>  sequencer.c | 6 ++++--\n>  1 file changed, 4 insertions(+), 2 deletions(-)\n>\n> diff --git a/sequencer.c b/sequencer.c\n> index 539c0ef601b..a4c932d3407 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -1070,7 +1070,8 @@ static int run_git_commit(struct repository *r,\n>  \tif (opts->gpg_sign)\n>  \t\targv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n>  \tif (opts->ignore_date)\n> -\t\targv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n> +\t\targv_array_pushf(&cmd.args, \"--date=%\"PRIuMAX,\n> +\t\t\t\t (uintmax_t)time(NULL));\n>  \tif (defmsg)\n>  \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>  \telse if (!(flags & EDIT_MSG))\n> @@ -3642,7 +3643,8 @@ static int do_merge(struct repository *r,\n>  \t\t\targv_array_push(&cmd.args, opts->gpg_sign);\n>  \t\tif (opts->ignore_date)\n>  \t\t\targv_array_pushf(&cmd.args,\n> -\t\t\t\t\t \"GIT_AUTHOR_DATE=%ld\", time(NULL));\n> +\t\t\t\t\t \"GIT_AUTHOR_DATE=%\"PRIuMAX,\n> +\t\t\t\t\t (uintmax_t)time(NULL));\n>\n>  \t\t/* Add the tips to be merged */\n>  \t\tfor (j = to_merge; j; j = j->next)\n> --\n> 2.22.0.windows.1.6.g271c090e89\n"},{"id":"380096","messageId":"CAL7ArXp04YM9chfrzGBzy1szxuqNuSeRmPYc35s3ZiJjoZaCQA@mail.gmail.com","threadId":"51596","inReplyTo":"xmqqimr9ilha.fsf@gitster-ct.c.googlers.com","subject":"Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-07T20:25:30Z","receivedAt":"2019-08-07T20:26:14Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Hi Junio\n\nOn Wed, Aug 7, 2019 at 11:08 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n>\n> > diff --git a/builtin/rebase.c b/builtin/rebase.c\n> > index db6ca9bd7d..3c195ddc73 100644\n> > --- a/builtin/rebase.c\n> > +++ b/builtin/rebase.c\n> > ...\n> > @@ -511,6 +523,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n> >       argc = parse_options(argc, argv, NULL, options,\n> >                       builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n>\n> Curious.  Did you rebase onto an older codebase?  I think the round\n> currently queued in my tree already has c0e78f7e46 which merged the\n> jk/unused-params-final-batch topic that updated this call to\n> parse_options() to pass prefix.  Perhaps you want to fetch from me\n> what has been on 'pu' (it should be \"log master..10827432\") and\n> compare what you had?  Unless there is no compelling reason not to,\n> it would be a good idea to base the reroll on the same commit as\n> the commit on which the previous version has been queued, which in\n> this case is 9c9b961d (\"The sixth batch\", 2019-07-19).\n\nOh~ I didn't notice it. I'll rebase and re send the patch. Thanks for\npointing out.\n\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..e617d3150e\n> > --- /dev/null\n> > +++ b/t/t3433-rebase-options-compatibility.sh\n> > @@ -0,0 +1,65 @@\n> > ...\n> > +\n> > +     git checkout --orphan master &&\n> > +     cat >file <<-EOF &&\n> > +     line 1\n> > +             line 2\n> > +     line 3\n> > +     EOF\n>\n> The second line triggers \"indent with spaces\" whitespace error; you\n> can protect these spaces in the leading indent like so:\n>\n>         sed -e \"s/^|//\" <<-\\EOF &&\n>         |line 1\n>         |        line 2\n>         |line 3\n>         EOF\n>\n> Also make it a habit to always quote the EOF token that begins the\n> here document (i.e. <<-\\EOF) when the here document does not need\n> variable interpolation.  I suspect (but I did not read all of the\n> tests) that there may be many other instances of here document in\n> this patch that can use the same improvement.\n\nWill keep this in mind.\n\nThanks\nRohit\n"},{"id":"380097","messageId":"CAL7ArXoaZU2zPq=nLRghwY+Rj1HPKtTXqaOF75b406iybX9bqw@mail.gmail.com","threadId":"51596","inReplyTo":"xmqqimr8hgjl.fsf@gitster-ct.c.googlers.com","subject":"Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-07T20:33:14Z","receivedAt":"2019-08-07T20:33:57Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Hi Junio and Dscho\n\nOn Thu, Aug 8, 2019 at 1:52 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>\n> > On Tue, 6 Aug 2019, Rohit Ashiwal wrote:\n> >\n> >> @@ -1046,6 +1066,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> >> +            argv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n> >>      if (defmsg)\n> >>              argv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n> >>      else if (!(flags & EDIT_MSG))\n> >\n> > I need this patch to make the code _at least_ compile on Windows again\n> > (I don't know whether it breaks the test suite yet):\n> >\n> > -- snipsnap --\n> > Subject: [PATCH] fixup! rebase -i: support --ignore-date\n> >\n> > It is a mistake to believe that the return value of `time()` is always\n> > an `unsigned long`.\n>\n> Good catch.  We can at least expect it to be some integral type ;-)\n>\n> With or without this fix-up, I think the patch is still not quite\n> right.  Output from time() formatted as an integer is a string of\n> digits, and the side that reads that string and interprets it as a\n> timestamp does so by calling parse_date(); it is up to that function\n> to decide what datestring format it is in, and it does not\n> necessarily take it as seconds since epoch.  It is safer to force\n> the \"seconds since epoch\" interpretation by writing the timestamp\n> string like so:\n>\n>         argv_array_pushf(&args, \"--date=@%ld\", time(NULL));\n>\n> See 14ac2864 (\"commit: accept more date formats for \"--date\"\",\n> 2014-05-01), which gives a good hint on how to do this right, and\n> 2c733fb2 (\"parse_date(): '@' prefix forces git-timestamp\",\n> 2012-02-02) for a backstory.\n>\n> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> > ---\n> >  sequencer.c | 6 ++++--\n> >  1 file changed, 4 insertions(+), 2 deletions(-)\n> >\n> > diff --git a/sequencer.c b/sequencer.c\n> > index 539c0ef601b..a4c932d3407 100644\n> > --- a/sequencer.c\n> > +++ b/sequencer.c\n> > @@ -1070,7 +1070,8 @@ static int run_git_commit(struct repository *r,\n> >       if (opts->gpg_sign)\n> >               argv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n> >       if (opts->ignore_date)\n> > -             argv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n> > +             argv_array_pushf(&cmd.args, \"--date=%\"PRIuMAX,\n> > +                              (uintmax_t)time(NULL));\n> >       if (defmsg)\n> >               argv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n> >       else if (!(flags & EDIT_MSG))\n> > @@ -3642,7 +3643,8 @@ static int do_merge(struct repository *r,\n> >                       argv_array_push(&cmd.args, opts->gpg_sign);\n> >               if (opts->ignore_date)\n> >                       argv_array_pushf(&cmd.args,\n> > -                                      \"GIT_AUTHOR_DATE=%ld\", time(NULL));\n> > +                                      \"GIT_AUTHOR_DATE=%\"PRIuMAX,\n> > +                                      (uintmax_t)time(NULL));\n> >\n> >               /* Add the tips to be merged */\n> >               for (j = to_merge; j; j = j->next)\n> > --\n> > 2.22.0.windows.1.6.g271c090e89\n\nThanks for suggestions, I'll incorporate these changes along\nwith changes suggested by Junio and re-send the patch.\n\n- Rohit\n"},{"id":"380118","messageId":"e2ce49a2-3681-23a8-baad-5dfcea7cbe77@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-4-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-08T11:29:20Z","receivedAt":"2019-08-08T11:29:27Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 06/08/2019 18:36, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            |  8 +++-\n>   builtin/rebase.c                        | 20 +++++++---\n>   sequencer.c                             | 52 ++++++++++++++++++++++++-\n>   sequencer.h                             |  1 +\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++\n>   6 files changed, 91 insertions(+), 10 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 85404fea52..83c5bbe06c 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.\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> +\tThis flag is passed to 'git am' to change the author date\n>   \tof the rebased commits (see linkgit:git-am[1]).\n>   +\n>   See also INCOMPATIBLE OPTIONS below.\n> @@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --committer-date-is-author-date\n>    * --ignore-date\n>    * --whitespace\n>    * -C\n> @@ -548,6 +551,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 --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 3c195ddc73..41fe9ebff8 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -82,6 +82,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> @@ -113,6 +114,8 @@ static struct replay_opts get_replay_opts(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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>   \treplay.strategy = opts->strategy;\n>   \n> @@ -532,6 +535,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>   \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n>   \t\t\t  \"--rebase-merges\"));\n>   \n> +\tif (opts.committer_date_is_author_date)\n> +\t\topts.flags |= REBASE_FORCE;\n> +\n>   \treturn !!run_rebase_interactive(&opts, command);\n>   }\n>   \n> @@ -970,6 +976,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> @@ -1417,9 +1425,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> @@ -1686,10 +1694,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\n> diff --git a/sequencer.c b/sequencer.c\n> index a2d7b0925e..65adf79222 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -147,6 +147,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> @@ -876,6 +877,17 @@ 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>   /* Read author-script and return an ident line (author <email> timestamp) */\n>   static const char *read_author_ident(struct strbuf *buf)\n>   {\n> @@ -904,6 +916,18 @@ static const char *read_author_ident(struct strbuf *buf)\n>   \treturn buf->buf;\n>   }\n>   \n> +static int setenv_committer_date_to_author_date(void)\n> +{\n> +\tint res = 1;\n\nIn the git codebase it is conventional to return -1 for an error\n\n> +\tchar *date = read_author_date_or_null();\n> +\n> +\tif (date)\n> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n> +\n> +\tfree(date);\n> +\treturn res;\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> @@ -961,6 +985,9 @@ static int run_git_commit(struct repository *r,\n>   {\n>   \tstruct child_process cmd = CHILD_PROCESS_INIT;\n>   \n> +\tif (opts->committer_date_is_author_date &&\n> +\t    setenv_committer_date_to_author_date())\n> +\t\treturn 1;\n\n-1 for errors please, as seen in the surrounding code.\n\n>   \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n>   \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n>   \t\tconst char *author = NULL;\n> @@ -1397,7 +1424,9 @@ 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) && opts->committer_date_is_author_date &&\n> +\t    setenv_committer_date_to_author_date())\n> +\t\treturn -1;\n\nI think it would be better to handle committer_date_is_author_date in a \nsingle place in this function, not have two implementations one of which \nis untested as shown in Stolee's latest test email. This function \nreceives the author as a string so it should work with the author string \nonce we have checked for amend.\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> @@ -1418,6 +1447,17 @@ static int try_to_commit(struct repository *r,\n>   \t\t\tres = error(_(\"unable to parse commit author\"));\n>   \t\t\tgoto out;\n>   \t\t}\n> +\t\tif (opts->committer_date_is_author_date) {\n> +\t\t\tchar *date;\n> +\t\t\tint len = strlen(author);\n> +\t\t\tchar *idx = memchr(author, '>', len);\n\nwhat happens if there is a corrupted author without an email?  - We end \nup with undefined behavior.\n\n> +\n> +\t\t\t++idx;\n> +\t\t\tdate = malloc(author + len - idx);\n> +\t\t\tmemcpy(date, idx, author + len - idx);\n> +\t\t\tsetenv(\"GIT_COMMITTER_DATE\", date, 1);\n> +\t\t\tfree(date);\n\ngit has a high level api for manipulation author/committer information \nin ident.c, it would be best to use that. In any case code like this \nshould be using strbuf's rather than malloc\n\n> +\t\t}\n>   \t\tparents = copy_commit_list(current_head->parents);\n>   \t\textra = read_commit_extra_headers(current_head, exclude_gpgsig);\n>   \t} else if (current_head) {\n\nDo the committer_date_is_author_date check after the end of this if.\n\nBest Wishes\n\nPhillip\n\n> @@ -2538,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> @@ -2620,6 +2665,8 @@ 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->reschedule_failed_exec)\n>   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>   \n> @@ -3708,7 +3755,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 0c494b83d4..e6cba468db 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index e617d3150e..ceab48a831 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\n>   \ttest_cmp expect file\n>   '\n>   \n> +test_expect_success '--committer-date-is-author-date works with am backend' '\n> +\tgit rebase -f HEAD^ &&\n> +\tgit rebase --committer-date-is-author-date HEAD^ &&\n> +\tgit show HEAD --pretty=\"format:%at\" >authortime &&\n> +\tgit show HEAD --pretty=\"format:%ct\" >committertime &&\n> +\ttest_cmp authortime committertime\n> +'\n> +\n> +test_expect_success '--committer-date-is-author-date works with interactive backend' '\n> +\tgit rebase -f HEAD^ &&\n> +\tgit rebase -i --committer-date-is-author-date HEAD^ &&\n> +\tgit show HEAD --pretty=\"format:%at\" >authortime &&\n> +\tgit show HEAD --pretty=\"format:%ct\" >committertime &&\n> +\ttest_cmp authortime committertime\n> +'\n> +\n>   test_done\n> \n"},{"id":"380119","messageId":"58e6840a-224a-8276-a376-a0f52a45e4d5@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-5-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCHl 4/6] sequencer: rename amend_author to author_to_rename","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-08T11:30:14Z","receivedAt":"2019-08-08T11:30:19Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 06/08/2019 18:36, Rohit Ashiwal wrote:\n> The purpose of amend_author was to free() the malloc()'d string\n> obtained from get_author(). But the name does not actually convey\n> this purpose. Rename it to something meaningful.\n\nThe name was intended to covey that it was only used when amending a \ncommit, I'm fine with the rename though.\n\nBest Wishes\n\nPhillip\n\n> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   sequencer.c | 6 +++---\n>   1 file changed, 3 insertions(+), 3 deletions(-)\n> \n> diff --git a/sequencer.c b/sequencer.c\n> index 65adf79222..d24a6fd585 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -1417,7 +1417,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> @@ -1441,7 +1441,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> @@ -1526,7 +1526,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> \n"},{"id":"380121","messageId":"0619f7b7-a7e5-54a2-3d28-ac359139bde7@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-6-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-08T11:42:19Z","receivedAt":"2019-08-08T11:42:25Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"\n\nOn 06/08/2019 18:36, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            |  6 ++--\n>   builtin/rebase.c                        | 17 +++++----\n>   sequencer.c                             | 48 ++++++++++++++++++++++---\n>   sequencer.h                             |  1 +\n>   t/t3433-rebase-options-compatibility.sh | 16 +++++++++\n>   5 files changed, 74 insertions(+), 14 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 83c5bbe06c..a5cdf8518b 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.\n>   \tas the committer date. This implies --force-rebase.\n>   \n>   --ignore-date::\n> -\tThis flag is passed to 'git am' to change the author date\n> -\tof the rebased commits (see linkgit:git-am[1]).\n> +\tLie about the author date by re-setting it to the value\n> +\tsame as committer (current) date. This implies --force-rebase.\n\nI'm not keen on talking about lying with the implication of deceit. Just \nsay that this resets the author date, there are perfectly legitimate \nreasons to do this.\n\n>   +\n>   See also INCOMPATIBLE OPTIONS below.\n>   \n> @@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --ignore-date\n>    * --whitespace\n>    * -C\n>   \n> @@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:\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>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 41fe9ebff8..7f464fc9ba 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -83,6 +83,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> @@ -116,6 +117,7 @@ static struct replay_opts get_replay_opts(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> @@ -535,7 +537,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>   \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n>   \t\t\t  \"--rebase-merges\"));\n>   \n> -\tif (opts.committer_date_is_author_date)\n> +\tif (opts.committer_date_is_author_date ||\n> +\t    opts.ignore_date)\n>   \t\topts.flags |= REBASE_FORCE;\n>   \n>   \treturn !!run_rebase_interactive(&opts, command);\n> @@ -978,6 +981,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> @@ -1428,8 +1433,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> @@ -1694,13 +1699,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> +\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, \"--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)) {\n> diff --git a/sequencer.c b/sequencer.c\n> index d24a6fd585..c882dc5d5f 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -148,6 +148,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> @@ -928,6 +929,17 @@ static int setenv_committer_date_to_author_date(void)\n>   \treturn res;\n>   }\n>   \n> +static void ignore_author_date(const char **author)\n> +{\n> +\tstruct strbuf new_author = STRBUF_INIT;\n> +\tchar *idx = memchr(*author, '>', strlen(*author));\n\nstrchr? I'd be happy to see this using the functions in ident.c which \ncheck the author is formatted correctly, as it stands this code will \nhappily continue if idx == NULL.\n\n> +\n> +\tstrbuf_add(&new_author, *author, idx - *author);\n> +\tstrbuf_addstr(&new_author, \"> \");\n> +\tdatestamp(&new_author);\n> +\t*author = 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> @@ -985,7 +997,7 @@ static int run_git_commit(struct repository *r,\n>   {\n>   \tstruct child_process cmd = CHILD_PROCESS_INIT;\n>   \n> -\tif (opts->committer_date_is_author_date &&\n> +\tif (opts->committer_date_is_author_date && !opts->ignore_date &&\n>   \t    setenv_committer_date_to_author_date())\n>   \t\treturn 1;\n\nWe read the author script again just below, can set the committer date \nthere by parsing the author string, that would mean you could use the \nsame function that works on an author string in try_to_commit() (this \ncomment should be on patch 3 I think)\n\n>   \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n> @@ -1013,10 +1025,18 @@ static int run_git_commit(struct repository *r,\n>   \n>   \t\tif (res <= 0)\n>   \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n> -\t\telse\n> +\t\telse {\n> +\t\t\tif (opts->ignore_date) {\n> +\t\t\t\tif (!author)\n> +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n> +\t\t\t\t\t    \"rebase -i, which must set the \"\n\nI know it's only a bug message but it's not just 'rebase -i' but 'rebase \n-k', 'rebase -m' ... that use this code path, it would be better just to \nsay 'rebase'\n\n> +\t\t\t\t\t    \"author before committing the tree\");\n> +\t\t\t\tignore_author_date(&author);\n> +\t\t\t}\n>   \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n>   \t\t\t\t\t  NULL, &root_commit, author,\n>   \t\t\t\t\t  opts->gpg_sign);\n> +\t\t}\n>   \n>   \t\tstrbuf_release(&msg);\n>   \t\tstrbuf_release(&script);\n> @@ -1046,6 +1066,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\targv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n\nI think this is racy as it only sets the author date, the committer date \nmay end up being different.\n\n>   \tif (defmsg)\n>   \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>   \telse if (!(flags & EDIT_MSG))\n> @@ -1425,7 +1447,7 @@ static int try_to_commit(struct repository *r,\n>   \tif (parse_head(r, &current_head))\n>   \t\treturn -1;\n>   \tif (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&\n> -\t    setenv_committer_date_to_author_date())\n> +\t    !opts->ignore_date && setenv_committer_date_to_author_date())\n>   \t\treturn -1;\n>   \tif (flags & AMEND_MSG) {\n>   \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n> @@ -1447,7 +1469,7 @@ static int try_to_commit(struct repository *r,\n>   \t\t\tres = error(_(\"unable to parse commit author\"));\n>   \t\t\tgoto out;\n>   \t\t}\n> -\t\tif (opts->committer_date_is_author_date) {\n> +\t\tif (opts->committer_date_is_author_date && !opts->ignore_date) {\n\nIf we only handled committer_date_is_author_date in a single place it \nwouldn't need to be changed twice in this patch\n\n>   \t\t\tchar *date;\n>   \t\t\tint len = strlen(author);\n>   \t\t\tchar *idx = memchr(author, '>', len);\n> @@ -1507,6 +1529,11 @@ static int try_to_commit(struct repository *r,\n>   \n>   \treset_ident_date();\n>   \n> +\tif (opts->ignore_date) {\n> +\t\tignore_author_date(&author);\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> @@ -2583,6 +2610,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> @@ -2667,6 +2699,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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> @@ -3484,6 +3518,9 @@ 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\targv_array_pushf(&cmd.args,\n> +\t\t\t\t\t \"GIT_AUTHOR_DATE=%ld\", time(NULL));\n>   \n>   \t\t/* Add the tips to be merged */\n>   \t\tfor (j = to_merge; j; j = j->next)\n> @@ -3756,7 +3793,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 e6cba468db..73d0515a3e 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index ceab48a831..95d99c4b7b 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n>   \ttest_cmp authortime committertime\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\nThat sounds potentially fragile but I guess the timezone is unlikely to \nchange in the future\n\nBest Wishes\n\nPhillip\n\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>   test_done\n> \n"},{"id":"380122","messageId":"0631044f-48ad-ad55-b256-cf500fc144cb@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-7-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCHl 6/6] rebase: add --author-date-is-committer-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-08T11:42:51Z","receivedAt":"2019-08-08T11:42:56Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 06/08/2019 18:36, Rohit Ashiwal wrote:\n> The previous commit introduced --ignore-date flag to interactive\n> rebase, but the name is actually very vague in context of rebase -i\n> since there are two dates we can work with. Add an alias to convey\n> the precise purpose.\n\nThat's an excellent idea\n\nBest Wishes\n\nPhillip\n\n> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt | 1 +\n>   builtin/rebase.c             | 2 ++\n>   2 files changed, 3 insertions(+)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index a5cdf8518b..bb60426911 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -388,6 +388,7 @@ See also INCOMPATIBLE OPTIONS below.\n>   \tas the committer date. This implies --force-rebase.\n>   \n>   --ignore-date::\n> +--author-date-is-committer-date::\n>   \tLie about the author date by re-setting it to the value\n>   \tsame as committer (current) date. This implies --force-rebase.\n>   +\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 7f464fc9ba..a9a42f9ee4 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -1433,6 +1433,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_BOOL(0, \"author-date-is-committer-date\", &options.ignore_date,\n> +\t\t\t \"ignore author date and use current 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_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n> \n"},{"id":"380142","messageId":"xmqqwofnfy0r.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"e2ce49a2-3681-23a8-baad-5dfcea7cbe77@gmail.com","subject":"Re: [GSoC][PATCHl 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-08T16:00:04Z","receivedAt":"2019-08-08T16:00:10Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> ...\n> I think it would be better to handle committer_date_is_author_date in\n> a single place in this function, not have two implementations one of\n> ...\n> git has a high level api for manipulation author/committer information\n> in ident.c, it would be best to use that. In any case code like this\n> should be using strbuf's rather than malloc\n> ...\n> Do the committer_date_is_author_date check after the end of this if.\n>\n> Best Wishes\n>\n> Phillip\n\nI've read all your review comments for this round, and they all\ncover good points.  Thanks for a good reviewer and a mentor.  After\nreading the patches myself, I have little to add ;-)\n"},{"id":"380143","messageId":"bdd867f3-62d6-eec2-9562-5dbe203f49b5@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-2-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-08T16:44:38Z","receivedAt":"2019-08-08T16:44:45Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 06/08/2019 18:36, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            | 10 +++-\n>   builtin/rebase.c                        | 26 ++++++++--\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n>   4 files changed, 95 insertions(+), 7 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 5e4e927647..85404fea52 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -371,8 +371,13 @@ 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>   \n>   --ignore-whitespace::\n> +\tThis flag is either passed to the 'git apply' program\n> +\t(see linkgit:git-apply[1]), or to 'git merge' program\n> +\t(see linkgit:git-merge[1]) as `-Xignore-space-change`,\n> +\tdepending on which backend is selected by other options.\n\nI think it would be better to document the effect of this option rather \nthan the implementation detail. It is confusing at the moment as it \ntalks about 'git merge' but we don't allow this option with merges.\n\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> @@ -520,7 +525,6 @@ The following options:\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> @@ -543,6 +547,8 @@ 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> + * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n>   \n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index db6ca9bd7d..3c195ddc73 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -79,6 +79,7 @@ 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>   \tchar *cmd;\n> @@ -97,7 +98,7 @@ struct rebase_options {\n>   \t\t.git_format_patch_opt = STRBUF_INIT\t\\\n>   \t}\n>   \n> -static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n> +static struct replay_opts get_replay_opts(struct rebase_options *opts)\n>   {\n>   \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n>   \n> @@ -114,6 +115,17 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n\nIt's a shame this changes the rebase_options that are passed in, this \nfunction should ideally not modify what is passed in.\n\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->ignore_whitespace) {\n> +\t\tstruct strbuf buf = STRBUF_INIT;\n> +\n> +\t\tif (opts->strategy_opts)\n> +\t\t\tstrbuf_addstr(&buf, opts->strategy_opts);\n> +\n> +\t\tstrbuf_addstr(&buf, \" --ignore-space-change\");\n> +\t\tfree(opts->strategy_opts);\n> +\t\topts->strategy_opts = strbuf_detach(&buf, NULL);\n> +\t}\n\nInstead of modifying opts->strategy_opts perhaps we could just use a \ntemporary variable\n\nBest Wishes\n\nPhillip\n\n>   \tif (opts->strategy_opts)\n>   \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n>   \n> @@ -511,6 +523,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>   \targc = parse_options(argc, argv, NULL, 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> @@ -954,6 +968,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> @@ -1401,9 +1417,6 @@ 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> @@ -1411,6 +1424,8 @@ 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\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> @@ -1821,6 +1836,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \t}\n>   \n>   \tif (options.rebase_merges) {\n> +\t\tif (options.ignore_whitespace)\n> +\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n> +\t\t\t      \"'--ignore-whitespace'\"));\n>   \t\tif (strategy_options.nr)\n>   \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n>   \t\t\t      \"'--strategy-option'\"));\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> new file mode 100755\n> index 0000000000..e617d3150e\n> --- /dev/null\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -0,0 +1,65 @@\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> +# 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> +\tcat >file <<-EOF &&\n> +\tline 1\n> +\t        line 2\n> +\tline 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_done\n> \n"},{"id":"380146","messageId":"24577efb-a959-04b1-c202-284571c5505e@gmail.com","threadId":"51596","inReplyTo":"0619f7b7-a7e5-54a2-3d28-ac359139bde7@gmail.com","subject":"Re: [GSoC][PATCHl 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-08T16:53:09Z","receivedAt":"2019-08-08T16:53:16Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 08/08/2019 12:42, Phillip Wood wrote:\n> On 06/08/2019 18:36, Rohit Ashiwal wrote:\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>>\n>> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\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, \n>> run:\\n\"\n>> @@ -985,7 +997,7 @@ static int run_git_commit(struct repository *r,\n>>   {\n>>       struct child_process cmd = CHILD_PROCESS_INIT;\n>> -    if (opts->committer_date_is_author_date &&\n>> +    if (opts->committer_date_is_author_date && !opts->ignore_date &&\n>>           setenv_committer_date_to_author_date())\n>>           return 1;\n> \n> We read the author script again just below, can set the committer date \n> there by parsing the author string, that would mean you could use the \n> same function that works on an author string in try_to_commit() (this \n> comment should be on patch 3 I think)\n\nIt's a bit more complicated as you've done this to avoid the duplication \nin the previous version. I think it should be possible to do it by \nreading the author identity upfront (protected by 'if \nis_rebase_i(opts)') and processing it appropriately in the two code \npaths. (You might need to refactor some of the functions like \nread_env_script() to do this.) An alternative would be to refactor \ntry_to_commit() so that it can create the root commit and delete the \ncode here that does that.\n\nBest Wishes\n\nPhillip\n\n> \n>>       if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n>> @@ -1013,10 +1025,18 @@ static int run_git_commit(struct repository *r,\n>>           if (res <= 0)\n>>               res = error_errno(_(\"could not read '%s'\"), defmsg);\n>> -        else\n>> +        else {\n>> +            if (opts->ignore_date) {\n>> +                if (!author)\n>> +                    BUG(\"ignore-date can only be used with \"\n>> +                        \"rebase -i, which must set the \"\n> \n> I know it's only a bug message but it's not just 'rebase -i' but 'rebase \n> -k', 'rebase -m' ... that use this code path, it would be better just to \n> say 'rebase'\n> \n>> +                        \"author before committing the tree\");\n>> +                ignore_author_date(&author);\n>> +            }\n>>               res = commit_tree(msg.buf, msg.len, cache_tree_oid,\n>>                         NULL, &root_commit, author,\n>>                         opts->gpg_sign);\n>> +        }\n>>           strbuf_release(&msg);\n>>           strbuf_release(&script);\n>> @@ -1046,6 +1066,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>> +        argv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n> \n> I think this is racy as it only sets the author date, the committer date \n> may end up being different.\n> \n>>       if (defmsg)\n>>           argv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>>       else if (!(flags & EDIT_MSG))\n>> @@ -1425,7 +1447,7 @@ static int try_to_commit(struct repository *r,\n>>       if (parse_head(r, &current_head))\n>>           return -1;\n>>       if (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&\n>> -        setenv_committer_date_to_author_date())\n>> +        !opts->ignore_date && setenv_committer_date_to_author_date())\n>>           return -1;\n>>       if (flags & AMEND_MSG) {\n>>           const char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n>> @@ -1447,7 +1469,7 @@ static int try_to_commit(struct repository *r,\n>>               res = error(_(\"unable to parse commit author\"));\n>>               goto out;\n>>           }\n>> -        if (opts->committer_date_is_author_date) {\n>> +        if (opts->committer_date_is_author_date && !opts->ignore_date) {\n> \n> If we only handled committer_date_is_author_date in a single place it \n> wouldn't need to be changed twice in this patch\n> \n>>               char *date;\n>>               int len = strlen(author);\n>>               char *idx = memchr(author, '>', len);\n>> @@ -1507,6 +1529,11 @@ static int try_to_commit(struct repository *r,\n>>       reset_ident_date();\n>> +    if (opts->ignore_date) {\n>> +        ignore_author_date(&author);\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>> @@ -2583,6 +2610,11 @@ static int read_populate_opts(struct \n>> replay_opts *opts)\n>>               opts->committer_date_is_author_date = 1;\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>> @@ -2667,6 +2699,8 @@ int write_basic_state(struct replay_opts *opts, \n>> const char *head_name,\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>> @@ -3484,6 +3518,9 @@ 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>> +            argv_array_pushf(&cmd.args,\n>> +                     \"GIT_AUTHOR_DATE=%ld\", time(NULL));\n>>           /* Add the tips to be merged */\n>>           for (j = to_merge; j; j = j->next)\n>> @@ -3756,7 +3793,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>> diff --git a/sequencer.h b/sequencer.h\n>> index e6cba468db..73d0515a3e 100644\n>> --- a/sequencer.h\n>> +++ b/sequencer.h\n>> @@ -44,6 +44,7 @@ struct replay_opts {\n>>       int quiet;\n>>       int reschedule_failed_exec;\n>>       int committer_date_is_author_date;\n>> +    int ignore_date;\n>>       int mainline;\n>> diff --git a/t/t3433-rebase-options-compatibility.sh \n>> b/t/t3433-rebase-options-compatibility.sh\n>> index ceab48a831..95d99c4b7b 100755\n>> --- a/t/t3433-rebase-options-compatibility.sh\n>> +++ b/t/t3433-rebase-options-compatibility.sh\n>> @@ -81,4 +81,20 @@ test_expect_success \n>> '--committer-date-is-author-date works with interactive back\n>>       test_cmp authortime committertime\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> That sounds potentially fragile but I guess the timezone is unlikely to \n> change in the future\n> \n> Best Wishes\n> \n> Phillip\n> \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>>   test_done\n>>\n"},{"id":"380321","messageId":"20190812174329.13995-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"bdd867f3-62d6-eec2-9562-5dbe203f49b5@gmail.com","subject":"Re: [GSoC][PATCHl 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T17:43:29Z","receivedAt":"2019-08-12T17:46:40Z","isPatch":false,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Hi Phillip\n\nOn Thu, 8 Aug 2019 17:44:38 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:\n> \n> [...]\n> >   --ignore-whitespace::\n> > +\tThis flag is either passed to the 'git apply' program\n> > +\t(see linkgit:git-apply[1]), or to 'git merge' program\n> > +\t(see linkgit:git-merge[1]) as `-Xignore-space-change`,\n> > +\tdepending on which backend is selected by other options.\n> \n> I think it would be better to document the effect of this option rather\n> than the implementation detail. It is confusing at the moment as it\n> talks about 'git merge' but we don't allow this option with merges.\n\nOh, it is just to indicate the user where to look for the definitions\nas currently the behaviour of both the backends is not exactly the\nsame neither do they work optimally. Hope in future when they are in\nharmony, then we can happily change it to match the then behaviour.\n\n> [...]\n\nThanks\nRohit\n\n"},{"id":"380331","messageId":"20190812194301.5655-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 0/6] rebase -i: support more options","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T19:42:54Z","receivedAt":"2019-08-12T19:46:12Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"I've tried to work on all the suggestion in this revision.\n\nBased on: 2e27de94d485a6da0c8e264c165e55100f1a13a8 (tag: v2.23.0-rc2)\n\nRohit Ashiwal (6):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: add NULL checks under read_author_script\n  rebase -i: support --committer-date-is-author-date\n  sequencer: rename amend_author to author_to_rename\n  rebase -i: support --ignore-date\n  rebase: add --author-date-is-committer-date\n\n Documentation/git-rebase.txt            |  23 +++--\n builtin/rebase.c                        |  66 +++++++++---\n sequencer.c                             | 132 ++++++++++++++++++++++--\n sequencer.h                             |   2 +\n t/t3422-rebase-incompatible-options.sh  |   2 -\n t/t3433-rebase-options-compatibility.sh | 100 ++++++++++++++++++\n 6 files changed, 295 insertions(+), 30 deletions(-)\n create mode 100755 t/t3433-rebase-options-compatibility.sh\n\nRange-diff:\n1:  e213112385 ! 1:  4cd0aa3084 rebase -i: add --ignore-whitespace flag\n    @@ -60,32 +60,35 @@\n      \tint autostash;\n      \tchar *cmd;\n     @@\n    - \t\t.git_format_patch_opt = STRBUF_INIT\t\\\n    - \t}\n      \n    --static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n    -+static struct replay_opts get_replay_opts(struct rebase_options *opts)\n    + static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n      {\n    ++\tchar *strategy_opts = opts->strategy_opts;\n      \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n      \n    + \treplay.action = REPLAY_INTERACTIVE_REBASE;\n     @@\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    +-\tif (opts->strategy_opts)\n    +-\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n     +\n     +\tif (opts->ignore_whitespace) {\n     +\t\tstruct strbuf buf = STRBUF_INIT;\n     +\n    -+\t\tif (opts->strategy_opts)\n    -+\t\t\tstrbuf_addstr(&buf, opts->strategy_opts);\n    ++\t\tif (strategy_opts)\n    ++\t\t\tstrbuf_addstr(&buf, strategy_opts);\n     +\n     +\t\tstrbuf_addstr(&buf, \" --ignore-space-change\");\n    -+\t\tfree(opts->strategy_opts);\n    -+\t\topts->strategy_opts = strbuf_detach(&buf, NULL);\n    ++\t\tfree(strategy_opts);\n    ++\t\tstrategy_opts = strbuf_detach(&buf, NULL);\n     +\t}\n    - \tif (opts->strategy_opts)\n    - \t\tparse_strategy_opts(&replay, opts->strategy_opts);\n    ++\tif (strategy_opts)\n    ++\t\tparse_strategy_opts(&replay, strategy_opts);\n      \n    + \treturn replay;\n    + }\n     @@\n      \targc = parse_options(argc, argv, prefix, options,\n      \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n    @@ -165,14 +168,14 @@\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    ++\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    ++\tcat >file <<-\\EOF &&\n     +\tline 1\n     +\tnew line 2\n     +\tline 3\n    @@ -181,10 +184,10 @@\n     +\tgit tag side &&\n     +\n     +\tgit checkout --orphan master &&\n    -+\tcat >file <<-EOF &&\n    -+\tline 1\n    -+\t        line 2\n    -+\tline 3\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    @@ -192,7 +195,7 @@\n     +'\n     +\n     +test_expect_success '--ignore-whitespace works with am backend' '\n    -+\tcat >expect <<-EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\tline 1\n     +\tnew line 2\n     +\tline 3\n    @@ -204,7 +207,7 @@\n     +'\n     +\n     +test_expect_success '--ignore-whitespace works with interactive backend' '\n    -+\tcat >expect <<-EOF &&\n    ++\tcat >expect <<-\\EOF &&\n     +\tline 1\n     +\tnew line 2\n     +\tline 3\n2:  df13514788 = 2:  e2c0304587 sequencer: add NULL checks under read_author_script\n3:  5735ec9ca2 ! 3:  6aed57ae2e rebase -i: support --committer-date-is-author-date\n    @@ -140,31 +140,28 @@\n      static const char *read_author_ident(struct strbuf *buf)\n      {\n     @@\n    - \treturn buf->buf;\n    - }\n    + {\n    + \tstruct child_process cmd = CHILD_PROCESS_INIT;\n      \n    -+static int setenv_committer_date_to_author_date(void)\n    -+{\n    -+\tint res = 1;\n    -+\tchar *date = read_author_date_or_null();\n    ++\tif (opts->committer_date_is_author_date) {\n    ++\t\tsize_t len;\n    ++\t\tint res = -1;\n    ++\t\tstruct strbuf datebuf = STRBUF_INIT;\n    ++\t\tchar *date = read_author_date_or_null();\n     +\n    -+\tif (date)\n    -+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n    ++\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n    ++\t\tfree(date);\n     +\n    -+\tfree(date);\n    -+\treturn res;\n    -+}\n    ++\t\tdate = strbuf_detach(&datebuf, &len);\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    -@@\n    - {\n    - \tstruct child_process cmd = CHILD_PROCESS_INIT;\n    - \n    -+\tif (opts->committer_date_is_author_date &&\n    -+\t    setenv_committer_date_to_author_date())\n    -+\t\treturn 1;\n    ++\t\tif (len > 1)\n    ++\t\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n    ++\n    ++\t\tfree(date);\n    ++\n    ++\t\tif (res)\n    ++\t\t\treturn -1;\n    ++\t}\n      \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n      \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n      \t\tconst char *author = NULL;\n    @@ -173,30 +170,31 @@\n      \tif (parse_head(r, &current_head))\n      \t\treturn -1;\n     -\n    -+\tif (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&\n    -+\t    setenv_committer_date_to_author_date())\n    -+\t\treturn -1;\n      \tif (flags & AMEND_MSG) {\n      \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n      \t\tconst char *out_enc = get_commit_output_encoding();\n     @@\n    - \t\t\tres = error(_(\"unable to parse commit author\"));\n    - \t\t\tgoto out;\n    - \t\t}\n    -+\t\tif (opts->committer_date_is_author_date) {\n    -+\t\t\tchar *date;\n    -+\t\t\tint len = strlen(author);\n    -+\t\t\tchar *idx = memchr(author, '>', len);\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\t\t++idx;\n    -+\t\t\tdate = malloc(author + len - idx);\n    -+\t\t\tmemcpy(date, idx, author + len - idx);\n    -+\t\t\tsetenv(\"GIT_COMMITTER_DATE\", date, 1);\n    -+\t\t\tfree(date);\n    -+\t\t}\n    - \t\tparents = copy_commit_list(current_head->parents);\n    - \t\textra = read_commit_extra_headers(current_head, exclude_gpgsig);\n    - \t} else if (current_head) {\n    ++\t\tsplit_ident_line(&ident, author, len);\n    ++\n    ++\t\tif (!ident.date_begin)\n    ++\t\t\treturn error(_(\"corrupted author without date information\"));\n    ++\n    ++\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n    ++\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n    ++\t\tstrbuf_release(&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    + \t\tgoto out;\n     @@\n      \t\t\topts->signoff = 1;\n      \t\t}\n    @@ -271,18 +269,18 @@\n      '\n      \n     +test_expect_success '--committer-date-is-author-date works with am backend' '\n    -+\tgit rebase -f HEAD^ &&\n    ++\tgit commit --amend &&\n     +\tgit rebase --committer-date-is-author-date HEAD^ &&\n    -+\tgit show HEAD --pretty=\"format:%at\" >authortime &&\n    -+\tgit show HEAD --pretty=\"format:%ct\" >committertime &&\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 rebase -f HEAD^ &&\n    ++\tgit commit --amend &&\n     +\tgit rebase -i --committer-date-is-author-date HEAD^ &&\n    -+\tgit show HEAD --pretty=\"format:%at\" >authortime &&\n    -+\tgit show HEAD --pretty=\"format:%ct\" >committertime &&\n    ++\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n    ++\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n     +\ttest_cmp authortime committertime\n     +'\n     +\n4:  cdcd66347b ! 4:  36a0c017c2 sequencer: rename amend_author to author_to_rename\n    @@ -3,8 +3,9 @@\n         sequencer: rename amend_author to author_to_rename\n     \n         The purpose of amend_author was to free() the malloc()'d string\n    -    obtained from get_author(). But the name does not actually convey\n    -    this purpose. Rename it to something meaningful.\n    +    obtained from get_author() while 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     \n5:  2f45a4e0b9 ! 5:  3a4ffeb995 rebase -i: support --ignore-date\n    @@ -17,7 +17,7 @@\n      --ignore-date::\n     -\tThis flag is passed to 'git am' to change the author date\n     -\tof the rebased commits (see linkgit:git-am[1]).\n    -+\tLie about the author date by re-setting it to the value\n    ++\tInstead of using the given author date, re-set it to the value\n     +\tsame as committer (current) date. This implies --force-rebase.\n      +\n      See also INCOMPATIBLE OPTIONS below.\n    @@ -63,6 +63,8 @@\n      \t\t\t  \"--rebase-merges\"));\n      \n     -\tif (opts.committer_date_is_author_date)\n    ++\tif (opts.ignore_date)\n    ++\t\topts.committer_date_is_author_date = 0;\n     +\tif (opts.committer_date_is_author_date ||\n     +\t    opts.ignore_date)\n      \t\topts.flags |= REBASE_FORCE;\n    @@ -93,6 +95,8 @@\n      \t}\n      \n     -\tif (options.committer_date_is_author_date)\n    ++\tif (options.ignore_date)\n    ++\t\toptions.committer_date_is_author_date = 0;\n     +\tif (options.committer_date_is_author_date ||\n     +\t    options.ignore_date)\n      \t\toptions.flags |= REBASE_FORCE;\n    @@ -118,33 +122,38 @@\n      static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n      static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n     @@\n    - \treturn res;\n    + \treturn buf->buf;\n      }\n      \n     +static void 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    -+\tchar *idx = memchr(*author, '>', strlen(*author));\n     +\n    -+\tstrbuf_add(&new_author, *author, idx - *author);\n    -+\tstrbuf_addstr(&new_author, \"> \");\n    ++\tsplit_ident_line(&ident, *author, len);\n    ++\tlen = ident.mail_end - ident.name_begin + 1;\n    ++\n    ++\tstrbuf_addf(&new_author, \"%.*s\", len, *author);\n     +\tdatestamp(&new_author);\n     +\t*author = strbuf_detach(&new_author, NULL);\n     +}\n    ++\n    ++static void push_dates(struct child_process *child)\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->args, \"--date=%s\", date.buf);\n    ++\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     @@\n    - {\n    - \tstruct child_process cmd = CHILD_PROCESS_INIT;\n    - \n    --\tif (opts->committer_date_is_author_date &&\n    -+\tif (opts->committer_date_is_author_date && !opts->ignore_date &&\n    - \t    setenv_committer_date_to_author_date())\n    - \t\treturn 1;\n    - \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n    -@@\n      \n      \t\tif (res <= 0)\n      \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n    @@ -153,8 +162,8 @@\n     +\t\t\tif (opts->ignore_date) {\n     +\t\t\t\tif (!author)\n     +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n    -+\t\t\t\t\t    \"rebase -i, which must set the \"\n    -+\t\t\t\t\t    \"author before committing the tree\");\n    ++\t\t\t\t\t    \"rebase, which must set the author \"\n    ++\t\t\t\t\t    \"before committing the tree\");\n     +\t\t\t\tignore_author_date(&author);\n     +\t\t\t}\n      \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n    @@ -169,29 +178,11 @@\n      \tif (opts->gpg_sign)\n      \t\targv_array_pushf(&cmd.args, \"-S%s\", opts->gpg_sign);\n     +\tif (opts->ignore_date)\n    -+\t\targv_array_pushf(&cmd.args, \"--date=%ld\", time(NULL));\n    ++\t\tpush_dates(&cmd);\n      \tif (defmsg)\n      \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n      \telse if (!(flags & EDIT_MSG))\n     @@\n    - \tif (parse_head(r, &current_head))\n    - \t\treturn -1;\n    - \tif (!(flags & AMEND_MSG) && opts->committer_date_is_author_date &&\n    --\t    setenv_committer_date_to_author_date())\n    -+\t    !opts->ignore_date && setenv_committer_date_to_author_date())\n    - \t\treturn -1;\n    - \tif (flags & AMEND_MSG) {\n    - \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", NULL };\n    -@@\n    - \t\t\tres = error(_(\"unable to parse commit author\"));\n    - \t\t\tgoto out;\n    - \t\t}\n    --\t\tif (opts->committer_date_is_author_date) {\n    -+\t\tif (opts->committer_date_is_author_date && !opts->ignore_date) {\n    - \t\t\tchar *date;\n    - \t\t\tint len = strlen(author);\n    - \t\t\tchar *idx = memchr(author, '>', len);\n    -@@\n      \n      \treset_ident_date();\n      \n    @@ -229,8 +220,7 @@\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\targv_array_pushf(&cmd.args,\n    -+\t\t\t\t\t \"GIT_AUTHOR_DATE=%ld\", time(NULL));\n    ++\t\t\tpush_dates(&cmd);\n      \n      \t\t/* Add the tips to be merged */\n      \t\tfor (j = to_merge; j; j = j->next)\n6:  8fa3da175c ! 6:  cb81e6c4e5 rebase: add --author-date-is-committer-date\n    @@ -17,7 +17,7 @@\n      \n      --ignore-date::\n     +--author-date-is-committer-date::\n    - \tLie about the author date by re-setting it to the value\n    + \tInstead of using the given author date, re-set it to the value\n      \tsame as committer (current) date. This implies --force-rebase.\n      +\n     \n-- \n2.21.0\n\n"},{"id":"380332","messageId":"20190812194301.5655-2-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T19:42:55Z","receivedAt":"2019-08-12T19:46:16Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"There are two backends available for rebasing, viz, the am and the\ninteractive. Naturally, there shall be some features that are\nimplemented in one but not in the other. One such flag is\n--ignore-whitespace which indicates merge mechanism to treat lines\nwith only whitespace changes as unchanged. Wire the interactive\nrebase to also understand the --ignore-whitespace flag by\ntranslating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 10 +++-\n builtin/rebase.c                        | 29 +++++++++--\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n 4 files changed, 97 insertions(+), 8 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 6156609cf7..28e5e08a83 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -371,8 +371,13 @@ 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 \n --ignore-whitespace::\n+\tThis flag is either passed to the 'git apply' program\n+\t(see linkgit:git-apply[1]), or to 'git merge' program\n+\t(see linkgit:git-merge[1]) as `-Xignore-space-change`,\n+\tdepending on which backend is selected by other options.\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@@ -520,7 +525,6 @@ The following options:\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@@ -543,6 +547,8 @@ 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+ * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 670096c065..ab1bbb78ee 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -79,6 +79,7 @@ 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 \tchar *cmd;\n@@ -99,6 +100,7 @@ struct rebase_options {\n \n static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n {\n+\tchar *strategy_opts = opts->strategy_opts;\n \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n \n \treplay.action = REPLAY_INTERACTIVE_REBASE;\n@@ -114,8 +116,19 @@ 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-\tif (opts->strategy_opts)\n-\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n+\n+\tif (opts->ignore_whitespace) {\n+\t\tstruct strbuf buf = STRBUF_INIT;\n+\n+\t\tif (strategy_opts)\n+\t\t\tstrbuf_addstr(&buf, strategy_opts);\n+\n+\t\tstrbuf_addstr(&buf, \" --ignore-space-change\");\n+\t\tfree(strategy_opts);\n+\t\tstrategy_opts = strbuf_detach(&buf, NULL);\n+\t}\n+\tif (strategy_opts)\n+\t\tparse_strategy_opts(&replay, strategy_opts);\n \n \treturn replay;\n }\n@@ -511,6 +524,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@@ -964,6 +979,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@@ -1407,9 +1424,6 @@ 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@@ -1417,6 +1431,8 @@ 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\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@@ -1834,6 +1850,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (options.rebase_merges) {\n+\t\tif (options.ignore_whitespace)\n+\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n+\t\t\t      \"'--ignore-whitespace'\"));\n \t\tif (strategy_options.nr)\n \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n \t\t\t      \"'--strategy-option'\"));\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nnew file mode 100755\nindex 0000000000..2e16e00a9d\n--- /dev/null\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -0,0 +1,65 @@\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+# 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 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_done\n-- \n2.21.0\n\n"},{"id":"380333","messageId":"20190812194301.5655-3-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 2/6] sequencer: add NULL checks under read_author_script","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T19:42:56Z","receivedAt":"2019-08-12T19:46:19Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"read_author_script reads name, email and author date from the author\nscript. However, it does not check if the arguments are NULL. Adding\nNULL checks will allow us to selectively get the required value, for\nexample:\n\n    char *date;\n    if (read_author_script(_path_, NULL, NULL, &date, _int_))\n\t    die(_(\"failed to read author date\"));\n    /* needs to be free()'d */\n    return date;\n\nAdd NULL checks for better control over the information retrieved.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 16 +++++++++++++---\n 1 file changed, 13 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 34ebf8ed94..30d77c2682 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -824,9 +824,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-- \n2.21.0\n\n"},{"id":"380334","messageId":"20190812194301.5655-4-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T19:42:57Z","receivedAt":"2019-08-12T19:46:22Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the committer date\nby changing it to the author date. Let's add the same for\ninteractive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            |  8 +++-\n builtin/rebase.c                        | 20 ++++++---\n sequencer.c                             | 57 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 19 +++++++++\n 6 files changed, 96 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 28e5e08a83..697ce8e6ff 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.\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+\tThis flag is passed to 'git am' to change the author date\n \tof the rebased commits (see linkgit:git-am[1]).\n +\n See also INCOMPATIBLE OPTIONS below.\n@@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -548,6 +551,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 --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex ab1bbb78ee..b1039f8db0 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -82,6 +82,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@@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -533,6 +536,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n \t\t\t  \"--rebase-merges\"));\n \n+\tif (opts.committer_date_is_author_date)\n+\t\topts.flags |= REBASE_FORCE;\n+\n \treturn !!run_rebase_interactive(&opts, command);\n }\n \n@@ -981,6 +987,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@@ -1424,9 +1432,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@@ -1697,10 +1705,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\ndiff --git a/sequencer.c b/sequencer.c\nindex 30d77c2682..fbc0ed0cad 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -147,6 +147,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@@ -879,6 +880,17 @@ 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 /* Read author-script and return an ident line (author <email> timestamp) */\n static const char *read_author_ident(struct strbuf *buf)\n {\n@@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,\n {\n \tstruct child_process cmd = CHILD_PROCESS_INIT;\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tsize_t len;\n+\t\tint res = -1;\n+\t\tstruct strbuf datebuf = STRBUF_INIT;\n+\t\tchar *date = read_author_date_or_null();\n+\n+\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n+\t\tfree(date);\n+\n+\t\tdate = strbuf_detach(&datebuf, &len);\n+\n+\t\tif (len > 1)\n+\t\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n+\n+\t\tfree(date);\n+\n+\t\tif (res)\n+\t\t\treturn -1;\n+\t}\n \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n \t\tconst char *author = NULL;\n@@ -1400,7 +1431,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\", NULL };\n \t\tconst char *out_enc = get_commit_output_encoding();\n@@ -1427,6 +1457,21 @@ 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\tsplit_ident_line(&ident, author, len);\n+\n+\t\tif (!ident.date_begin)\n+\t\t\treturn error(_(\"corrupted author without date information\"));\n+\n+\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n+\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&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 \t\tgoto out;\n@@ -2542,6 +2587,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@@ -2624,6 +2674,8 @@ 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->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3821,7 +3873,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 6704acbb9c..e3881e9275 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 2e16e00a9d..b2419a2b75 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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@@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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_done\n-- \n2.21.0\n\n"},{"id":"380335","messageId":"20190812194301.5655-5-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T19:42:58Z","receivedAt":"2019-08-12T19:46:26Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() while 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 fbc0ed0cad..e186136ccc 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1424,7 +1424,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@@ -1445,7 +1445,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@@ -1534,7 +1534,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.21.0\n\n"},{"id":"380336","messageId":"20190812194301.5655-6-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T19:42:59Z","receivedAt":"2019-08-12T19:46:29Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the author date\nby changing it to the committer (current) date. Let's add the same\nfor interactive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            |  6 +--\n builtin/rebase.c                        | 21 +++++++---\n sequencer.c                             | 55 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3433-rebase-options-compatibility.sh | 16 +++++++\n 5 files changed, 88 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 697ce8e6ff..24ad2dda0b 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n-\tThis flag is passed to 'git am' to change the author date\n-\tof the rebased commits (see linkgit:git-am[1]).\n+\tInstead of using the given author date, re-set it to the value\n+\tsame as committer (current) date. This implies --force-rebase.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:\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  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex b1039f8db0..ed58ca8e5a 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -83,6 +83,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@@ -117,6 +118,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@@ -536,7 +538,10 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n \t\t\t  \"--rebase-merges\"));\n \n-\tif (opts.committer_date_is_author_date)\n+\tif (opts.ignore_date)\n+\t\topts.committer_date_is_author_date = 0;\n+\tif (opts.committer_date_is_author_date ||\n+\t    opts.ignore_date)\n \t\topts.flags |= REBASE_FORCE;\n \n \treturn !!run_rebase_interactive(&opts, command);\n@@ -989,6 +994,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@@ -1435,8 +1442,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@@ -1705,13 +1712,15 @@ 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+\tif (options.ignore_date)\n+\t\toptions.committer_date_is_author_date = 0;\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, \"--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 e186136ccc..aecd9b4ad8 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -148,6 +148,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@@ -919,6 +920,31 @@ static const char *read_author_ident(struct strbuf *buf)\n \treturn buf->buf;\n }\n \n+static void 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+\tsplit_ident_line(&ident, *author, len);\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\n+\tstrbuf_addf(&new_author, \"%.*s\", len, *author);\n+\tdatestamp(&new_author);\n+\t*author = strbuf_detach(&new_author, NULL);\n+}\n+\n+static void push_dates(struct child_process *child)\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->args, \"--date=%s\", date.buf);\n+\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@@ -1020,10 +1046,18 @@ static int run_git_commit(struct repository *r,\n \n \t\tif (res <= 0)\n \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n-\t\telse\n+\t\telse {\n+\t\t\tif (opts->ignore_date) {\n+\t\t\t\tif (!author)\n+\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n+\t\t\t\t\t    \"rebase, which must set the author \"\n+\t\t\t\t\t    \"before committing the tree\");\n+\t\t\t\tignore_author_date(&author);\n+\t\t\t}\n \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n \t\t\t\t\t  NULL, &root_commit, author,\n \t\t\t\t\t  opts->gpg_sign);\n+\t\t}\n \n \t\tstrbuf_release(&msg);\n \t\tstrbuf_release(&script);\n@@ -1053,6 +1087,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);\n \tif (defmsg)\n \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n \telse if (!(flags & EDIT_MSG))\n@@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,\n \n \treset_ident_date();\n \n+\tif (opts->ignore_date) {\n+\t\tignore_author_date(&author);\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@@ -2592,6 +2633,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@@ -2676,6 +2722,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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@@ -3601,6 +3649,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);\n \n \t\t/* Add the tips to be merged */\n \t\tfor (j = to_merge; j; j = j->next)\n@@ -3874,7 +3924,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 e3881e9275..bf5a79afdb 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex b2419a2b75..c060fcd10b 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n \ttest_cmp authortime committertime\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 test_done\n-- \n2.21.0\n\n"},{"id":"380337","messageId":"20190812194301.5655-7-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-12T19:43:00Z","receivedAt":"2019-08-12T19:46:33Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The previous commit introduced --ignore-date flag to interactive\nrebase, but the name is actually very vague in context of rebase -i\nsince there are two dates we can work with. Add an alias to convey\nthe precise purpose.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt | 1 +\n builtin/rebase.c             | 2 ++\n 2 files changed, 3 insertions(+)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 24ad2dda0b..6a52d721e2 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -388,6 +388,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n+--author-date-is-committer-date::\n \tInstead of using the given author date, re-set it to the value\n \tsame as committer (current) date. This implies --force-rebase.\n +\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex ed58ca8e5a..19b1fc0f3a 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1442,6 +1442,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_BOOL(0, \"author-date-is-committer-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current 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_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n-- \n2.21.0\n\n"},{"id":"380361","messageId":"7274e753-f75c-ad9a-9c2c-7ba8abc32971@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-4-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-13T10:38:57Z","receivedAt":"2019-08-13T10:39:06Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nThis is looking good, I think it is almost there now\n\nOn 12/08/2019 20:42, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            |  8 +++-\n>   builtin/rebase.c                        | 20 ++++++---\n>   sequencer.c                             | 57 ++++++++++++++++++++++++-\n>   sequencer.h                             |  1 +\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++\n>   6 files changed, 96 insertions(+), 10 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 28e5e08a83..697ce8e6ff 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.\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> +\tThis flag is passed to 'git am' to change the author date\n>   \tof the rebased commits (see linkgit:git-am[1]).\n>   +\n>   See also INCOMPATIBLE OPTIONS below.\n> @@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --committer-date-is-author-date\n>    * --ignore-date\n>    * --whitespace\n>    * -C\n> @@ -548,6 +551,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 --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index ab1bbb78ee..b1039f8db0 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -82,6 +82,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> @@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>   \treplay.strategy = opts->strategy;\n>   \n> @@ -533,6 +536,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>   \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n>   \t\t\t  \"--rebase-merges\"));\n>   \n> +\tif (opts.committer_date_is_author_date)\n> +\t\topts.flags |= REBASE_FORCE;\n> +\n>   \treturn !!run_rebase_interactive(&opts, command);\n>   }\n>   \n> @@ -981,6 +987,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> @@ -1424,9 +1432,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> @@ -1697,10 +1705,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\n> diff --git a/sequencer.c b/sequencer.c\n> index 30d77c2682..fbc0ed0cad 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -147,6 +147,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> @@ -879,6 +880,17 @@ 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>   /* Read author-script and return an ident line (author <email> timestamp) */\n>   static const char *read_author_ident(struct strbuf *buf)\n>   {\n> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,\n>   {\n>   \tstruct child_process cmd = CHILD_PROCESS_INIT;\n>   \n> +\tif (opts->committer_date_is_author_date) {\n> +\t\tsize_t len;\n> +\t\tint res = -1;\n> +\t\tstruct strbuf datebuf = STRBUF_INIT;\n> +\t\tchar *date = read_author_date_or_null();\n\nYou must always check the return value of functions that might return \nNULL. In this case we should return an error as you do in try_to \n_commit() later\n\n> +\n> +\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n\nGNU printf() will add something like '(null)' to the buffer if you pass \na NULL pointer so I don't think we can be sure that this will not \nincrease the length of the buffer if date is NULL. An explicit check \nabove would be much clearer as well rather than checking len later. What \nhappens if you don't add the '@' at the beginning? (I'm don't know much \nabout git's date handling)\n\n> +\t\tfree(date);\n> +\n> +\t\tdate = strbuf_detach(&datebuf, &len);\n> +\n> +\t\tif (len > 1)\n> +\t\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n> +\n> +\t\tfree(date);\n> +\n> +\t\tif (res)\n> +\t\t\treturn -1;\n> +\t}\n>   \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n>   \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n>   \t\tconst char *author = NULL;\n> @@ -1400,7 +1431,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\", NULL };\n>   \t\tconst char *out_enc = get_commit_output_encoding();\n> @@ -1427,6 +1457,21 @@ 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\tsplit_ident_line(&ident, author, len);\n> +\n> +\t\tif (!ident.date_begin)\n> +\t\t\treturn error(_(\"corrupted author without date information\"));\n\nWe return an error if we cannot get the date - this is exactly what we \nshould be doing above. It is also great to see a single version of this \nbeing used whether or not we are amending.\n\n> +\n> +\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n\nI think we should use %s.* and ident.date_end to be sure we getting what \nwe want. Your version is OK if the author is formatted correctly but I'm \nuneasy about relying on that when we can get the verified end from ident.\n\nBest Wishes\n\nPhillip\n\n> +\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +\t\tstrbuf_release(&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>   \t\tgoto out;\n> @@ -2542,6 +2587,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> @@ -2624,6 +2674,8 @@ 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->reschedule_failed_exec)\n>   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>   \n> @@ -3821,7 +3873,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 6704acbb9c..e3881e9275 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 2e16e00a9d..b2419a2b75 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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_done\n> \n"},{"id":"380363","messageId":"a505fdf3-5926-9765-21ef-b82334a3fba4@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-2-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-13T12:07:11Z","receivedAt":"2019-08-13T12:07:19Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nThanks for the re-roll\n\nOn 12/08/2019 20:42, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            | 10 +++-\n>   builtin/rebase.c                        | 29 +++++++++--\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n>   4 files changed, 97 insertions(+), 8 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 6156609cf7..28e5e08a83 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -371,8 +371,13 @@ 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>   \n>   --ignore-whitespace::\n> +\tThis flag is either passed to the 'git apply' program\n> +\t(see linkgit:git-apply[1]), or to 'git merge' program\n> +\t(see linkgit:git-merge[1]) as `-Xignore-space-change`,\n> +\tdepending on which backend is selected by other options.\n\nI still think this should document what it does rather than how it is \nimplemented - see my previous comments.\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> @@ -520,7 +525,6 @@ The following options:\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> @@ -543,6 +547,8 @@ 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> + * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n>   \n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 670096c065..ab1bbb78ee 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -79,6 +79,7 @@ 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>   \tchar *cmd;\n> @@ -99,6 +100,7 @@ struct rebase_options {\n>   \n>   static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>   {\n> +\tchar *strategy_opts = opts->strategy_opts;\n\nstrategy_opts is a shallow copy of opts->strategy_opts - this will cause \nproblems later\n\n>   \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n>   \n>   \treplay.action = REPLAY_INTERACTIVE_REBASE;\n> @@ -114,8 +116,19 @@ 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> -\tif (opts->strategy_opts)\n> -\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n> +\n> +\tif (opts->ignore_whitespace) {\n> +\t\tstruct strbuf buf = STRBUF_INIT;\n> +\n> +\t\tif (strategy_opts)\n> +\t\t\tstrbuf_addstr(&buf, strategy_opts);\n\nI'd rewrite this as\n\tif (opts->strategy_opts)\n\t\tstrbuf_addstr(&buf, opts->strategy_opts);\n\nwithout the outer if testing opts->ignore_whitespace\n> +\nthen add\n\tif (opts->ignore_whitespace)\nhere\n> +\t\tstrbuf_addstr(&buf, \" --ignore-space-change\");\n> +\t\tfree(strategy_opts);\n\nand then you don't need this free() or strategy_opts. At the moment this \nhas freed opts->stragety_opts which is what we were trying to avoid, in \nfact it's slightly worse than the last version because we don't change \nopts->strategy_opts to reflect the fact it has been freed. Also the \ncaller cannot know if it has been freed as it depends what other options \nare set.\n\n> +\t\tstrategy_opts = strbuf_detach(&buf, NULL);\n> +\t}\n> +\tif (strategy_opts)\n> +\t\tparse_strategy_opts(&replay, strategy_opts);\n\nreplace this withe\n\tif (buf.len)\n\t\tparse_strategy_opts(&replay, buf.buf);\n\tstrbuf_release(&buf);\n\nThis way we never change opts->strategy_opts and we always release the \ntemporary copy.\n\nBest Wishes\n\nPhillip\n\n>   \n>   \treturn replay;\n>   }\n> @@ -511,6 +524,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> @@ -964,6 +979,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> @@ -1407,9 +1424,6 @@ 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> @@ -1417,6 +1431,8 @@ 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\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> @@ -1834,6 +1850,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \t}\n>   \n>   \tif (options.rebase_merges) {\n> +\t\tif (options.ignore_whitespace)\n> +\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n> +\t\t\t      \"'--ignore-whitespace'\"));\n>   \t\tif (strategy_options.nr)\n>   \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n>   \t\t\t      \"'--strategy-option'\"));\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> new file mode 100755\n> index 0000000000..2e16e00a9d\n> --- /dev/null\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -0,0 +1,65 @@\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> +# 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 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_done\n> \n"},{"id":"380364","messageId":"f34a6bf7-8725-774c-5fde-0349bc8565bd@gmail.com","threadId":"51596","inReplyTo":"7274e753-f75c-ad9a-9c2c-7ba8abc32971@gmail.com","subject":"Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-13T12:09:46Z","receivedAt":"2019-08-13T12:09:52Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/08/2019 11:38, Phillip Wood wrote:\n> Hi Rohit\n> \n> [...]\n>> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,\n>>   {\n>>       struct child_process cmd = CHILD_PROCESS_INIT;\n>> +    if (opts->committer_date_is_author_date) {\n>> +        size_t len;\n>> +        int res = -1;\n>> +        struct strbuf datebuf = STRBUF_INIT;\n>> +        char *date = read_author_date_or_null();\n> \n> You must always check the return value of functions that might return \n> NULL. In this case we should return an error as you do in try_to \n> _commit() later\n> \n>> +\n>> +        strbuf_addf(&datebuf, \"@%s\", date);\n> \n> GNU printf() will add something like '(null)' to the buffer if you pass \n> a NULL pointer so I don't think we can be sure that this will not \n> increase the length of the buffer if date is NULL.\n\nI should have added that passing NULL to snprintf() and friends is going \nto be undefined behavior anyway so you shouldn't do it for that reason \nalone.\n\nBest Wishes\n\nPhillip\n\n  An explicit check\n> above would be much clearer as well rather than checking len later. What \n> happens if you don't add the '@' at the beginning? (I'm don't know much \n> about git's date handling)\n> \n>> +        free(date);\n>> +\n>> +        date = strbuf_detach(&datebuf, &len);\n>> +\n>> +        if (len > 1)\n>> +            res = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n>> +\n>> +        free(date);\n>> +\n>> +        if (res)\n>> +            return -1;\n>> +    }\n>>       if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n>>           struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n>>           const char *author = NULL;\n>> @@ -1400,7 +1431,6 @@ static int try_to_commit(struct repository *r,\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>> @@ -1427,6 +1457,21 @@ static int try_to_commit(struct repository *r,\n>>           commit_list_insert(current_head, &parents);\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>> +        split_ident_line(&ident, author, len);\n>> +\n>> +        if (!ident.date_begin)\n>> +            return error(_(\"corrupted author without date \n>> information\"));\n> \n> We return an error if we cannot get the date - this is exactly what we \n> should be doing above. It is also great to see a single version of this \n> being used whether or not we are amending.\n> \n>> +\n>> +        strbuf_addf(&date, \"@%s\",ident.date_begin);\n> \n> I think we should use %s.* and ident.date_end to be sure we getting what \n> we want. Your version is OK if the author is formatted correctly but I'm \n> uneasy about relying on that when we can get the verified end from ident.\n> \n> Best Wishes\n> \n> Phillip\n> \n>> +        setenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n>> +        strbuf_release(&date);\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>> @@ -2542,6 +2587,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>> @@ -2624,6 +2674,8 @@ int write_basic_state(struct replay_opts *opts, \n>> const char *head_name,\n>>           write_file(rebase_path_gpg_sign_opt(), \"-S%s\\n\", \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->reschedule_failed_exec)\n>>           write_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>> @@ -3821,7 +3873,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 6704acbb9c..e3881e9275 100644\n>> --- a/sequencer.h\n>> +++ b/sequencer.h\n>> @@ -43,6 +43,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 4342f79eea..7402f7e3da 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 \n>> --signoff' '\n>> diff --git a/t/t3433-rebase-options-compatibility.sh \n>> b/t/t3433-rebase-options-compatibility.sh\n>> index 2e16e00a9d..b2419a2b75 100755\n>> --- a/t/t3433-rebase-options-compatibility.sh\n>> +++ b/t/t3433-rebase-options-compatibility.sh\n>> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility \n>> between am and interactive backe\n>>   . ./test-lib.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>> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with \n>> interactive backend' '\n>>       test_cmp expect file\n>>   '\n>> +test_expect_success '--committer-date-is-author-date works with am \n>> 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 \n>> 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_done\n>>\n"},{"id":"380382","messageId":"b59f0aa2-1dc3-905a-0094-5f63718dffcf@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-6-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-13T13:28:23Z","receivedAt":"2019-08-13T13:28:31Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nThis is looking better - there are a couple of memory management issues \nand minor nit-picks but apart from that it looks good.\n\nOn 12/08/2019 20:42, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            |  6 +--\n>   builtin/rebase.c                        | 21 +++++++---\n>   sequencer.c                             | 55 ++++++++++++++++++++++++-\n>   sequencer.h                             |  1 +\n>   t/t3433-rebase-options-compatibility.sh | 16 +++++++\n>   5 files changed, 88 insertions(+), 11 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 697ce8e6ff..24ad2dda0b 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -388,8 +388,8 @@ See also INCOMPATIBLE OPTIONS below.\n>   \tas the committer date. This implies --force-rebase.\n>   \n>   --ignore-date::\n> -\tThis flag is passed to 'git am' to change the author date\n> -\tof the rebased commits (see linkgit:git-am[1]).\n> +\tInstead of using the given author date, re-set\n\nreset is not hyphenated\n\n> it to the value\n> +\tsame\n> as committer (current) date. This implies --force-rebase.\n\ns/value same as committer/same value as the committer/\n\n>   +\n>   See also INCOMPATIBLE OPTIONS below.\n>   \n> @@ -526,7 +526,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --ignore-date\n>    * --whitespace\n>    * -C\n>   \n> @@ -552,6 +551,7 @@ In addition, the following pairs of options are incompatible:\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>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index b1039f8db0..ed58ca8e5a 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -83,6 +83,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> @@ -117,6 +118,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> @@ -536,7 +538,10 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>   \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n>   \t\t\t  \"--rebase-merges\"));\n>   \n> -\tif (opts.committer_date_is_author_date)\n> +\tif (opts.ignore_date)\n> +\t\topts.committer_date_is_author_date = 0;\n> +\tif (opts.committer_date_is_author_date ||\n> +\t    opts.ignore_date)\n>   \t\topts.flags |= REBASE_FORCE;\n\nIs any of this used by rebase--preserve-merges.sh?\n\n>   \treturn !!run_rebase_interactive(&opts, command);\n> @@ -989,6 +994,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> @@ -1435,8 +1442,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> @@ -1705,13 +1712,15 @@ 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> +\tif (options.ignore_date)\n> +\t\toptions.committer_date_is_author_date = 0;\n\nWe should probably print an error if the user gives \n--committer-date-is-author-date and --author-date-is-committer-date (and \nin cmd_rebase__interactive() if we keep this option there)\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, \"--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)) {\n> diff --git a/sequencer.c b/sequencer.c\n> index e186136ccc..aecd9b4ad8 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -148,6 +148,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> @@ -919,6 +920,31 @@ static const char *read_author_ident(struct strbuf *buf)\n>   \treturn buf->buf;\n>   }\n>   \n> +static void 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> +\tsplit_ident_line(&ident, *author, len);\n> +\tlen = ident.mail_end - ident.name_begin + 1;\n> +\n> +\tstrbuf_addf(&new_author, \"%.*s\", len, *author);\n> +\tdatestamp(&new_author);\n> +\t*author = strbuf_detach(&new_author, NULL);\n> +}\n\nIt's good to see this using the indet api. I think this would be nicer \nif it took a char* returned the new author rather than changing the \nfunction argument, particularly as it does not free the string that is \npassed in so the ownership is unclear.\n\n> +\n> +static void push_dates(struct child_process *child)\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->args, \"--date=%s\", date.buf);\n\nit doesn't matter but it might have been nicer to set both dates the \nsame way in the environment.\n\n> +\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> @@ -1020,10 +1046,18 @@ static int run_git_commit(struct repository *r,\n>   \n>   \t\tif (res <= 0)\n>   \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n> -\t\telse\n> +\t\telse {\n> +\t\t\tif (opts->ignore_date) {\n> +\t\t\t\tif (!author)\n> +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n> +\t\t\t\t\t    \"rebase, which must set the author \"\n> +\t\t\t\t\t    \"before committing the tree\");\n> +\t\t\t\tignore_author_date(&author);\n\nIs this leaking the old author? I'd rather see\n\n\ttmp_author = ignore_author_date(author);\n\tfree(author);\n\tauthor = tmp_author;\n\n> +\t\t\t}\n>   \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n>   \t\t\t\t\t  NULL, &root_commit, author,\n>   \t\t\t\t\t  opts->gpg_sign);\n> +\t\t}\n>   \n>   \t\tstrbuf_release(&msg);\n>   \t\tstrbuf_release(&script);\n> @@ -1053,6 +1087,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);\n>   \tif (defmsg)\n>   \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>   \telse if (!(flags & EDIT_MSG))\n> @@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,\n>   \n>   \treset_ident_date();\n>   \n> +\tif (opts->ignore_date) {\n> +\t\tignore_author_date(&author);\n> +\t\tfree(author_to_free);\n\nWhere is author_to_free set? We should always free the old author, see \nabove.\n\n> +\t\tauthor_to_free = (char *)author;\n\nWhy do we need the cast - is author const?\n\nBest Wishes\n\nPhillip\n\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> @@ -2592,6 +2633,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> @@ -2676,6 +2722,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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> @@ -3601,6 +3649,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);\n>   \n>   \t\t/* Add the tips to be merged */\n>   \t\tfor (j = to_merge; j; j = j->next)\n> @@ -3874,7 +3924,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 e3881e9275..bf5a79afdb 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index b2419a2b75..c060fcd10b 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n>   \ttest_cmp authortime committertime\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>   test_done\n> \n"},{"id":"380383","messageId":"ca11527b-0abf-9146-1e6c-d0f095c762a3@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-5-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 4/6] sequencer: rename amend_author to author_to_rename","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-13T13:29:34Z","receivedAt":"2019-08-13T13:29:40Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 12/08/2019 20:42, Rohit Ashiwal wrote:\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> also use the variable to free() the author at our convenience.\n> Rename it to convey this meaning.\n\nThanks for rewording this\n\nBest Wishes\n\nPhillip\n\n> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   sequencer.c | 6 +++---\n>   1 file changed, 3 insertions(+), 3 deletions(-)\n> \n> diff --git a/sequencer.c b/sequencer.c\n> index fbc0ed0cad..e186136ccc 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -1424,7 +1424,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> @@ -1445,7 +1445,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> @@ -1534,7 +1534,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> \n"},{"id":"380384","messageId":"32b4a676-876b-1ddb-e10c-e9b7646ac961@gmail.com","threadId":"51596","inReplyTo":"20190812194301.5655-4-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-13T13:35:51Z","receivedAt":"2019-08-13T13:36:00Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 12/08/2019 20:42, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            |  8 +++-\n>   builtin/rebase.c                        | 20 ++++++---\n>   sequencer.c                             | 57 ++++++++++++++++++++++++-\n>   sequencer.h                             |  1 +\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++\n>   6 files changed, 96 insertions(+), 10 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 28e5e08a83..697ce8e6ff 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -383,8 +383,12 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.\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> +\tThis flag is passed to 'git am' to change the author date\n\nVery minor nit-pick. This has lost the plural for 'dates'. I'm not sure \nthis is correct as there will be more than one date because the commits \nwill have different dates. If it had said 'change the date of each \nrebased commit' then the singular would definitely be right but as it \nstands I'm not sure this is an improvement.\n\nBest Wishes\n\nPhillip\n\n>   \tof the rebased commits (see linkgit:git-am[1]).\n>   +\n>   See also INCOMPATIBLE OPTIONS below.\n> @@ -522,7 +526,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --committer-date-is-author-date\n>    * --ignore-date\n>    * --whitespace\n>    * -C\n> @@ -548,6 +551,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 --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index ab1bbb78ee..b1039f8db0 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -82,6 +82,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> @@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>   \treplay.strategy = opts->strategy;\n>   \n> @@ -533,6 +536,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n>   \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n>   \t\t\t  \"--rebase-merges\"));\n>   \n> +\tif (opts.committer_date_is_author_date)\n> +\t\topts.flags |= REBASE_FORCE;\n> +\n>   \treturn !!run_rebase_interactive(&opts, command);\n>   }\n>   \n> @@ -981,6 +987,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> @@ -1424,9 +1432,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> @@ -1697,10 +1705,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\n> diff --git a/sequencer.c b/sequencer.c\n> index 30d77c2682..fbc0ed0cad 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -147,6 +147,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> @@ -879,6 +880,17 @@ 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>   /* Read author-script and return an ident line (author <email> timestamp) */\n>   static const char *read_author_ident(struct strbuf *buf)\n>   {\n> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,\n>   {\n>   \tstruct child_process cmd = CHILD_PROCESS_INIT;\n>   \n> +\tif (opts->committer_date_is_author_date) {\n> +\t\tsize_t len;\n> +\t\tint res = -1;\n> +\t\tstruct strbuf datebuf = STRBUF_INIT;\n> +\t\tchar *date = read_author_date_or_null();\n> +\n> +\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n> +\t\tfree(date);\n> +\n> +\t\tdate = strbuf_detach(&datebuf, &len);\n> +\n> +\t\tif (len > 1)\n> +\t\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n> +\n> +\t\tfree(date);\n> +\n> +\t\tif (res)\n> +\t\t\treturn -1;\n> +\t}\n>   \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n>   \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n>   \t\tconst char *author = NULL;\n> @@ -1400,7 +1431,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\", NULL };\n>   \t\tconst char *out_enc = get_commit_output_encoding();\n> @@ -1427,6 +1457,21 @@ 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\tsplit_ident_line(&ident, author, len);\n> +\n> +\t\tif (!ident.date_begin)\n> +\t\t\treturn error(_(\"corrupted author without date information\"));\n> +\n> +\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n> +\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n> +\t\tstrbuf_release(&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>   \t\tgoto out;\n> @@ -2542,6 +2587,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> @@ -2624,6 +2674,8 @@ 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->reschedule_failed_exec)\n>   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>   \n> @@ -3821,7 +3873,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 6704acbb9c..e3881e9275 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 2e16e00a9d..b2419a2b75 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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_done\n> \n"},{"id":"380396","messageId":"xmqqsgq5805u.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"7274e753-f75c-ad9a-9c2c-7ba8abc32971@gmail.com","subject":"Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-13T17:06:53Z","receivedAt":"2019-08-13T17:06: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>>   +\tif (opts->committer_date_is_author_date) {\n>> +\t\tsize_t len;\n>> +\t\tint res = -1;\n>> +\t\tstruct strbuf datebuf = STRBUF_INIT;\n>> +\t\tchar *date = read_author_date_or_null();\n>\n> You must always check the return value of functions that might return\n> NULL. In this case we should return an error as you do in try_to\n> _commit() later\n>\n>> +\n>> +\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n>\n> GNU printf() will add something like '(null)' to the buffer if you\n> pass a NULL pointer so I don't think we can be sure that this will not\n> increase the length of the buffer if date is NULL.\n\nAnd an implementation that is not as lenient may outright segfault.\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\tsplit_ident_line(&ident, author, len);\n>> +\n>> +\t\tif (!ident.date_begin)\n>> +\t\t\treturn error(_(\"corrupted author without date information\"));\n>\n> We return an error if we cannot get the date - this is exactly what we\n> should be doing above. It is also great to see a single version of\n> this being used whether or not we are amending.\n>\n>> +\n>> +\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n>\n> I think we should use %s.* and ident.date_end to be sure we getting\n> what we want. Your version is OK if the author is formatted correctly\n> but I'm uneasy about relying on that when we can get the verified end\n> from ident.\n\nIf the author line is not formatted correctly, split_ident_line()\nwould notice and return NULL in these fields, I think (in other\nwords, my take on the call to split_ident_line() above is not\nnecessarily done in order to \"split\", but primarily to validate that\nthe line is formatted correctly---and find the beginning of the\ntimestamp field).\n\nBut your \"pay attention to date_end\" raises an interesting point.\n\nThe string that follows ident.date_begin would be a large integer\n(i.e. number of seconds since epoch), a SP, a positive or negative\nsign (i.e. east or west of GMT), 4 digits (i.e. timezone offset), so\nif you want to leave something like \"@1544328981\" in the buffer, you\nneed to stop at .date_end to omit the timezone information.\n\nOn the other hand, if you do want the timezone information as well\n(which I think is the case for this codepath), you should not stop\nat there and have something like \"@1544328981 +0900\", the code as\nwritten would give better result.\n"},{"id":"380397","messageId":"xmqqo90t7zhl.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"b59f0aa2-1dc3-905a-0094-5f63718dffcf@gmail.com","subject":"Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-13T17:21:26Z","receivedAt":"2019-08-13T17:21:31Z","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>> +static void push_dates(struct child_process *child)\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->args, \"--date=%s\", date.buf);\n>\n> it doesn't matter but it might have been nicer to set both dates the\n> same way in the environment.\n> +\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n\nWe can see that this date string lacks timezone information, which\nwould likely fall back to whatever timezone the user is in.  Is that\nwhat we want?  I am guessing it is, as we are dealing with \"now\"\ntimestamp, but wanted to double check.\n\n>> +\t\t\tif (opts->ignore_date) {\n>> +\t\t\t\tif (!author)\n>> +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n>> +\t\t\t\t\t    \"rebase, which must set the author \"\n>> +\t\t\t\t\t    \"before committing the tree\");\n>> +\t\t\t\tignore_author_date(&author);\n>\n> Is this leaking the old author? I'd rather see\n>\n> \ttmp_author = ignore_author_date(author);\n> \tfree(author);\n> \tauthor = tmp_author;\n\nOr make sure ignore_author_date() does not leak the original, when\nit rewrites its parameter.\n\nBut I have a larger question at the higher design level.  Why are we\npassing a single string \"author\" around, instead of parsed and split\nfields, like <name, email, timestamp, tz> tuple?  That would allow us\nto replace only the time part a lot more easily.  Would it make the\nother parts of the code more cumbersome (I didn't check---and if\nthat is the case, then that is a valid reason why we want to stick\nto the current \"a single string 'author' keeps the necessary info\nfor the 4-tuple\" design).\n\n>> +\t\t\t}\n>>   \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n>>   \t\t\t\t\t  NULL, &root_commit, author,\n>>   \t\t\t\t\t  opts->gpg_sign);\n>> +\t\t}\n>>     \t\tstrbuf_release(&msg);\n>>   \t\tstrbuf_release(&script);\n>> @@ -1053,6 +1087,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);\n>>   \tif (defmsg)\n>>   \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>>   \telse if (!(flags & EDIT_MSG))\n>> @@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,\n>>     \treset_ident_date();\n>>   +\tif (opts->ignore_date) {\n>> +\t\tignore_author_date(&author);\n>> +\t\tfree(author_to_free);\n>\n> Where is author_to_free set? We should always free the old author, see\n> above.\n\nOr require callers to pass a free()able memory to ignore_author_date()\nand have the callee free the original?\n"},{"id":"380398","messageId":"xmqqk1bh7z6f.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20190812194301.5655-7-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-13T17:28:08Z","receivedAt":"2019-08-13T17:28:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n\n> The previous commit introduced --ignore-date flag to interactive\n> rebase, but the name is actually very vague in context of rebase -i\n> since there are two dates we can work with. Add an alias to convey\n> the precise purpose.\n\nThis sounds more like the existing \"--reset-author\" but only takes\nover the timestamp part without taking over the authorship.\n\nIOW, I am wondering if \"--reset-author-date\" is a better name.\n\n"},{"id":"380419","messageId":"xmqqblws7n8r.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20190812194301.5655-6-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-13T21:45:56Z","receivedAt":"2019-08-13T21:46:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n\n>  --ignore-date::\n> -\tThis flag is passed to 'git am' to change the author date\n> -\tof the rebased commits (see linkgit:git-am[1]).\n> +\tInstead of using the given author date, re-set it to the value\n> +\tsame as committer (current) date. This implies --force-rebase.\n\ns/to the value same as .* date\\./the current time./;\n\nThe more important thing is that we record the current timestamp as\nthe author date; that timestamp being very close to the committer\ndate of the resulting commit is a mere consequence of the fact that\nwe use the current time for committer date and much less important.\n\nAgain, I think reset-author-date would be a better synonym to this\none.\n\n"},{"id":"380453","messageId":"0a0a6fd3-933e-c0a4-03c2-8c1c69e5ffca@gmail.com","threadId":"51596","inReplyTo":"xmqqsgq5805u.fsf@gitster-ct.c.googlers.com","subject":"Re: [GSoC][PATCH v2 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-14T18:38:45Z","receivedAt":"2019-08-14T18:38:50Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/08/2019 18:06, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n>  [...]\n>>> +\n>>> +\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n>>\n>> I think we should use %s.* and ident.date_end to be sure we getting\n>> what we want. Your version is OK if the author is formatted correctly\n>> but I'm uneasy about relying on that when we can get the verified end\n>> from ident.\n> \n> If the author line is not formatted correctly, split_ident_line()\n> would notice and return NULL in these fields, I think (in other\n> words, my take on the call to split_ident_line() above is not\n> necessarily done in order to \"split\", but primarily to validate that\n> the line is formatted correctly---and find the beginning of the\n> timestamp field).\n\nI just had a read through split_ident_line() and it looks to me like it \nwill ignore any junk after the timezone. So long as it sees '+' or '-' \nfollowed by at least one digit it will use that for the time zone and \nreturn success regardless of what follows it so I think we want to pay \nattention to the end data it returns for the date and timezone.\n\n> But your \"pay attention to date_end\" raises an interesting point.\n> \n> The string that follows ident.date_begin would be a large integer\n> (i.e. number of seconds since epoch), a SP, a positive or negative\n> sign (i.e. east or west of GMT), 4 digits (i.e. timezone offset), so\n> if you want to leave something like \"@1544328981\" in the buffer, you\n> need to stop at .date_end to omit the timezone information.\n> \n> On the other hand, if you do want the timezone information as well\n> (which I think is the case for this codepath), you should not stop\n> at there and have something like \"@1544328981 +0900\", the code as\n> written would give better result.\n\nGood point, I had forgotten that split_ident_line() returned separate \nfields for the date and timezone. I agree that we want the timezone here \ntoo. I  I think it would be a good idea to beef up the tests to use a \nnon default timezone to check that we are actually setting it correctly.\n\nBest Wishes\n\nPhillip\n\n"},{"id":"380454","messageId":"812513a6-bd83-5830-055f-7c0252e5ecd8@gmail.com","threadId":"51596","inReplyTo":"xmqqo90t7zhl.fsf@gitster-ct.c.googlers.com","subject":"Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-14T18:47:54Z","receivedAt":"2019-08-14T18:48:01Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Junio & Rohit\n\nOn 13/08/2019 18:21, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>>> +static void push_dates(struct child_process *child)\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->args, \"--date=%s\", date.buf);\n>>\n>> it doesn't matter but it might have been nicer to set both dates the\n>> same way in the environment.\n>> +\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n> \n> We can see that this date string lacks timezone information, which\n> would likely fall back to whatever timezone the user is in.  Is that\n> what we want?  I am guessing it is, as we are dealing with \"now\"\n> timestamp, but wanted to double check.\n\nI think we probably want to use the local timezone as you suggest\n\n>>> +\t\t\tif (opts->ignore_date) {\n>>> +\t\t\t\tif (!author)\n>>> +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n>>> +\t\t\t\t\t    \"rebase, which must set the author \"\n>>> +\t\t\t\t\t    \"before committing the tree\");\n>>> +\t\t\t\tignore_author_date(&author);\n>>\n>> Is this leaking the old author? I'd rather see\n>>\n>> \ttmp_author = ignore_author_date(author);\n>> \tfree(author);\n>> \tauthor = tmp_author;\n> \n> Or make sure ignore_author_date() does not leak the original, when\n> it rewrites its parameter.\n> \n> But I have a larger question at the higher design level.  Why are we\n> passing a single string \"author\" around, instead of parsed and split\n> fields, like <name, email, timestamp, tz> tuple?  That would allow us\n> to replace only the time part a lot more easily.  Would it make the\n> other parts of the code more cumbersome (I didn't check---and if\n> that is the case, then that is a valid reason why we want to stick\n> to the current \"a single string 'author' keeps the necessary info\n> for the 4-tuple\" design).\n\nIt's a bit of a mess at the moment. There are places where we want a \nsingle author data string when calling commit_tree_extended(), and other \nplaces where we want to set the name, email and date in the environment \nwhen running 'git commit'. For the latter case we use a file which we \nread and write as the C version just follows what the shell script did. \nI think carrying round a <name, email, timestamp, tz> tuple would be the \nsensible way to go and we can build the author string when we need it. \nDoing that would hopefully eliminate having to read and write the author \nfile so much. I haven't looked at how difficult it would be to change \nthe existing code to do that. We should also really carry the commit \nmessage around in a variable and only write it to a file if a pick fails \nor we are editing the message and running 'git commit'. If we're just \nusing commit_tree_extended() there is no need to be writing the message \nto a file and then reading it back in again later.\n\nBest Wishes\n\nPhillip\n\n>>> +\t\t\t}\n>>>    \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n>>>    \t\t\t\t\t  NULL, &root_commit, author,\n>>>    \t\t\t\t\t  opts->gpg_sign);\n>>> +\t\t}\n>>>      \t\tstrbuf_release(&msg);\n>>>    \t\tstrbuf_release(&script);\n>>> @@ -1053,6 +1087,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);\n>>>    \tif (defmsg)\n>>>    \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>>>    \telse if (!(flags & EDIT_MSG))\n>>> @@ -1515,6 +1551,11 @@ static int try_to_commit(struct repository *r,\n>>>      \treset_ident_date();\n>>>    +\tif (opts->ignore_date) {\n>>> +\t\tignore_author_date(&author);\n>>> +\t\tfree(author_to_free);\n>>\n>> Where is author_to_free set? We should always free the old author, see\n>> above.\n> \n> Or require callers to pass a free()able memory to ignore_author_date()\n> and have the callee free the original?\n> \n"},{"id":"380455","messageId":"c03439bf-54bf-b53d-9400-bdc4dd2a1309@gmail.com","threadId":"51596","inReplyTo":"xmqqblws7n8r.fsf@gitster-ct.c.googlers.com","subject":"Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-14T18:51:15Z","receivedAt":"2019-08-14T18:51:20Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 13/08/2019 22:45, Junio C Hamano wrote:\n> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n> \n>>   --ignore-date::\n>> -\tThis flag is passed to 'git am' to change the author date\n>> -\tof the rebased commits (see linkgit:git-am[1]).\n>> +\tInstead of using the given author date, re-set it to the value\n>> +\tsame as committer (current) date. This implies --force-rebase.\n> \n> s/to the value same as .* date\\./the current time./;\n> \n> The more important thing is that we record the current timestamp as\n> the author date; that timestamp being very close to the committer\n> date of the resulting commit is a mere consequence of the fact that\n> we use the current time for committer date and much less important.\n\nThat's an important distinction, particularly if GIT_COMMITTER_DATE is \nset in the environment - are we aiming to have the author and committer \ndates match or are we just resetting the author date to now? Rohit - do \nyou know which --ignore-date does in the am based rebase?\n\nBest Wishes\n\nPhillip\n\n> \n> Again, I think reset-author-date would be a better synonym to this\n> one.\n> \n"},{"id":"380458","messageId":"xmqq8srv5ypo.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"c03439bf-54bf-b53d-9400-bdc4dd2a1309@gmail.com","subject":"Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-14T19:33:23Z","receivedAt":"2019-08-14T19:33:32Z","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> That's an important distinction, particularly if GIT_COMMITTER_DATE is\n> set in the environment - are we aiming to have the author and\n> committer dates match or are we just resetting the author date to now?\n> Rohit - do you know which --ignore-date does in the am based rebase?\n\nThe purpose \"am --ignore-date\" was to ignore \"Date:\" that came from\nthe patch message, overriding it with the current date.  It might\nhave become harder to read in the C version, but \"git show v2.0.0:git-am.sh\"\nwould be an easier way to read how \"--ignore-date\" wanted to behave.\n\n"},{"id":"380575","messageId":"8104c7e7-e29c-5a41-4097-55912dbe9fc5@gmail.com","threadId":"51596","inReplyTo":"xmqq8srv5ypo.fsf@gitster-ct.c.googlers.com","subject":"Re: [GSoC][PATCH v2 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-17T09:28:55Z","receivedAt":"2019-08-17T09:29:03Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 14/08/2019 20:33, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> That's an important distinction, particularly if GIT_COMMITTER_DATE is\n>> set in the environment - are we aiming to have the author and\n>> committer dates match or are we just resetting the author date to now?\n>> Rohit - do you know which --ignore-date does in the am based rebase?\n> \n> The purpose \"am --ignore-date\" was to ignore \"Date:\" that came from\n> the patch message, overriding it with the current date.  It might\n> have become harder to read in the C version, but \"git show v2.0.0:git-am.sh\"\n> would be an easier way to read how \"--ignore-date\" wanted to behave.\n\nThanks for the pointer, looking at the code I agree that \n--reset-author-date would be a better alias. If GIT_COMMITTER_DATE is \nnot set then the author and committer dates match, otherwise the author \ndate is reset to the current time. The code also shows how we should be \ncombining --ignore-date and --committer-date-is-author-date.\n\nBest Wishes\n\nPhillip\n"},{"id":"380760","messageId":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v3 0/6] rebase -i: support more options","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:29Z","receivedAt":"2019-08-20T03:45:48Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"I've tries to incorporated all the suggestions.\n\nSome points:\n  - According to v2.0.0's git-am.sh, ignore-date should override\n    committer-date-is-author-date. Ergo, we are not barfing out\n    when both flags are provided.\n  - Should the 'const' qualifier be removed[2]? Since it is leaving\n    a false impression that author should not be free()'d.\n\n[1]: git show v2.0.0:git-am.sh\n[2]: https://github.com/git/git/blob/v2.23.0/sequencer.c#L959\n\nRohit Ashiwal (6):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: add NULL checks under read_author_script\n  rebase -i: support --committer-date-is-author-date\n  sequencer: rename amend_author to author_to_rename\n  rebase -i: support --ignore-date\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt            |  26 +++--\n builtin/rebase.c                        |  53 +++++++---\n sequencer.c                             | 135 ++++++++++++++++++++++--\n sequencer.h                             |   2 +\n t/t3422-rebase-incompatible-options.sh  |   2 -\n t/t3433-rebase-options-compatibility.sh | 100 ++++++++++++++++++\n 6 files changed, 289 insertions(+), 29 deletions(-)\n create mode 100755 t/t3433-rebase-options-compatibility.sh\n\nRange-diff:\n1:  4cd0aa3084 ! 1:  e82ed8cad5 rebase -i: add --ignore-whitespace flag\n    @@ -19,10 +19,13 @@\n      default is `--no-fork-point`, otherwise the default is `--fork-point`.\n      \n      --ignore-whitespace::\n    -+\tThis flag is either passed to the 'git apply' program\n    -+\t(see linkgit:git-apply[1]), or to 'git merge' program\n    -+\t(see linkgit:git-merge[1]) as `-Xignore-space-change`,\n    -+\tdepending on which backend is selected by other options.\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    @@ -63,7 +66,7 @@\n      \n      static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n      {\n    -+\tchar *strategy_opts = opts->strategy_opts;\n    ++\tstruct strbuf strategy_buf = STRBUF_INIT;\n      \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n      \n      \treplay.action = REPLAY_INTERACTIVE_REBASE;\n    @@ -71,24 +74,19 @@\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    --\tif (opts->strategy_opts)\n    --\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n    -+\n    -+\tif (opts->ignore_whitespace) {\n    -+\t\tstruct strbuf buf = STRBUF_INIT;\n    -+\n    -+\t\tif (strategy_opts)\n    -+\t\t\tstrbuf_addstr(&buf, strategy_opts);\n     +\n    -+\t\tstrbuf_addstr(&buf, \" --ignore-space-change\");\n    -+\t\tfree(strategy_opts);\n    -+\t\tstrategy_opts = strbuf_detach(&buf, NULL);\n    -+\t}\n    -+\tif (strategy_opts)\n    -+\t\tparse_strategy_opts(&replay, strategy_opts);\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      \treturn replay;\n      }\n    + \n     @@\n      \targc = parse_options(argc, argv, prefix, options,\n      \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n2:  e2c0304587 = 2:  209057b361 sequencer: add NULL checks under read_author_script\n3:  6aed57ae2e ! 3:  a4e6644ef8 rebase -i: support --committer-date-is-author-date\n    @@ -21,10 +21,12 @@\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 the rebased commits (see linkgit:git-am[1]).\n    ++\tof each rebased commit (see linkgit:git-am[1]).\n      +\n      See also INCOMPATIBLE OPTIONS below.\n    + \n     @@\n      \n      The following options:\n    @@ -62,16 +64,6 @@\n      \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n      \treplay.strategy = opts->strategy;\n      \n    -@@\n    - \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n    - \t\t\t  \"--rebase-merges\"));\n    - \n    -+\tif (opts.committer_date_is_author_date)\n    -+\t\topts.flags |= REBASE_FORCE;\n    -+\n    - \treturn !!run_rebase_interactive(&opts, command);\n    - }\n    - \n     @@\n      \n      \tif (opts->ignore_whitespace)\n    @@ -149,14 +141,14 @@\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\tfree(date);\n     +\n     +\t\tdate = strbuf_detach(&datebuf, &len);\n    -+\n    -+\t\tif (len > 1)\n    -+\t\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n    -+\n    ++\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n     +\t\tfree(date);\n     +\n     +\t\tif (res)\n    @@ -187,7 +179,7 @@\n     +\t\tif (!ident.date_begin)\n     +\t\t\treturn error(_(\"corrupted author without date information\"));\n     +\n    -+\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n    ++\t\tstrbuf_addf(&date, \"@%s\", ident.date_begin);\n     +\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n     +\t\tstrbuf_release(&date);\n     +\t}\n4:  36a0c017c2 = 4:  6ac1885c54 sequencer: rename amend_author to author_to_rename\n5:  3a4ffeb995 ! 5:  a69749dd67 rebase -i: support --ignore-date\n    @@ -16,9 +16,9 @@\n      \n      --ignore-date::\n     -\tThis flag is passed to 'git am' to change the author date\n    --\tof the rebased commits (see linkgit:git-am[1]).\n    -+\tInstead of using the given author date, re-set it to the value\n    -+\tsame as committer (current) date. This implies --force-rebase.\n    +-\tof each rebased commit (see linkgit:git-am[1]).\n    ++\tInstead of using the given author date, reset it to the value\n    ++\tsame as the current time. This implies --force-rebase.\n      +\n      See also INCOMPATIBLE OPTIONS below.\n      \n    @@ -58,18 +58,6 @@\n      \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n      \treplay.strategy = opts->strategy;\n      \n    -@@\n    - \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n    - \t\t\t  \"--rebase-merges\"));\n    - \n    --\tif (opts.committer_date_is_author_date)\n    -+\tif (opts.ignore_date)\n    -+\t\topts.committer_date_is_author_date = 0;\n    -+\tif (opts.committer_date_is_author_date ||\n    -+\t    opts.ignore_date)\n    - \t\topts.flags |= REBASE_FORCE;\n    - \n    - \treturn !!run_rebase_interactive(&opts, command);\n     @@\n      \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n      \tif (opts->committer_date_is_author_date)\n    @@ -125,18 +113,19 @@\n      \treturn buf->buf;\n      }\n      \n    -+static void ignore_author_date(const char **author)\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 = strlen(author);\n     +\tstruct ident_split ident;\n     +\tstruct strbuf new_author = STRBUF_INIT;\n     +\n    -+\tsplit_ident_line(&ident, *author, len);\n    ++\tsplit_ident_line(&ident, author, len);\n     +\tlen = ident.mail_end - ident.name_begin + 1;\n     +\n    -+\tstrbuf_addf(&new_author, \"%.*s\", len, *author);\n    ++\tstrbuf_addf(&new_author, \"%.*s \", len, author);\n     +\tdatestamp(&new_author);\n    -+\t*author = strbuf_detach(&new_author, NULL);\n    ++\treturn strbuf_detach(&new_author, NULL);\n     +}\n     +\n     +static void push_dates(struct child_process *child)\n    @@ -160,11 +149,13 @@\n     -\t\telse\n     +\t\telse {\n     +\t\t\tif (opts->ignore_date) {\n    ++\t\t\t\tchar *new_author = ignore_author_date(author);\n     +\t\t\t\tif (!author)\n     +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n     +\t\t\t\t\t    \"rebase, which must set the author \"\n     +\t\t\t\t\t    \"before committing the tree\");\n    -+\t\t\t\tignore_author_date(&author);\n    ++\t\t\t\tfree((void *)author);\n    ++\t\t\t\tauthor = new_author;\n     +\t\t\t}\n      \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n      \t\t\t\t\t  NULL, &root_commit, author,\n    @@ -187,7 +178,7 @@\n      \treset_ident_date();\n      \n     +\tif (opts->ignore_date) {\n    -+\t\tignore_author_date(&author);\n    ++\t\tauthor = ignore_author_date(author);\n     +\t\tfree(author_to_free);\n     +\t\tauthor_to_free = (char *)author;\n     +\t}\n6:  cb81e6c4e5 ! 6:  210d15cca0 rebase: add --author-date-is-committer-date\n    @@ -1,6 +1,6 @@\n     Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n     \n    -    rebase: add --author-date-is-committer-date\n    +    rebase: add --reset-author-date\n     \n         The previous commit introduced --ignore-date flag to interactive\n         rebase, but the name is actually very vague in context of rebase -i\n    @@ -16,9 +16,9 @@\n      \tas the committer date. This implies --force-rebase.\n      \n      --ignore-date::\n    -+--author-date-is-committer-date::\n    - \tInstead of using the given author date, re-set it to the value\n    - \tsame as committer (current) date. This implies --force-rebase.\n    ++--reset-author-date::\n    + \tInstead of using the given author date, reset it to the value\n    + \tsame as the current time. This implies --force-rebase.\n      +\n     \n      diff --git a/builtin/rebase.c b/builtin/rebase.c\n    @@ -28,7 +28,7 @@\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, \"author-date-is-committer-date\", &options.ignore_date,\n    ++\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n     +\t\t\t \"ignore author date and use current date\"),\n      \t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n      \t\t\t \"ignore author date and use current date\"),\n-- \n2.21.0\n\n"},{"id":"380761","messageId":"20190820034536.13071-2-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v3 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:30Z","receivedAt":"2019-08-20T03:45:51Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"There are two backends available for rebasing, viz, the am and the\ninteractive. Naturally, there shall be some features that are\nimplemented in one but not in the other. One such flag is\n--ignore-whitespace which indicates merge mechanism to treat lines\nwith only whitespace changes as unchanged. Wire the interactive\nrebase to also understand the --ignore-whitespace flag by\ntranslating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 13 ++++-\n builtin/rebase.c                        | 22 +++++++--\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n 4 files changed, 94 insertions(+), 7 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 6156609cf7..873eb5768c 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -371,8 +371,16 @@ 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 \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@@ -520,7 +528,6 @@ The following options:\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@@ -543,6 +550,8 @@ 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+ * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 670096c065..f8a618d54c 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -79,6 +79,7 @@ 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 \tchar *cmd;\n@@ -99,6 +100,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@@ -114,9 +116,15 @@ 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+\tstrbuf_release(&strategy_buf);\n \treturn replay;\n }\n \n@@ -511,6 +519,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@@ -964,6 +974,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@@ -1407,9 +1419,6 @@ 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@@ -1417,6 +1426,8 @@ 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\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@@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (options.rebase_merges) {\n+\t\tif (options.ignore_whitespace)\n+\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n+\t\t\t      \"'--ignore-whitespace'\"));\n \t\tif (strategy_options.nr)\n \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n \t\t\t      \"'--strategy-option'\"));\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nnew file mode 100755\nindex 0000000000..2e16e00a9d\n--- /dev/null\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -0,0 +1,65 @@\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+# 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 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_done\n-- \n2.21.0\n\n"},{"id":"380762","messageId":"20190820034536.13071-3-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v3 2/6] sequencer: add NULL checks under read_author_script","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:31Z","receivedAt":"2019-08-20T03:45:54Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"read_author_script reads name, email and author date from the author\nscript. However, it does not check if the arguments are NULL. Adding\nNULL checks will allow us to selectively get the required value, for\nexample:\n\n    char *date;\n    if (read_author_script(_path_, NULL, NULL, &date, _int_))\n\t    die(_(\"failed to read author date\"));\n    /* needs to be free()'d */\n    return date;\n\nAdd NULL checks for better control over the information retrieved.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 16 +++++++++++++---\n 1 file changed, 13 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 34ebf8ed94..30d77c2682 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -824,9 +824,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-- \n2.21.0\n\n"},{"id":"380763","messageId":"20190820034536.13071-4-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v3 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:32Z","receivedAt":"2019-08-20T03:45:59Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the committer date\nby changing it to the author date. Let's add the same for\ninteractive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 10 +++--\n builtin/rebase.c                        | 17 +++++---\n sequencer.c                             | 57 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 19 +++++++++\n 6 files changed, 94 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 873eb5768c..e7c0eac18c 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -386,9 +386,13 @@ unchanged for the sake of a three-way merge.\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+\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@@ -525,7 +529,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -551,6 +554,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 --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex f8a618d54c..656bc7d7e9 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -82,6 +82,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@@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -976,6 +979,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@@ -1419,9 +1424,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@@ -1692,10 +1697,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\ndiff --git a/sequencer.c b/sequencer.c\nindex 30d77c2682..29b67bc1ae 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -147,6 +147,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@@ -879,6 +880,17 @@ 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 /* Read author-script and return an ident line (author <email> timestamp) */\n static const char *read_author_ident(struct strbuf *buf)\n {\n@@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,\n {\n \tstruct child_process cmd = CHILD_PROCESS_INIT;\n \n+\tif (opts->committer_date_is_author_date) {\n+\t\tsize_t len;\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\tfree(date);\n+\n+\t\tdate = strbuf_detach(&datebuf, &len);\n+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n+\t\tfree(date);\n+\n+\t\tif (res)\n+\t\t\treturn -1;\n+\t}\n \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n \t\tconst char *author = NULL;\n@@ -1400,7 +1431,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\", NULL };\n \t\tconst char *out_enc = get_commit_output_encoding();\n@@ -1427,6 +1457,21 @@ 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\tsplit_ident_line(&ident, author, len);\n+\n+\t\tif (!ident.date_begin)\n+\t\t\treturn error(_(\"corrupted author without date information\"));\n+\n+\t\tstrbuf_addf(&date, \"@%s\", ident.date_begin);\n+\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n+\t\tstrbuf_release(&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 \t\tgoto out;\n@@ -2542,6 +2587,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@@ -2624,6 +2674,8 @@ 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->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3821,7 +3873,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 6704acbb9c..e3881e9275 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 2e16e00a9d..b2419a2b75 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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@@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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_done\n-- \n2.21.0\n\n"},{"id":"380764","messageId":"20190820034536.13071-5-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v3 4/6] sequencer: rename amend_author to author_to_rename","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:33Z","receivedAt":"2019-08-20T03:46:02Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() while 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 29b67bc1ae..8f7b984333 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1424,7 +1424,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@@ -1445,7 +1445,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@@ -1534,7 +1534,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.21.0\n\n"},{"id":"380765","messageId":"20190820034536.13071-6-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v3 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:34Z","receivedAt":"2019-08-20T03:46:06Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the author date\nby changing it to the committer (current) date. Let's add the same\nfor interactive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            |  6 +--\n builtin/rebase.c                        | 16 ++++---\n sequencer.c                             | 58 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3433-rebase-options-compatibility.sh | 16 +++++++\n 5 files changed, 87 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e7c0eac18c..e7ac9fae0b 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This 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 value\n+\tsame as the current time. This implies --force-rebase.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:\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  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 656bc7d7e9..a63531ee90 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -83,6 +83,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@@ -117,6 +118,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@@ -981,6 +983,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@@ -1427,8 +1431,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@@ -1697,13 +1701,15 @@ 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+\tif (options.ignore_date)\n+\t\toptions.committer_date_is_author_date = 0;\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, \"--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 8f7b984333..f5a9590844 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -148,6 +148,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@@ -919,6 +920,32 @@ static const char *read_author_ident(struct strbuf *buf)\n \treturn buf->buf;\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+\tsplit_ident_line(&ident, author, len);\n+\tlen = ident.mail_end - ident.name_begin + 1;\n+\n+\tstrbuf_addf(&new_author, \"%.*s \", len, author);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n+static void push_dates(struct child_process *child)\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->args, \"--date=%s\", date.buf);\n+\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@@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,\n \n \t\tif (res <= 0)\n \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n-\t\telse\n+\t\telse {\n+\t\t\tif (opts->ignore_date) {\n+\t\t\t\tchar *new_author = ignore_author_date(author);\n+\t\t\t\tif (!author)\n+\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n+\t\t\t\t\t    \"rebase, which must set the author \"\n+\t\t\t\t\t    \"before committing the tree\");\n+\t\t\t\tfree((void *)author);\n+\t\t\t\tauthor = new_author;\n+\t\t\t}\n \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n \t\t\t\t\t  NULL, &root_commit, author,\n \t\t\t\t\t  opts->gpg_sign);\n+\t\t}\n \n \t\tstrbuf_release(&msg);\n \t\tstrbuf_release(&script);\n@@ -1053,6 +1090,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);\n \tif (defmsg)\n \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n \telse if (!(flags & EDIT_MSG))\n@@ -1515,6 +1554,11 @@ 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\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@@ -2592,6 +2636,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@@ -2676,6 +2725,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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@@ -3601,6 +3652,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);\n \n \t\t/* Add the tips to be merged */\n \t\tfor (j = to_merge; j; j = j->next)\n@@ -3874,7 +3927,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 e3881e9275..bf5a79afdb 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex b2419a2b75..c060fcd10b 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n \ttest_cmp authortime committertime\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 test_done\n-- \n2.21.0\n\n"},{"id":"380766","messageId":"20190820034536.13071-7-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"[GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:35Z","receivedAt":"2019-08-20T03:46:09Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The previous commit introduced --ignore-date flag to interactive\nrebase, but the name is actually very vague in context of rebase -i\nsince there are two dates we can work with. Add an alias to convey\nthe precise purpose.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt | 1 +\n builtin/rebase.c             | 2 ++\n 2 files changed, 3 insertions(+)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 24ad2dda0b..6a52d721e2 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -388,6 +388,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n+--author-date-is-committer-date::\n \tInstead of using the given author date, re-set it to the value\n \tsame as committer (current) date. This implies --force-rebase.\n +\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex ed58ca8e5a..19b1fc0f3a 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1442,6 +1442,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_BOOL(0, \"author-date-is-committer-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current 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_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n-- \n2.21.0\n\n"},{"id":"380767","messageId":"20190820034536.13071-8-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v3 6/6] rebase: add --reset-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:45:36Z","receivedAt":"2019-08-20T03:46:13Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The previous commit introduced --ignore-date flag to interactive\nrebase, but the name is actually very vague in context of rebase -i\nsince there are two dates we can work with. Add an alias to convey\nthe precise purpose.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt | 1 +\n builtin/rebase.c             | 2 ++\n 2 files changed, 3 insertions(+)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e7ac9fae0b..ec62ba36b8 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -391,6 +391,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the given author date, reset it to the value\n \tsame as the current time. This implies --force-rebase.\n +\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex a63531ee90..dcf758845b 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1431,6 +1431,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_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current 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_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n-- \n2.21.0\n\n"},{"id":"380769","messageId":"CAL7ArXpKggCm2Ex0Kk3m+jDbfd3roCYmj=6DFG=k-1kJm-j+tA@mail.gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v3 0/6] rebase -i: support more options","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T03:54:44Z","receivedAt":"2019-08-20T03:55:24Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"On Tue, Aug 20, 2019 at 9:15 AM Rohit Ashiwal\n<rohit.ashiwal265@gmail.com> wrote:\n>\n> I've tries to incorporated all the suggestions.\n\nI've tried to incorporate all the suggestions.\n"},{"id":"380770","messageId":"20190820040036.14798-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-7-rohit.ashiwal265@gmail.com","subject":"Re: [GSoC][PATCH v2 6/6] rebase: add --author-date-is-committer-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T04:00:36Z","receivedAt":"2019-08-20T04:00:45Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Hi Everyone\n\nPlease ignore this patch. I forgot to clean the output dir before\nsending this iteration.\n\nThanks\nRohit\n\n"},{"id":"380799","messageId":"a3e329b6-51e6-af2a-b512-cba71be95a1e@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-4-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v3 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-20T13:32:29Z","receivedAt":"2019-08-20T13:32:37Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOne thing that struck we was that we should support this with rebase -r \nwhich means setting GIT_COMMITTER_DATE when we fork 'git merge'. I've \ngot a couple of other comments below\n\nOn 20/08/2019 04:45, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            | 10 +++--\n>   builtin/rebase.c                        | 17 +++++---\n>   sequencer.c                             | 57 ++++++++++++++++++++++++-\n>   sequencer.h                             |  1 +\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 19 +++++++++\n>   6 files changed, 94 insertions(+), 11 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 873eb5768c..e7c0eac18c 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -386,9 +386,13 @@ unchanged for the sake of a three-way merge.\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> +\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> @@ -525,7 +529,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --committer-date-is-author-date\n>    * --ignore-date\n>    * --whitespace\n>    * -C\n> @@ -551,6 +554,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 --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index f8a618d54c..656bc7d7e9 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -82,6 +82,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> @@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>   \treplay.strategy = opts->strategy;\n>   \n> @@ -976,6 +979,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> @@ -1419,9 +1424,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> @@ -1692,10 +1697,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\n> diff --git a/sequencer.c b/sequencer.c\n> index 30d77c2682..29b67bc1ae 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -147,6 +147,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> @@ -879,6 +880,17 @@ 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>   /* Read author-script and return an ident line (author <email> timestamp) */\n>   static const char *read_author_ident(struct strbuf *buf)\n>   {\n> @@ -964,6 +976,25 @@ static int run_git_commit(struct repository *r,\n>   {\n>   \tstruct child_process cmd = CHILD_PROCESS_INIT;\n>   \n> +\tif (opts->committer_date_is_author_date) {\n> +\t\tsize_t len;\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\nIt is good to this this new error checking\n\n> +\n> +\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n> +\t\tfree(date);\n> +\n> +\t\tdate = strbuf_detach(&datebuf, &len);\n> +\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n> +\t\tfree(date);\n\nThis could be simplified slightly by doing\n\tres = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf. 1);\n\tstrbuf_release(&datebuf);\n\n> +\n> +\t\tif (res)\n> +\t\t\treturn -1;\n> +\t}\n>   \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n>   \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n>   \t\tconst char *author = NULL;\n> @@ -1400,7 +1431,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\", NULL };\n>   \t\tconst char *out_enc = get_commit_output_encoding();\n> @@ -1427,6 +1457,21 @@ 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\tsplit_ident_line(&ident, author, len);\n> +\n> +\t\tif (!ident.date_begin)\n> +\t\t\treturn error(_(\"corrupted author without date information\"));\n\nI had to read the source of split_ident_line() to check this was safe, I \nthink it is better to use the return value to check for errors  - a \nquick greps shows that this is what all the other callers do.\n\n> +\n> +\t\tstrbuf_addf(&date, \"@%s\", ident.date_begin);\n\nI still think this will pass any junk after a corrupted timezone, it \nwould be better to do\n\n\tstrbuf_addf(&date, \"@%.*s %.*s\", ident.date_begin, ident.data_end - \nident.date_begin, ident.tz_begin, ident.tz_end - ident.tz_begin);\n\n> +\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n\nThe code above (in run_git_commit()) checks the return value of setenv() \nand returns an error if it failed should this be doing the same?\n\nBest Wishes\n\nPhillip\n\n> +\t\tstrbuf_release(&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>   \t\tgoto out;\n> @@ -2542,6 +2587,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> @@ -2624,6 +2674,8 @@ 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->reschedule_failed_exec)\n>   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>   \n> @@ -3821,7 +3873,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 6704acbb9c..e3881e9275 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 2e16e00a9d..b2419a2b75 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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> @@ -62,4 +65,20 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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_done\n> \n"},{"id":"380800","messageId":"ca047519-7226-a94b-9ec6-d5e23b6cf31d@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-6-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v3 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-20T13:45:38Z","receivedAt":"2019-08-20T13:45:44Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 20/08/2019 04:45, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            |  6 +--\n>   builtin/rebase.c                        | 16 ++++---\n>   sequencer.c                             | 58 ++++++++++++++++++++++++-\n>   sequencer.h                             |  1 +\n>   t/t3433-rebase-options-compatibility.sh | 16 +++++++\n>   5 files changed, 87 insertions(+), 10 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index e7c0eac18c..e7ac9fae0b 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.\n>   \tas the committer date. This 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 value\n> +\tsame as the current time. This implies --force-rebase.\n>   +\n>   See also INCOMPATIBLE OPTIONS below.\n>   \n> @@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --ignore-date\n>    * --whitespace\n>    * -C\n>   \n> @@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:\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>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 656bc7d7e9..a63531ee90 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -83,6 +83,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> @@ -117,6 +118,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> @@ -981,6 +983,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> @@ -1427,8 +1431,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> @@ -1697,13 +1701,15 @@ 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> +\tif (options.ignore_date)\n> +\t\toptions.committer_date_is_author_date = 0;\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, \"--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)) {\n> diff --git a/sequencer.c b/sequencer.c\n> index 8f7b984333..f5a9590844 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -148,6 +148,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> @@ -919,6 +920,32 @@ static const char *read_author_ident(struct strbuf *buf)\n>   \treturn buf->buf;\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> +\tsplit_ident_line(&ident, author, len);\n\nYou need to check the return value whenever you call split_ident_line(). \nIn this case doing so would avoid using NULL pointers below if the \nauthor is corrupted.\n\n> +\tlen = ident.mail_end - ident.name_begin + 1;\n> +\n> +\tstrbuf_addf(&new_author, \"%.*s \", len, author);\n> +\tdatestamp(&new_author);\n> +\treturn strbuf_detach(&new_author, NULL);\n> +}\n\nI think this is clearer now it returns the new author\n\n> +\n> +static void push_dates(struct child_process *child)\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->args, \"--date=%s\", date.buf);\n> +\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n\nLooking at the code in builtin/am.c it is quite clear how it handles the \ncombination of --ignore-date and --committer-date-is-author date is it \nsets GIT_COMMITTER_DATE in a single place. Here we've got two separate \npieces of code one from patch 3 the other added here. This \nimplementation differs from the one in builtin/am.c if --ignore-date is \ngiven when GIT_COMMITTER_DATE is set in the environment and \n--committer-date-is-author-date is not given.\n\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> @@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,\n>   \n>   \t\tif (res <= 0)\n>   \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n> -\t\telse\n> +\t\telse {\n> +\t\t\tif (opts->ignore_date) {\n> +\t\t\t\tchar *new_author = ignore_author_date(author);\n> +\t\t\t\tif (!author)\n> +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n> +\t\t\t\t\t    \"rebase, which must set the author \"\n> +\t\t\t\t\t    \"before committing the tree\");\n> +\t\t\t\tfree((void *)author);\n> +\t\t\t\tauthor = new_author;\n> +\t\t\t}\n>   \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n>   \t\t\t\t\t  NULL, &root_commit, author,\n>   \t\t\t\t\t  opts->gpg_sign);\n> +\t\t}\n>   \n>   \t\tstrbuf_release(&msg);\n>   \t\tstrbuf_release(&script);\n> @@ -1053,6 +1090,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);\n>   \tif (defmsg)\n>   \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>   \telse if (!(flags & EDIT_MSG))\n> @@ -1515,6 +1554,11 @@ 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\tfree(author_to_free);\n> +\t\tauthor_to_free = (char *)author;\n> +\t}\n\nThe memory handling is much clearer now\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> @@ -2592,6 +2636,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> @@ -2676,6 +2725,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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> @@ -3601,6 +3652,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);\n>   \n>   \t\t/* Add the tips to be merged */\n>   \t\tfor (j = to_merge; j; j = j->next)\n> @@ -3874,7 +3927,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 e3881e9275..bf5a79afdb 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index b2419a2b75..c060fcd10b 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -81,4 +81,20 @@ test_expect_success '--committer-date-is-author-date works with interactive back\n>   \ttest_cmp authortime committertime\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\nI'm still worried that this will hide some breakage in the future. Can \nwe add a test for rebase -r as well to check that code please.\n\nBest Wishes\n\nPhillip\n\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>   test_done\n> \n"},{"id":"380801","messageId":"71c313d7-e08d-f62f-c52e-aabca0d97002@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-1-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v3 0/6] rebase -i: support more options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-20T13:56:06Z","receivedAt":"2019-08-20T13:56:12Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 20/08/2019 04:45, Rohit Ashiwal wrote:\n> I've tries to incorporated all the suggestions.\n\nIt is helpful if you can list the changes to remind us all what we said. \n(as a patch author I find composing that is helpful to remind me if \nthere's anything I've forgotten to address)\n\nAlso there are a couple of things that were discussed such as splitting \nup the author and passing it round as a <name, email, date, tz> tuple \nand testing a non-default timezone which aren't included - that's fine \nbut it helps if you take a moment to explain why in the cover letter.\n\n> \n> Some points:\n>    - According to v2.0.0's git-am.sh, ignore-date should override\n>      committer-date-is-author-date. Ergo, we are not barfing out\n>      when both flags are provided.\n>    - Should the 'const' qualifier be removed[2]? Since it is leaving\n>      a false impression that author should not be free()'d.\n\nThe author returned by read_author_ident() is owned by the strbuf that \nyou pass to read_author_ident() which is confusing.\n\nBest Wishes\n\nPhillip\n\n> \n> [1]: git show v2.0.0:git-am.sh\n> [2]: https://github.com/git/git/blob/v2.23.0/sequencer.c#L959\n> \n> Rohit Ashiwal (6):\n>    rebase -i: add --ignore-whitespace flag\n>    sequencer: add NULL checks under read_author_script\n>    rebase -i: support --committer-date-is-author-date\n>    sequencer: rename amend_author to author_to_rename\n>    rebase -i: support --ignore-date\n>    rebase: add --reset-author-date\n> \n>   Documentation/git-rebase.txt            |  26 +++--\n>   builtin/rebase.c                        |  53 +++++++---\n>   sequencer.c                             | 135 ++++++++++++++++++++++--\n>   sequencer.h                             |   2 +\n>   t/t3422-rebase-incompatible-options.sh  |   2 -\n>   t/t3433-rebase-options-compatibility.sh | 100 ++++++++++++++++++\n>   6 files changed, 289 insertions(+), 29 deletions(-)\n>   create mode 100755 t/t3433-rebase-options-compatibility.sh\n> \n> Range-diff:\n> 1:  4cd0aa3084 ! 1:  e82ed8cad5 rebase -i: add --ignore-whitespace flag\n>      @@ -19,10 +19,13 @@\n>        default is `--no-fork-point`, otherwise the default is `--fork-point`.\n>        \n>        --ignore-whitespace::\n>      -+\tThis flag is either passed to the 'git apply' program\n>      -+\t(see linkgit:git-apply[1]), or to 'git merge' program\n>      -+\t(see linkgit:git-merge[1]) as `-Xignore-space-change`,\n>      -+\tdepending on which backend is selected by other options.\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>      @@ -63,7 +66,7 @@\n>        \n>        static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n>        {\n>      -+\tchar *strategy_opts = opts->strategy_opts;\n>      ++\tstruct strbuf strategy_buf = STRBUF_INIT;\n>        \tstruct replay_opts replay = REPLAY_OPTS_INIT;\n>        \n>        \treplay.action = REPLAY_INTERACTIVE_REBASE;\n>      @@ -71,24 +74,19 @@\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>      --\tif (opts->strategy_opts)\n>      --\t\tparse_strategy_opts(&replay, opts->strategy_opts);\n>      -+\n>      -+\tif (opts->ignore_whitespace) {\n>      -+\t\tstruct strbuf buf = STRBUF_INIT;\n>      -+\n>      -+\t\tif (strategy_opts)\n>      -+\t\t\tstrbuf_addstr(&buf, strategy_opts);\n>       +\n>      -+\t\tstrbuf_addstr(&buf, \" --ignore-space-change\");\n>      -+\t\tfree(strategy_opts);\n>      -+\t\tstrategy_opts = strbuf_detach(&buf, NULL);\n>      -+\t}\n>      -+\tif (strategy_opts)\n>      -+\t\tparse_strategy_opts(&replay, strategy_opts);\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>        \treturn replay;\n>        }\n>      +\n>       @@\n>        \targc = parse_options(argc, argv, prefix, options,\n>        \t\t\tbuiltin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);\n> 2:  e2c0304587 = 2:  209057b361 sequencer: add NULL checks under read_author_script\n> 3:  6aed57ae2e ! 3:  a4e6644ef8 rebase -i: support --committer-date-is-author-date\n>      @@ -21,10 +21,12 @@\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 the rebased commits (see linkgit:git-am[1]).\n>      ++\tof each rebased commit (see linkgit:git-am[1]).\n>        +\n>        See also INCOMPATIBLE OPTIONS below.\n>      +\n>       @@\n>        \n>        The following options:\n>      @@ -62,16 +64,6 @@\n>        \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>        \treplay.strategy = opts->strategy;\n>        \n>      -@@\n>      - \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n>      - \t\t\t  \"--rebase-merges\"));\n>      -\n>      -+\tif (opts.committer_date_is_author_date)\n>      -+\t\topts.flags |= REBASE_FORCE;\n>      -+\n>      - \treturn !!run_rebase_interactive(&opts, command);\n>      - }\n>      -\n>       @@\n>        \n>        \tif (opts->ignore_whitespace)\n>      @@ -149,14 +141,14 @@\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\tfree(date);\n>       +\n>       +\t\tdate = strbuf_detach(&datebuf, &len);\n>      -+\n>      -+\t\tif (len > 1)\n>      -+\t\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n>      -+\n>      ++\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n>       +\t\tfree(date);\n>       +\n>       +\t\tif (res)\n>      @@ -187,7 +179,7 @@\n>       +\t\tif (!ident.date_begin)\n>       +\t\t\treturn error(_(\"corrupted author without date information\"));\n>       +\n>      -+\t\tstrbuf_addf(&date, \"@%s\",ident.date_begin);\n>      ++\t\tstrbuf_addf(&date, \"@%s\", ident.date_begin);\n>       +\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\n>       +\t\tstrbuf_release(&date);\n>       +\t}\n> 4:  36a0c017c2 = 4:  6ac1885c54 sequencer: rename amend_author to author_to_rename\n> 5:  3a4ffeb995 ! 5:  a69749dd67 rebase -i: support --ignore-date\n>      @@ -16,9 +16,9 @@\n>        \n>        --ignore-date::\n>       -\tThis flag is passed to 'git am' to change the author date\n>      --\tof the rebased commits (see linkgit:git-am[1]).\n>      -+\tInstead of using the given author date, re-set it to the value\n>      -+\tsame as committer (current) date. This implies --force-rebase.\n>      +-\tof each rebased commit (see linkgit:git-am[1]).\n>      ++\tInstead of using the given author date, reset it to the value\n>      ++\tsame as the current time. This implies --force-rebase.\n>        +\n>        See also INCOMPATIBLE OPTIONS below.\n>        \n>      @@ -58,18 +58,6 @@\n>        \treplay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>        \treplay.strategy = opts->strategy;\n>        \n>      -@@\n>      - \t\twarning(_(\"--[no-]rebase-cousins has no effect without \"\n>      - \t\t\t  \"--rebase-merges\"));\n>      -\n>      --\tif (opts.committer_date_is_author_date)\n>      -+\tif (opts.ignore_date)\n>      -+\t\topts.committer_date_is_author_date = 0;\n>      -+\tif (opts.committer_date_is_author_date ||\n>      -+\t    opts.ignore_date)\n>      - \t\topts.flags |= REBASE_FORCE;\n>      -\n>      - \treturn !!run_rebase_interactive(&opts, command);\n>       @@\n>        \t\targv_array_push(&am.args, \"--ignore-whitespace\");\n>        \tif (opts->committer_date_is_author_date)\n>      @@ -125,18 +113,19 @@\n>        \treturn buf->buf;\n>        }\n>        \n>      -+static void ignore_author_date(const char **author)\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 = strlen(author);\n>       +\tstruct ident_split ident;\n>       +\tstruct strbuf new_author = STRBUF_INIT;\n>       +\n>      -+\tsplit_ident_line(&ident, *author, len);\n>      ++\tsplit_ident_line(&ident, author, len);\n>       +\tlen = ident.mail_end - ident.name_begin + 1;\n>       +\n>      -+\tstrbuf_addf(&new_author, \"%.*s\", len, *author);\n>      ++\tstrbuf_addf(&new_author, \"%.*s \", len, author);\n>       +\tdatestamp(&new_author);\n>      -+\t*author = strbuf_detach(&new_author, NULL);\n>      ++\treturn strbuf_detach(&new_author, NULL);\n>       +}\n>       +\n>       +static void push_dates(struct child_process *child)\n>      @@ -160,11 +149,13 @@\n>       -\t\telse\n>       +\t\telse {\n>       +\t\t\tif (opts->ignore_date) {\n>      ++\t\t\t\tchar *new_author = ignore_author_date(author);\n>       +\t\t\t\tif (!author)\n>       +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n>       +\t\t\t\t\t    \"rebase, which must set the author \"\n>       +\t\t\t\t\t    \"before committing the tree\");\n>      -+\t\t\t\tignore_author_date(&author);\n>      ++\t\t\t\tfree((void *)author);\n>      ++\t\t\t\tauthor = new_author;\n>       +\t\t\t}\n>        \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n>        \t\t\t\t\t  NULL, &root_commit, author,\n>      @@ -187,7 +178,7 @@\n>        \treset_ident_date();\n>        \n>       +\tif (opts->ignore_date) {\n>      -+\t\tignore_author_date(&author);\n>      ++\t\tauthor = ignore_author_date(author);\n>       +\t\tfree(author_to_free);\n>       +\t\tauthor_to_free = (char *)author;\n>       +\t}\n> 6:  cb81e6c4e5 ! 6:  210d15cca0 rebase: add --author-date-is-committer-date\n>      @@ -1,6 +1,6 @@\n>       Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n>       \n>      -    rebase: add --author-date-is-committer-date\n>      +    rebase: add --reset-author-date\n>       \n>           The previous commit introduced --ignore-date flag to interactive\n>           rebase, but the name is actually very vague in context of rebase -i\n>      @@ -16,9 +16,9 @@\n>        \tas the committer date. This implies --force-rebase.\n>        \n>        --ignore-date::\n>      -+--author-date-is-committer-date::\n>      - \tInstead of using the given author date, re-set it to the value\n>      - \tsame as committer (current) date. This implies --force-rebase.\n>      ++--reset-author-date::\n>      + \tInstead of using the given author date, reset it to the value\n>      + \tsame as the current time. This implies --force-rebase.\n>        +\n>       \n>        diff --git a/builtin/rebase.c b/builtin/rebase.c\n>      @@ -28,7 +28,7 @@\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, \"author-date-is-committer-date\", &options.ignore_date,\n>      ++\t\tOPT_BOOL(0, \"reset-author-date\", &options.ignore_date,\n>       +\t\t\t \"ignore author date and use current date\"),\n>        \t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n>        \t\t\t \"ignore author date and use current date\"),\n> \n"},{"id":"380818","messageId":"xmqqwof7vim6.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20190820034536.13071-6-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v3 5/6] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-20T17:42:25Z","receivedAt":"2019-08-20T17:42:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@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\nMental note: ignore_author_date() would not allow author==NULL as its input.\n\n> @@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,\n>  \n>  \t\tif (res <= 0)\n>  \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n> -\t\telse\n> +\t\telse {\n> +\t\t\tif (opts->ignore_date) {\n> +\t\t\t\tchar *new_author = ignore_author_date(author);\n> +\t\t\t\tif (!author)\n> +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n> +\t\t\t\t\t    \"rebase, which must set the author \"\n> +\t\t\t\t\t    \"before committing the tree\");\n\nYet, author is used and then checked for NULL-ness, which is\nbackwards.  Before we have a chance to issue this BUG(), we would\nalready have segfaulted inside ignore_author_date().\n\n"},{"id":"380821","messageId":"xmqqsgpvvi3s.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"71c313d7-e08d-f62f-c52e-aabca0d97002@gmail.com","subject":"Re: [PATCH v3 0/6] rebase -i: support more options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-20T17:53:27Z","receivedAt":"2019-08-20T17:53:35Z","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> Hi Rohit\n>\n> On 20/08/2019 04:45, Rohit Ashiwal wrote:\n>> I've tries to incorporated all the suggestions.\n>\n> It is helpful if you can list the changes to remind us all what we\n> said. (as a patch author I find composing that is helpful to remind me\n> if there's anything I've forgotten to address)\n>\n> Also there are a couple of things that were discussed such as\n> splitting up the author and passing it round as a <name, email, date,\n> tz> tuple and testing a non-default timezone which aren't included -\n> that's fine but it helps if you take a moment to explain why in the\n> cover letter.\n>\n>>\n>> Some points:\n>>    - According to v2.0.0's git-am.sh, ignore-date should override\n>>      committer-date-is-author-date. Ergo, we are not barfing out\n>>      when both flags are provided.\n>>    - Should the 'const' qualifier be removed[2]? Since it is leaving\n>>      a false impression that author should not be free()'d.\n>\n> The author returned by read_author_ident() is owned by the strbuf that\n> you pass to read_author_ident() which is confusing.\n>\n> Best Wishes\n>\n> Phillip\n\nI've looked at this round, but will push out v2 for today's\nintegration cycle, mostly due to lack of time, but there do not seem\nto be great difference between the iterations.\n\nThe \"ignore-date\" step conflicts semantically with b0a31861\n(\"sequencer: simplify root commit creation\", 2019-08-19) but in a\ngood way.  Without the clean-up b0a31861 makes, we need to munge the\ntimestamp in two places, but with it, there is only one place that\nneeds to modify the timestamp for the feature (in try_to_commit()).\n\nYou may want to see if these \"more options\" topic can take advantage\nof the \"simplify root commit creation\" by building on top of some\nform of it (I do not know offhand if b0a31861 (\"sequencer: simplify\nroot commit creation\", 2019-08-19) must build on other two patches\nto fix \"rebase -i\" or it can be split out as an independent\nclean-up), and if it is feasible, work with your student to make it\nhappen, perhaps?\n\nThanks.\n\n"},{"id":"380827","messageId":"3bdbcc74-0252-3d07-02b9-84789386fec6@gmail.com","threadId":"51596","inReplyTo":"xmqqwof7vim6.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-20T18:30:54Z","receivedAt":"2019-08-20T18:30:59Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 20/08/2019 18:42, Junio C Hamano wrote:\n> Rohit Ashiwal <rohit.ashiwal265@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> \n> Mental note: ignore_author_date() would not allow author==NULL as its input.\n> \n>> @@ -1020,10 +1047,20 @@ static int run_git_commit(struct repository *r,\n>>   \n>>   \t\tif (res <= 0)\n>>   \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n>> -\t\telse\n>> +\t\telse {\n>> +\t\t\tif (opts->ignore_date) {\n>> +\t\t\t\tchar *new_author = ignore_author_date(author);\n>> +\t\t\t\tif (!author)\n>> +\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n>> +\t\t\t\t\t    \"rebase, which must set the author \"\n>> +\t\t\t\t\t    \"before committing the tree\");\n> \n> Yet, author is used and then checked for NULL-ness, which is\n> backwards.  Before we have a chance to issue this BUG(), we would\n> already have segfaulted inside ignore_author_date().\n> \n\nGood catch!\n"},{"id":"380829","messageId":"c8bede99-8926-2bdc-a3ff-b8ee49bb6e34@gmail.com","threadId":"51596","inReplyTo":"xmqqsgpvvi3s.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 0/6] rebase -i: support more options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-20T18:37:16Z","receivedAt":"2019-08-20T18:37:22Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 20/08/2019 18:53, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> Hi Rohit\n>>\n>> On 20/08/2019 04:45, Rohit Ashiwal wrote:\n>>> I've tries to incorporated all the suggestions.\n>>\n>> It is helpful if you can list the changes to remind us all what we\n>> said. (as a patch author I find composing that is helpful to remind me\n>> if there's anything I've forgotten to address)\n>>\n>> Also there are a couple of things that were discussed such as\n>> splitting up the author and passing it round as a <name, email, date,\n>> tz> tuple and testing a non-default timezone which aren't included -\n>> that's fine but it helps if you take a moment to explain why in the\n>> cover letter.\n>>\n>>>\n>>> Some points:\n>>>     - According to v2.0.0's git-am.sh, ignore-date should override\n>>>       committer-date-is-author-date. Ergo, we are not barfing out\n>>>       when both flags are provided.\n>>>     - Should the 'const' qualifier be removed[2]? Since it is leaving\n>>>       a false impression that author should not be free()'d.\n>>\n>> The author returned by read_author_ident() is owned by the strbuf that\n>> you pass to read_author_ident() which is confusing.\n>>\n>> Best Wishes\n>>\n>> Phillip\n> \n> I've looked at this round, but will push out v2 for today's\n> integration cycle, mostly due to lack of time, but there do not seem\n> to be great difference between the iterations.\n> \n> The \"ignore-date\" step conflicts semantically with b0a31861\n> (\"sequencer: simplify root commit creation\", 2019-08-19) but in a\n> good way.  Without the clean-up b0a31861 makes, we need to munge the\n> timestamp in two places, but with it, there is only one place that\n> needs to modify the timestamp for the feature (in try_to_commit()).\n\nThat was my hope\n\n> You may want to see if these \"more options\" topic can take advantage\n> of the \"simplify root commit creation\" by building on top of some\n> form of it (I do not know offhand if b0a31861 (\"sequencer: simplify\n> root commit creation\", 2019-08-19) must build on other two patches\n> to fix \"rebase -i\" or it can be split out as an independent\n> clean-up), and if it is feasible, work with your student to make it\n> happen, perhaps?\n\nIf it is separated out from the first two there will be a minor textual \nconflict as the first patch in that series changes the root commit \ncreation to stop it writing CHERRY_PICK_HEAD and then b0a31861 deletes \nthe modified version but it shouldn't be a problem to resolve manually. \nRohit do you want to try cherry-picking b0a31861 onto master and then \nrebasing your patches on top of it? - it would be nice to simplify things.\n\nBest Wishes\n\nPhillip\n\n> Thanks.\n> \n"},{"id":"380832","messageId":"98aeebc5-fceb-1ce8-9c27-d425c3f6e674@gmail.com","threadId":"51596","inReplyTo":"20190820034536.13071-2-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-08-20T18:40:54Z","receivedAt":"2019-08-20T18:41:00Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 20/08/2019 04:45, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            | 13 ++++-\n>   builtin/rebase.c                        | 22 +++++++--\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n>   4 files changed, 94 insertions(+), 7 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 6156609cf7..873eb5768c 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -371,8 +371,16 @@ 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>   \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\nThanks for spelling out exactly what this does. I had not appreciated \nthe difference before. Does this mean that if I have a branch with some \nwhitespace cleanups I'll get different results if I rebase it with the \nsequencer compared to am? (I suspect from the description that the \nsequencer will simply ignore all my whitespace changes)\n\nI think this is ready if we can live with the difference - I'm not \nentirely convinced that adding an option with the same name and a \ndifferent behavior is going to improve things though.\n\nBest Wishes\n\nPhillip\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> @@ -520,7 +528,6 @@ The following options:\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> @@ -543,6 +550,8 @@ 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> + * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n>   \n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 670096c065..f8a618d54c 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -79,6 +79,7 @@ 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>   \tchar *cmd;\n> @@ -99,6 +100,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> @@ -114,9 +116,15 @@ 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> +\tstrbuf_release(&strategy_buf);\n>   \treturn replay;\n>   }\n>   \n> @@ -511,6 +519,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> @@ -964,6 +974,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> @@ -1407,9 +1419,6 @@ 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> @@ -1417,6 +1426,8 @@ 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\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> @@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \t}\n>   \n>   \tif (options.rebase_merges) {\n> +\t\tif (options.ignore_whitespace)\n> +\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n> +\t\t\t      \"'--ignore-whitespace'\"));\n>   \t\tif (strategy_options.nr)\n>   \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n>   \t\t\t      \"'--strategy-option'\"));\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> new file mode 100755\n> index 0000000000..2e16e00a9d\n> --- /dev/null\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -0,0 +1,65 @@\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> +# 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 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_done\n> \n"},{"id":"380835","messageId":"CAL7ArXrNaCh9vbvNUuDVCsogT9c+j8J+TMts+nW+S7R2EKhiwA@mail.gmail.com","threadId":"51596","inReplyTo":"98aeebc5-fceb-1ce8-9c27-d425c3f6e674@gmail.com","subject":"Re: [PATCH v3 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-08-20T18:47:35Z","receivedAt":"2019-08-20T18:48:15Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Hi Phillip\n\nOn Wed, Aug 21, 2019 at 12:10 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> Thanks for spelling out exactly what this does. I had not appreciated\n> the difference before. Does this mean that if I have a branch with some\n> whitespace cleanups I'll get different results if I rebase it with the\n> sequencer compared to am? (I suspect from the description that the\n> sequencer will simply ignore all my whitespace changes)\n\nI'm afraid that this is the case.\n\n> I think this is ready if we can live with the difference - I'm not\n> entirely convinced that adding an option with the same name and a\n> different behavior is going to improve things though.\n\nThis is the first step to improving consistency. We can\nfurther improve upon the implementation. I have already\nmentioned that in the cover letter of previous patches[1].\n\nThanks\nRohit\n\n[1]: https://public-inbox.org/git/20190712185015.20585-1-rohit.ashiwal265@gmail.com/\n"},{"id":"381012","messageId":"xmqqsgprnc1u.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20190820034536.13071-3-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v3 2/6] sequencer: add NULL checks under read_author_script","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-08-23T15:20:29Z","receivedAt":"2019-08-23T15:20:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n\n> read_author_script reads name, email and author date from the author\n> script. However, it does not check if the arguments are NULL. Adding\n> NULL checks will allow us to selectively get the required value,...\n\nI had a hard time understanding the argument here without knowing\nwhy I had trouble, and I think I figured it out.  What you wrote may\nnot be incorrect per-se, but the logic is backwards.\n\nThe function has been about reading all three, and it always took\nand required the callers to pass three valid pointers to locations\nto store these three.  It did not check for NULL; passing NULL was\nsimply a bug in the caller who deserved a segfault.\n\nThis series, however, wants to allow new callers of the function to\nselectively read some among the three and ignore the rest, and you\nhappened to choose \"pass NULL for an uninteresting field\" as the\nnew calling convention.\n\nThat choice is where \"checking for NULL\" comes in.\n\nIn other words, \"checking for NULL\" is merely an implementation\ndetail for a more important change this patch brings in: We now\ncan read some and ignore the rest, while requiring that the input\nfile is well formed even for the fields we do not care about.\n\n\n\n    sequencer: allow callers of read_author_script() to ignore fields\n\n    The current callers of the read_author_script() function read\n    name, email and date from the author script.  Allow callers to\n    signal that they are not interested in some among these three\n    fields by passing NULL.\n\n    Note that fields that are ignored still must exist and be\n    formatted correctly in the author script.\n\nor something like that, perhaps.\n\n"},{"id":"382005","messageId":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v4 0/6] rebase -i: support more options","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T11:50:28Z","receivedAt":"2019-09-07T11:50:58Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Following the suggestion of Phillip I've rebased my patch on master (745f681289)\nand cherry-picking b0a3186140.\n\nBase: 745f6812895b31c02b29bdfe4ae8e5498f776c26\n      with cherry-picked b0a3186140dbc7bd64cbc6ef733386a0f1eb6a4d\n\nOutline:\n  2/6:\n      - Change commit message and description\n  3/6:\n      - add test for rebase -r\n      - add strict bounds while pushing ident date\n  5/6:\n      - bug fix: (following am's code) if --ignore-date is provided,\n                 we should setenv GIT_COMMITTER_DATE to \"\".\n      - catch error when ident line is malformed\n      - push GIT_AUTHOR_DATE instead of providing it with --date so\n        that \"git merge\" can also use push_dates function\n      - add test for rebase -r\n\n\nRohit Ashiwal (6):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: allow callers of read_author_script() to ignore fields\n  rebase -i: support --committer-date-is-author-date\n  sequencer: rename amend_author to author_to_rename\n  rebase -i: support --ignore-date\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt            |  26 +++--\n builtin/rebase.c                        |  55 +++++++---\n sequencer.c                             | 134 +++++++++++++++++++++--\n sequencer.h                             |   2 +\n t/t3422-rebase-incompatible-options.sh  |   2 -\n t/t3433-rebase-options-compatibility.sh | 137 ++++++++++++++++++++++++\n 6 files changed, 328 insertions(+), 28 deletions(-)\n create mode 100755 t/t3433-rebase-options-compatibility.sh\n\nRange-diff:\n--- snip ---\n 1:  e82ed8cad5 = 49:  77af1d66db rebase -i: add --ignore-whitespace flag\n 2:  209057b361 ! 50:  1f7f1407b2 sequencer: add NULL checks under read_author_script\n    @@ -1,19 +1,14 @@\n     Author: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n     \n    -    sequencer: add NULL checks under read_author_script\n    +    sequencer: allow callers of read_author_script() to ignore fields\n     \n    -    read_author_script reads name, email and author date from the author\n    -    script. However, it does not check if the arguments are NULL. Adding\n    -    NULL checks will allow us to selectively get the required value, for\n    -    example:\n    +    The current callers of the read_author_script() function read name,\n    +    email and date from the author script.  Allow callers to signal that\n    +    they are not interested in some among these three fields by passing\n    +    NULL.\n     \n    -        char *date;\n    -        if (read_author_script(_path_, NULL, NULL, &date, _int_))\n    -                die(_(\"failed to read author date\"));\n    -        /* needs to be free()'d */\n    -        return date;\n    -\n    -    Add NULL checks for better control over the information retrieved.\n    +    Note that fields that are ignored still must exist and be formatted\n    +    correctly in the author script.\n     \n         Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n     \n 3:  a4e6644ef8 ! 51:  cc1614154e rebase -i: support --committer-date-is-author-date\n    @@ -128,35 +128,34 @@\n     +\treturn date;\n     +}\n     +\n    - /* Read author-script and return an ident line (author <email> timestamp) */\n    - static const char *read_author_ident(struct strbuf *buf)\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     @@\n    - {\n    - \tstruct child_process cmd = CHILD_PROCESS_INIT;\n      \n    -+\tif (opts->committer_date_is_author_date) {\n    -+\t\tsize_t len;\n    -+\t\tint res = -1;\n    -+\t\tstruct strbuf datebuf = STRBUF_INIT;\n    -+\t\tchar *date = read_author_date_or_null();\n    + \tcmd.git_cmd = 1;\n    + \n    ++        if (opts->committer_date_is_author_date) {\n    ++\t        int res = -1;\n    ++\t        struct strbuf datebuf = STRBUF_INIT;\n    ++\t        char *date = read_author_date_or_null();\n     +\n    -+\t\tif (!date)\n    -+\t\t\treturn -1;\n    ++\t        if (!date)\n    ++\t                return -1;\n     +\n    -+\t\tstrbuf_addf(&datebuf, \"@%s\", date);\n    -+\t\tfree(date);\n    ++\t        strbuf_addf(&datebuf, \"@%s\", date);\n    ++\t        res = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf, 1);\n     +\n    -+\t\tdate = strbuf_detach(&datebuf, &len);\n    -+\t\tres = setenv(\"GIT_COMMITTER_DATE\", date, 1);\n    -+\t\tfree(date);\n    ++\t\tstrbuf_release(&datebuf);\n    ++\t        free(date);\n     +\n    -+\t\tif (res)\n    -+\t\t\treturn -1;\n    -+\t}\n    - \tif ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) {\n    - \t\tstruct strbuf msg = STRBUF_INIT, script = STRBUF_INIT;\n    - \t\tconst char *author = NULL;\n    ++\t        if (res)\n    ++\t                return -1;\n    ++        }\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     @@\n      \n      \tif (parse_head(r, &current_head))\n    @@ -174,14 +173,19 @@\n     +\t\tstruct ident_split ident;\n     +\t\tstruct strbuf date = STRBUF_INIT;\n     +\n    -+\t\tsplit_ident_line(&ident, author, len);\n    -+\n    ++\t\tif (split_ident_line(&ident, author, len) < 0)\n    ++\t\t\treturn error(_(\"malformed ident line\"));\n     +\t\tif (!ident.date_begin)\n     +\t\t\treturn error(_(\"corrupted author without date information\"));\n     +\n    -+\t\tstrbuf_addf(&date, \"@%s\", ident.date_begin);\n    -+\t\tsetenv(\"GIT_COMMITTER_DATE\", date.buf, 1);\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    @@ -256,6 +260,20 @@\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    +@@\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     @@\n      \ttest_cmp expect file\n      '\n    @@ -275,5 +293,18 @@\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 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      test_done\n 4:  6ac1885c54 = 52:  9e92c79bda sequencer: rename amend_author to author_to_rename\n 5:  a69749dd67 ! 53:  fc68e55e78 rebase -i: support --ignore-date\n    @@ -83,8 +83,10 @@\n      \t}\n      \n     -\tif (options.committer_date_is_author_date)\n    -+\tif (options.ignore_date)\n    ++\tif (options.ignore_date) {\n     +\t\toptions.committer_date_is_author_date = 0;\n    ++\t\tsetenv(\"GIT_COMMITTER_DATE\", \"\", 1);\n    ++\t}\n     +\tif (options.committer_date_is_author_date ||\n     +\t    options.ignore_date)\n      \t\toptions.flags |= REBASE_FORCE;\n    @@ -110,7 +112,7 @@\n      static GIT_PATH_FUNC(rebase_path_verbose, \"rebase-merge/verbose\")\n      static GIT_PATH_FUNC(rebase_path_quiet, \"rebase-merge/quiet\")\n     @@\n    - \treturn buf->buf;\n    + \treturn date;\n      }\n      \n     +/* Construct a free()able author string with current time as the author date */\n    @@ -120,7 +122,10 @@\n     +\tstruct ident_split ident;\n     +\tstruct strbuf new_author = STRBUF_INIT;\n     +\n    -+\tsplit_ident_line(&ident, author, len);\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, author);\n    @@ -134,7 +139,7 @@\n     +\tstruct strbuf date = STRBUF_INIT;\n     +\n     +\tstrbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n    -+\targv_array_pushf(&child->args, \"--date=%s\", date.buf);\n    ++\targv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n     +\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n     +\tstrbuf_release(&date);\n     +}\n    @@ -143,28 +148,6 @@\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     @@\n    - \n    - \t\tif (res <= 0)\n    - \t\t\tres = error_errno(_(\"could not read '%s'\"), defmsg);\n    --\t\telse\n    -+\t\telse {\n    -+\t\t\tif (opts->ignore_date) {\n    -+\t\t\t\tchar *new_author = ignore_author_date(author);\n    -+\t\t\t\tif (!author)\n    -+\t\t\t\t\tBUG(\"ignore-date can only be used with \"\n    -+\t\t\t\t\t    \"rebase, which must set the author \"\n    -+\t\t\t\t\t    \"before committing the tree\");\n    -+\t\t\t\tfree((void *)author);\n    -+\t\t\t\tauthor = new_author;\n    -+\t\t\t}\n    - \t\t\tres = commit_tree(msg.buf, msg.len, cache_tree_oid,\n    - \t\t\t\t\t  NULL, &root_commit, author,\n    - \t\t\t\t\t  opts->gpg_sign);\n    -+\t\t}\n    - \n    - \t\tstrbuf_release(&msg);\n    - \t\tstrbuf_release(&script);\n    -@@\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    @@ -179,6 +162,10 @@\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    @@ -242,7 +229,7 @@\n      --- a/t/t3433-rebase-options-compatibility.sh\n      +++ b/t/t3433-rebase-options-compatibility.sh\n     @@\n    - \ttest_cmp authortime committertime\n    + \tdone <rev_list\n      '\n      \n     +# Checking for +0000 in author time is enough since default\n    @@ -252,13 +239,32 @@\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    ++\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n    ++\tgrep \"+0000\" authortime &&\n    ++\tgrep \"+0000\" committertime\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    ++\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n    ++\tgrep \"+0000\" authortime &&\n    ++\tgrep \"+0000\" committertime\n     +'\n    ++\n    ++test_expect_success '--ignore-date works with rebase -r' '\n    ++\tgit checkout side &&\n    ++\tgit merge 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\tgit show $HASH --pretty=\"format:%ci\" >committertime\n    ++\t\tgrep \"+0000\" authortime\n    ++\t\tgrep \"+0000\" committertime\n    ++\tdone <rev_list\n    ++'\n    ++\n      test_done\n 6:  210d15cca0 = 54:  396d5f16eb rebase: add --reset-author-date\n-- \n2.21.0\n\n"},{"id":"382006","messageId":"20190907115034.14933-2-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v4 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T11:50:29Z","receivedAt":"2019-09-07T11:51:02Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"There are two backends available for rebasing, viz, the am and the\ninteractive. Naturally, there shall be some features that are\nimplemented in one but not in the other. One such flag is\n--ignore-whitespace which indicates merge mechanism to treat lines\nwith only whitespace changes as unchanged. Wire the interactive\nrebase to also understand the --ignore-whitespace flag by\ntranslating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 13 ++++-\n builtin/rebase.c                        | 22 +++++++--\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n 4 files changed, 94 insertions(+), 7 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 6156609cf7..873eb5768c 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -371,8 +371,16 @@ 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 \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@@ -520,7 +528,6 @@ The following options:\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@@ -543,6 +550,8 @@ 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+ * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 670096c065..f8a618d54c 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -79,6 +79,7 @@ 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 \tchar *cmd;\n@@ -99,6 +100,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@@ -114,9 +116,15 @@ 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+\tstrbuf_release(&strategy_buf);\n \treturn replay;\n }\n \n@@ -511,6 +519,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@@ -964,6 +974,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@@ -1407,9 +1419,6 @@ 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@@ -1417,6 +1426,8 @@ 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\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@@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (options.rebase_merges) {\n+\t\tif (options.ignore_whitespace)\n+\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n+\t\t\t      \"'--ignore-whitespace'\"));\n \t\tif (strategy_options.nr)\n \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n \t\t\t      \"'--strategy-option'\"));\ndiff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\nindex a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nnew file mode 100755\nindex 0000000000..2e16e00a9d\n--- /dev/null\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -0,0 +1,65 @@\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+# 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 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_done\n-- \n2.21.0\n\n"},{"id":"382007","messageId":"20190907115034.14933-3-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v4 2/6] sequencer: allow callers of read_author_script() to ignore fields","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T11:50:30Z","receivedAt":"2019-09-07T11:51:06Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The current callers of the read_author_script() function read name,\nemail and date from the author script.  Allow callers to signal that\nthey are not interested in some among these three fields by passing\nNULL.\n\nNote that fields that are ignored still must exist and be formatted\ncorrectly in the author script.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 16 +++++++++++++---\n 1 file changed, 13 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex e55550510a..adeff2561e 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -824,9 +824,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-- \n2.21.0\n\n"},{"id":"382008","messageId":"20190907115034.14933-4-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v4 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T11:50:31Z","receivedAt":"2019-09-07T11:51:12Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the committer date\nby changing it to the author date. Let's add the same for\ninteractive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 10 ++--\n builtin/rebase.c                        | 17 +++++--\n sequencer.c                             | 61 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 37 +++++++++++++++\n 6 files changed, 116 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 873eb5768c..e7c0eac18c 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -386,9 +386,13 @@ unchanged for the sake of a three-way merge.\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+\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@@ -525,7 +529,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -551,6 +554,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 --ignore-whitespace\n+ * --preserve-merges and --committer-date-is-author-date\n  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex f8a618d54c..656bc7d7e9 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -82,6 +82,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@@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -976,6 +979,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@@ -1419,9 +1424,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@@ -1692,10 +1697,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\ndiff --git a/sequencer.c b/sequencer.c\nindex adeff2561e..fd925f2d72 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -147,6 +147,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@@ -879,6 +880,17 @@ 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 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 +950,24 @@ static int run_git_commit(struct repository *r,\n \n \tcmd.git_cmd = 1;\n \n+        if (opts->committer_date_is_author_date) {\n+\t        int res = -1;\n+\t        struct strbuf datebuf = STRBUF_INIT;\n+\t        char *date = read_author_date_or_null();\n+\n+\t        if (!date)\n+\t                return -1;\n+\n+\t        strbuf_addf(&datebuf, \"@%s\", date);\n+\t        res = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf, 1);\n+\n+\t\tstrbuf_release(&datebuf);\n+\t        free(date);\n+\n+\t        if (res)\n+\t                return -1;\n+        }\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@@ -1331,7 +1361,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\", NULL };\n \t\tconst char *out_enc = get_commit_output_encoding();\n@@ -1359,6 +1388,26 @@ 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\treturn error(_(\"malformed ident line\"));\n+\t\tif (!ident.date_begin)\n+\t\t\treturn error(_(\"corrupted author without date information\"));\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@@ -2473,6 +2522,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@@ -2555,6 +2609,8 @@ 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->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3752,7 +3808,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 6704acbb9c..e3881e9275 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 2e16e00a9d..6c1fbab4d8 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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@@ -26,8 +29,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@@ -62,4 +70,33 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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 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 test_done\n-- \n2.21.0\n\n"},{"id":"382009","messageId":"20190907115034.14933-5-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v4 4/6] sequencer: rename amend_author to author_to_rename","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T11:50:32Z","receivedAt":"2019-09-07T11:51:15Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() while 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 fd925f2d72..0d78abeec8 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1354,7 +1354,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@@ -1375,7 +1375,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@@ -1470,7 +1470,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.21.0\n\n"},{"id":"382010","messageId":"20190907115034.14933-6-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v4 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T11:50:33Z","receivedAt":"2019-09-07T11:51:17Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the author date\nby changing it to the committer (current) date. Let's add the same\nfor interactive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            |  6 +--\n builtin/rebase.c                        | 18 ++++++---\n sequencer.c                             | 53 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3433-rebase-options-compatibility.sh | 35 ++++++++++++++++\n 5 files changed, 104 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e7c0eac18c..e7ac9fae0b 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This 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 value\n+\tsame as the current time. This implies --force-rebase.\n +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:\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  * --rebase-merges and --ignore-whitespace\n  * --rebase-merges and --strategy\n  * --rebase-merges and --strategy-option\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 656bc7d7e9..e6f90f61dd 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -83,6 +83,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@@ -117,6 +118,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@@ -981,6 +983,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@@ -1427,8 +1431,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@@ -1697,13 +1701,17 @@ 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+\tif (options.ignore_date) {\n+\t\toptions.committer_date_is_author_date = 0;\n+\t\tsetenv(\"GIT_COMMITTER_DATE\", \"\", 1);\n+\t}\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, \"--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 0d78abeec8..188499190f 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -148,6 +148,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@@ -891,6 +892,35 @@ static char *read_author_date_or_null(void)\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, author);\n+\tdatestamp(&new_author);\n+\treturn strbuf_detach(&new_author, NULL);\n+}\n+\n+static void push_dates(struct child_process *child)\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+\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@@ -983,6 +1013,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);\n \tif (defmsg)\n \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n \telse if (!(flags & EDIT_MSG))\n@@ -1451,6 +1483,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@@ -2527,6 +2568,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@@ -2611,6 +2657,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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@@ -3536,6 +3584,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);\n \n \t\t/* Add the tips to be merged */\n \t\tfor (j = to_merge; j; j = j->next)\n@@ -3809,7 +3859,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 e3881e9275..bf5a79afdb 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 6c1fbab4d8..0ad7bfc6a0 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -99,4 +99,39 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '\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+\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n+\tgrep \"+0000\" authortime &&\n+\tgrep \"+0000\" committertime\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 show HEAD --pretty=\"format:%ci\" >committertime &&\n+\tgrep \"+0000\" authortime &&\n+\tgrep \"+0000\" committertime\n+'\n+\n+test_expect_success '--ignore-date works with rebase -r' '\n+\tgit checkout side &&\n+\tgit merge 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\tgit show $HASH --pretty=\"format:%ci\" >committertime\n+\t\tgrep \"+0000\" authortime\n+\t\tgrep \"+0000\" committertime\n+\tdone <rev_list\n+'\n+\n test_done\n-- \n2.21.0\n\n"},{"id":"382011","messageId":"20190907115034.14933-7-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v4 6/6] rebase: add --reset-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T11:50:34Z","receivedAt":"2019-09-07T11:51:21Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The previous commit introduced --ignore-date flag to interactive\nrebase, but the name is actually very vague in context of rebase -i\nsince there are two dates we can work with. Add an alias to convey\nthe precise purpose.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt | 1 +\n builtin/rebase.c             | 2 ++\n 2 files changed, 3 insertions(+)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e7ac9fae0b..ec62ba36b8 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -391,6 +391,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the given author date, reset it to the value\n \tsame as the current time. This implies --force-rebase.\n +\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex e6f90f61dd..57e411dd59 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1431,6 +1431,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_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current 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_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n-- \n2.21.0\n\n"},{"id":"382026","messageId":"20190907205647.11011-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-6-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v4 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-09-07T20:56:47Z","receivedAt":"2019-09-07T20:57:12Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"On Sat,  7 Sep 2019 17:20:33 +0530 Rohit Ashiwal <rohit.ashiwal265@gmail.com> wrote:\n> [...]\n> +test_expect_success '--ignore-date works with rebase -r' '\n> +\tgit checkout side &&\n> +\tgit merge commit3 &&\n\nShould use --no-ff option to be sure that it handles \"merge\"\ncommits properly. Same for [3/6]. Please Junio change it while\napplying the patch.\n\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\tgit show $HASH --pretty=\"format:%ci\" >committertime\n> +\t\tgrep \"+0000\" authortime\n> +\t\tgrep \"+0000\" committertime\n> +\tdone <rev_list\n> +'\n> [...]\n\nBest\nRohit\n\n"},{"id":"382080","messageId":"xmqq8sqxl557.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20190907115034.14933-1-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v4 0/6] rebase -i: support more options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-09-09T18:02:28Z","receivedAt":"2019-09-09T18:02:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n\n> Following the suggestion of Phillip I've rebased my patch on master (745f681289)\n> and cherry-picking b0a3186140.\n\nSorry, but that's horrible.  The latter does not even cleanly apply\non the former.\n\nLet me see if I can find time to whip this into a reasonable shape.\n\nThanks.\n"},{"id":"382088","messageId":"d16a2c76-32c0-1080-a2de-00803ff84962@gmail.com","threadId":"51596","inReplyTo":"xmqq8sqxl557.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v4 0/6] rebase -i: support more options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-09-09T18:51:22Z","receivedAt":"2019-09-09T18:51:29Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 09/09/2019 19:02, Junio C Hamano wrote:\n> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n> \n>> Following the suggestion of Phillip I've rebased my patch on master (745f681289)\n>> and cherry-picking b0a3186140.\n> \n> Sorry, but that's horrible.  The latter does not even cleanly apply\n> on the former.\n\nYes I had assumed that the cherry pick would become the first patch of \nthis series and be dropped from pw/rebase-i-show-HEAD-to-reword. I \nshould have been more explicit about that.\n\n> Let me see if I can find time to whip this into a reasonable shape.\n\nAs pw/rebase-i-show-HEAD-to-reword is slated for next perhaps these \ncould build on that. The first patch needs am -3 to apply to that branch \nbut the result looks ok and the rest apply as is.\n\nBest Wishes\n\nPhillip\n\n> Thanks.\n> \n"},{"id":"382092","messageId":"xmqq1rwpjmrl.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"d16a2c76-32c0-1080-a2de-00803ff84962@gmail.com","subject":"Re: [PATCH v4 0/6] rebase -i: support more options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-09-09T19:24:46Z","receivedAt":"2019-09-09T19:24:52Z","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> Yes I had assumed that the cherry pick would become the first patch of\n> this series and be dropped from pw/rebase-i-show-HEAD-to-reword.\n\nAh, such an arrangement would have made a log more sense, indeed.\n\n> As pw/rebase-i-show-HEAD-to-reword is slated for next perhaps these\n> could build on that. The first patch needs am -3 to apply to that\n> branch but the result looks ok and the rest apply as is.\n\nAs this is more or less \"new feature\" series, I do not mind too much\nto make it depend on another topic in flight that is getting solid.\n\nThanks for helping.\n"},{"id":"383058","messageId":"5adde732-173b-d24d-d23f-bb4d043076d7@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-6-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v4 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-09-27T10:00:58Z","receivedAt":"2019-09-27T10:01:05Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nThis is an improvement but there are a couple of outstanding issues from \nthe previous round with regard to handing --ignore-date when \nGIT_COMMITTER_DATE is set. I'll try and look at the rest of the series soon.\n\nOn 07/09/2019 12:50, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>  Documentation/git-rebase.txt            |  6 +--\n>  builtin/rebase.c                        | 18 ++++++---\n>  sequencer.c                             | 53 ++++++++++++++++++++++++-\n>  sequencer.h                             |  1 +\n>  t/t3433-rebase-options-compatibility.sh | 35 ++++++++++++++++\n>  5 files changed, 104 insertions(+), 9 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index e7c0eac18c..e7ac9fae0b 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.\n>  \tas the committer date. This 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 value\n> +\tsame as the current time. This implies --force-rebase.\n\ns/value same as the// as Junio suggested in [1]\n\n[1]\nhttps://public-inbox.org/git/20190806173638.17510-1-rohit.ashiwal265@gmail.com/T/#m88cf5f28110c56cf81c338c507b1d8e901b4bd6a\n\n>  +\n>  See also INCOMPATIBLE OPTIONS below.\n>  \n> @@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS\n>  \n>  The following options:\n>  \n> - * --ignore-date\n>   * --whitespace\n>   * -C\n>  \n> @@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:\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>   * --rebase-merges and --ignore-whitespace\n>   * --rebase-merges and --strategy\n>   * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 656bc7d7e9..e6f90f61dd 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -83,6 +83,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> @@ -117,6 +118,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> @@ -981,6 +983,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> @@ -1427,8 +1431,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> @@ -1697,13 +1701,17 @@ 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> +\tif (options.ignore_date) {\n> +\t\toptions.committer_date_is_author_date = 0;\n> +\t\tsetenv(\"GIT_COMMITTER_DATE\", \"\", 1);\n> +\t}\n\nWhat if GIT_COMMITTER_DATE is set? We want to match the behavior of git\nam in that case. cf [2]\n\n[2] \nhttps://public-inbox.org/git/20190806173638.17510-1-rohit.ashiwal265@gmail.com/T/#m4f5a58fdbdb8797c5fddc5ac1b1145dbe4d01263\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, \"--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)) {\n> diff --git a/sequencer.c b/sequencer.c\n> index 0d78abeec8..188499190f 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -148,6 +148,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> @@ -891,6 +892,35 @@ static char *read_author_date_or_null(void)\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\nThis error checking is a welcome improvement\n\n> +\tlen = ident.mail_end - ident.name_begin + 1;\n> +\n> +\tstrbuf_addf(&new_author, \"%.*s \", len, author);\n\nYou use ident.name_begin to calculate the length which I think is the\nright thing to do but then you pass author rather than ident.name_begin\nhere.\n\n> +\tdatestamp(&new_author);\n> +\treturn strbuf_detach(&new_author, NULL);\n> +}\n> +\n> +static void push_dates(struct child_process *child)\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> +\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n\nIt's nice to see the environment being used for both of these now\n\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> @@ -983,6 +1013,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);\n>  \tif (defmsg)\n>  \t\targv_array_pushl(&cmd.args, \"-F\", defmsg, NULL);\n>  \telse if (!(flags & EDIT_MSG))\n> @@ -1451,6 +1483,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\nIt's good to see the error handling improved\n\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> @@ -2527,6 +2568,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> @@ -2611,6 +2657,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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> @@ -3536,6 +3584,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);\n>  \n>  \t\t/* Add the tips to be merged */\n>  \t\tfor (j = to_merge; j; j = j->next)\n> @@ -3809,7 +3859,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 e3881e9275..bf5a79afdb 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 6c1fbab4d8..0ad7bfc6a0 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -99,4 +99,39 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '\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> +\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n> +\tgrep \"+0000\" authortime &&\n> +\tgrep \"+0000\" committertime\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 show HEAD --pretty=\"format:%ci\" >committertime &&\n> +\tgrep \"+0000\" authortime &&\n> +\tgrep \"+0000\" committertime\n> +'\n> +\n> +test_expect_success '--ignore-date works with rebase -r' '\n> +\tgit checkout side &&\n> +\tgit merge 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\tgit show $HASH --pretty=\"format:%ci\" >committertime\n> +\t\tgrep \"+0000\" authortime\n> +\t\tgrep \"+0000\" committertime\n> +\tdone <rev_list\n> +'\n\nIt's good to see the new test. Did you see Stolee's email [4] about the \ntest coverage of the previous version of this series? You should check \nthat this series tests all the untested non-error handling lines.\n\n[4] \nhttps://public-inbox.org/git/1ed86989-9ba2-0cd7-b6f7-654d1943b1d7@gmail.com/\n\nBest Wishes\n\nPhillip\n\n>  test_done\n> \n\n"},{"id":"383405","messageId":"9e311cef-1f9d-4146-c2a7-c8179cdcdaf1@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-2-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-10-04T09:29:36Z","receivedAt":"2019-10-04T09:29:43Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 07/09/2019 12:50, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            | 13 ++++-\n>   builtin/rebase.c                        | 22 +++++++--\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n>   4 files changed, 94 insertions(+), 7 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 6156609cf7..873eb5768c 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -371,8 +371,16 @@ 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>   \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> @@ -520,7 +528,6 @@ The following options:\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> @@ -543,6 +550,8 @@ 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> + * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n>   \n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 670096c065..f8a618d54c 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -79,6 +79,7 @@ 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>   \tchar *cmd;\n> @@ -99,6 +100,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> @@ -114,9 +116,15 @@ 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> +\tstrbuf_release(&strategy_buf);\n>   \treturn replay;\n>   }\n>   \n> @@ -511,6 +519,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> @@ -964,6 +974,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> @@ -1407,9 +1419,6 @@ 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> @@ -1417,6 +1426,8 @@ 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\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> @@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n>   \t}\n>   \n>   \tif (options.rebase_merges) {\n> +\t\tif (options.ignore_whitespace)\n> +\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n> +\t\t\t      \"'--ignore-whitespace'\"));\n\n--rebase-merges now supports --strategy_option so we should fix this.\n\n>   \t\tif (strategy_options.nr)\n>   \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n>   \t\t\t      \"'--strategy-option'\"));\n> diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> index a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> new file mode 100755\n> index 0000000000..2e16e00a9d\n> --- /dev/null\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -0,0 +1,65 @@\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> +# This is a special case in which both am and interactive backends\n> +# provide the same output. \n\nI'm still concerned that we have to construct a special test case to get \nboth backends to generate the same output. If this series is about \nsupporting the behavior of the am backend in the sequencer then I'm \nworried that having the same option name have two different behaviors \nwill create more problems than it solves. Do you have a feeling for how \noften the two backends give different results?\n\nBest Wishes\n\nPhillip\n\nIt 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 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_done\n> \n"},{"id":"383408","messageId":"3f29cb5d-dbc2-ae00-651b-22e9f437372a@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-4-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-10-04T09:37:43Z","receivedAt":"2019-10-04T09:37:50Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nThe handling of ident_split is looking better now but I've got a \nquestion below about returning vs going to a cleanup section when \nthere's an error.\n\nOn 07/09/2019 12:50, Rohit Ashiwal wrote:\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> \n> Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> ---\n>   Documentation/git-rebase.txt            | 10 ++--\n>   builtin/rebase.c                        | 17 +++++--\n>   sequencer.c                             | 61 ++++++++++++++++++++++++-\n>   sequencer.h                             |  1 +\n>   t/t3422-rebase-incompatible-options.sh  |  1 -\n>   t/t3433-rebase-options-compatibility.sh | 37 +++++++++++++++\n>   6 files changed, 116 insertions(+), 11 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index 873eb5768c..e7c0eac18c 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -386,9 +386,13 @@ unchanged for the sake of a three-way merge.\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> +\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> @@ -525,7 +529,6 @@ INCOMPATIBLE OPTIONS\n>   \n>   The following options:\n>   \n> - * --committer-date-is-author-date\n>    * --ignore-date\n>    * --whitespace\n>    * -C\n> @@ -551,6 +554,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 --ignore-whitespace\n> + * --preserve-merges and --committer-date-is-author-date\n>    * --rebase-merges and --ignore-whitespace\n>    * --rebase-merges and --strategy\n>    * --rebase-merges and --strategy-option\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index f8a618d54c..656bc7d7e9 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -82,6 +82,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> @@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n>   \treplay.strategy = opts->strategy;\n>   \n> @@ -976,6 +979,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> @@ -1419,9 +1424,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> @@ -1692,10 +1697,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\n> diff --git a/sequencer.c b/sequencer.c\n> index adeff2561e..fd925f2d72 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -147,6 +147,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> @@ -879,6 +880,17 @@ 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>   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 +950,24 @@ static int run_git_commit(struct repository *r,\n>   \n>   \tcmd.git_cmd = 1;\n>   \n> +        if (opts->committer_date_is_author_date) {\n> +\t        int res = -1;\n> +\t        struct strbuf datebuf = STRBUF_INIT;\n> +\t        char *date = read_author_date_or_null();\n> +\n> +\t        if (!date)\n> +\t                return -1;\n> +\n> +\t        strbuf_addf(&datebuf, \"@%s\", date);\n> +\t        res = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf, 1);\n> +\n> +\t\tstrbuf_release(&datebuf);\n> +\t        free(date);\n> +\n> +\t        if (res)\n> +\t                return -1;\n> +        }\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> @@ -1331,7 +1361,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\", NULL };\n>   \t\tconst char *out_enc = get_commit_output_encoding();\n> @@ -1359,6 +1388,26 @@ 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\treturn error(_(\"malformed ident line\"));\n\nHere (and just below) we return if there is an error but later on we \n`goto out` should we be doing that here to clean something up?\n\nBest Wishes\n\nPhillip\n\n> +\t\tif (!ident.date_begin)\n> +\t\t\treturn error(_(\"corrupted author without date information\"));\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> @@ -2473,6 +2522,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> @@ -2555,6 +2609,8 @@ 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->reschedule_failed_exec)\n>   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>   \n> @@ -3752,7 +3808,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 6704acbb9c..e3881e9275 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 2e16e00a9d..6c1fbab4d8 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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> @@ -26,8 +29,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> @@ -62,4 +70,33 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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 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>   test_done\n> \n"},{"id":"383470","messageId":"CABPp-BFzFM8L=CB-nPfdP9AAg+vW0=cyqG7XzuwgRvS9vhzgyw@mail.gmail.com","threadId":"51596","inReplyTo":"9e311cef-1f9d-4146-c2a7-c8179cdcdaf1@gmail.com","subject":"Re: [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2019-10-05T18:12:53Z","receivedAt":"2019-10-05T18:13:07Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Oct 4, 2019 at 2:29 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> Hi Rohit\n>\n> On 07/09/2019 12:50, Rohit Ashiwal wrote:\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> >\n> > Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n> > ---\n> >   Documentation/git-rebase.txt            | 13 ++++-\n> >   builtin/rebase.c                        | 22 +++++++--\n> >   t/t3422-rebase-incompatible-options.sh  |  1 -\n> >   t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n> >   4 files changed, 94 insertions(+), 7 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 6156609cf7..873eb5768c 100644\n> > --- a/Documentation/git-rebase.txt\n> > +++ b/Documentation/git-rebase.txt\n> > @@ -371,8 +371,16 @@ 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> >\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> > @@ -520,7 +528,6 @@ The following options:\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> > @@ -543,6 +550,8 @@ 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> > + * --rebase-merges and --ignore-whitespace\n> >    * --rebase-merges and --strategy\n> >    * --rebase-merges and --strategy-option\n> >\n> > diff --git a/builtin/rebase.c b/builtin/rebase.c\n> > index 670096c065..f8a618d54c 100644\n> > --- a/builtin/rebase.c\n> > +++ b/builtin/rebase.c\n> > @@ -79,6 +79,7 @@ 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> >       char *cmd;\n> > @@ -99,6 +100,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> > @@ -114,9 +116,15 @@ 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> > +     strbuf_release(&strategy_buf);\n> >       return replay;\n> >   }\n> >\n> > @@ -511,6 +519,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> > @@ -964,6 +974,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> > @@ -1407,9 +1419,6 @@ 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> > @@ -1417,6 +1426,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\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> > @@ -1834,6 +1845,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n> >       }\n> >\n> >       if (options.rebase_merges) {\n> > +             if (options.ignore_whitespace)\n> > +                     die(_(\"cannot combine '--rebase-merges' with \"\n> > +                           \"'--ignore-whitespace'\"));\n>\n> --rebase-merges now supports --strategy_option so we should fix this.\n>\n> >               if (strategy_options.nr)\n> >                       die(_(\"cannot combine '--rebase-merges' with \"\n> >                             \"'--strategy-option'\"));\n> > diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n> > index a5868ea152..4342f79eea 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> > new file mode 100755\n> > index 0000000000..2e16e00a9d\n> > --- /dev/null\n> > +++ b/t/t3433-rebase-options-compatibility.sh\n> > @@ -0,0 +1,65 @@\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> > +# This is a special case in which both am and interactive backends\n> > +# provide the same output.\n>\n> I'm still concerned that we have to construct a special test case to get\n> both backends to generate the same output. If this series is about\n> supporting the behavior of the am backend in the sequencer then I'm\n> worried that having the same option name have two different behaviors\n> will create more problems than it solves. Do you have a feeling for how\n> often the two backends give different results?\n\nI think the wording choice of \"special case\" was unfortunate; it's\nactually a common case.  Most the time the two backends will give the\nsame results, it's only in special cases that they don't.  See\nhttps://public-inbox.org/git/CABPp-BE+D-GFJaucgCCsBA8E7nQAxc0vNE92HaCpOTQrUp=mPA@mail.gmail.com/\n"},{"id":"383520","messageId":"20191006175713.17164-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"9e311cef-1f9d-4146-c2a7-c8179cdcdaf1@gmail.com","subject":"Re: [PATCH v4 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-10-06T17:57:13Z","receivedAt":"2019-10-06T17:58:04Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Hi Phillip\n\nOn Fri, 4 Oct 2019 10:29:36 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> [...]\n> --rebase-merges now supports --strategy_option so we should fix this.\n\nYes, now that it supports --strategy_options I'll remove it from\nhere.\n\n> [...]\n\n\nThanks\nRohit\n\n"},{"id":"383521","messageId":"20191006175729.17257-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"3f29cb5d-dbc2-ae00-651b-22e9f437372a@gmail.com","subject":"Re: [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-10-06T17:57:29Z","receivedAt":"2019-10-06T17:58:18Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"On Fri, 4 Oct 2019 10:37:43 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:\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\treturn error(_(\"malformed ident line\"));\n>\n> Here (and just below) we return if there is an error but later on we \n> `goto out` should we be doing that here to clean something up?\n\nYes, a mistake indeed. This should be replace with an error and a\ngoto statement.\n\n> Best Wishes\n>\n> Phillip\n>\n> > +\t\tif (!ident.date_begin)\n> > +\t\t\treturn error(_(\"corrupted author without date information\"));\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\nThanks\nRohit\n\n"},{"id":"383522","messageId":"20191006175747.17340-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"5adde732-173b-d24d-d23f-bb4d043076d7@gmail.com","subject":"Re: [PATCH v4 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-10-06T17:57:47Z","receivedAt":"2019-10-06T17:58:36Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"On Fri, 27 Sep 2019 11:00:58 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> [...]\n\nThanks for all the advice and improvements.\n\n> [...]\n> It's good to see the new test. Did you see Stolee's email [4] about the\n> test coverage of the previous version of this series? You should check\n> that this series tests all the untested non-error handling lines.\n>\n> [4]\n> https://public-inbox.org/git/1ed86989-9ba2-0cd7-b6f7-654d1943b1d7@gmail.com/\n\nYes, I've seen it and have improved the test since.\n\nThanks\nRohit\n\n"},{"id":"384770","messageId":"103fc38d-48b4-c81f-a0ef-5163a1018e88@gmail.com","threadId":"51596","inReplyTo":"20190907115034.14933-4-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v4 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-10-24T13:28:43Z","receivedAt":"2019-10-24T13:28:50Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 07/09/2019 12:50, Rohit Ashiwal wrote:\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> [...]> diff --git a/sequencer.c b/sequencer.c\n> index adeff2561e..fd925f2d72 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -147,6 +147,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> @@ -879,6 +880,17 @@ 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\nThis function and the hunk below are untested according to Stolee's \nlatest test email [1]. We need a test that gets the sequencer to fork \n'git commit' rewording a commit should do that.\n\nBest Wishes\n\nPhillip\n\n[1] \nhttps://public-inbox.org/git/ed8e65a2-72e8-210c-d4a4-eacdb5c7b0e8@gmail.com/\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 +950,24 @@ static int run_git_commit(struct repository *r,\n>   \n>   \tcmd.git_cmd = 1;\n>   \n> +        if (opts->committer_date_is_author_date) {\n> +\t        int res = -1;\n> +\t        struct strbuf datebuf = STRBUF_INIT;\n> +\t        char *date = read_author_date_or_null();\n> +\n> +\t        if (!date)\n> +\t                return -1;\n> +\n> +\t        strbuf_addf(&datebuf, \"@%s\", date);\n> +\t        res = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf, 1);\n> +\n> +\t\tstrbuf_release(&datebuf);\n> +\t        free(date);\n> +\n> +\t        if (res)\n> +\t                return -1;\n> +        }\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> @@ -1331,7 +1361,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\", NULL };\n>   \t\tconst char *out_enc = get_commit_output_encoding();\n> @@ -1359,6 +1388,26 @@ 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\treturn error(_(\"malformed ident line\"));\n> +\t\tif (!ident.date_begin)\n> +\t\t\treturn error(_(\"corrupted author without date information\"));\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> @@ -2473,6 +2522,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> @@ -2555,6 +2609,8 @@ 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->reschedule_failed_exec)\n>   \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n>   \n> @@ -3752,7 +3808,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 6704acbb9c..e3881e9275 100644\n> --- a/sequencer.h\n> +++ b/sequencer.h\n> @@ -43,6 +43,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 4342f79eea..7402f7e3da 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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\n> index 2e16e00a9d..6c1fbab4d8 100755\n> --- a/t/t3433-rebase-options-compatibility.sh\n> +++ b/t/t3433-rebase-options-compatibility.sh\n> @@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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> @@ -26,8 +29,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> @@ -62,4 +70,33 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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 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>   test_done\n> \n"},{"id":"384790","messageId":"6208a090-09ff-8756-2d9a-1fd7b9be6197@gmail.com","threadId":"51596","inReplyTo":"20191006175747.17340-1-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v4 5/6] rebase -i: support --ignore-date","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-10-24T20:36:55Z","receivedAt":"2019-10-24T20:37:01Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 06/10/2019 18:57, Rohit Ashiwal wrote:\n> On Fri, 27 Sep 2019 11:00:58 +0100 Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>\n>> [...]\n> \n> Thanks for all the advice and improvements.\n> \n>> [...]\n>> It's good to see the new test. Did you see Stolee's email [4] about the\n>> test coverage of the previous version of this series? You should check\n>> that this series tests all the untested non-error handling lines.\n>>\n>> [4]\n>> https://public-inbox.org/git/1ed86989-9ba2-0cd7-b6f7-654d1943b1d7@gmail.com/\n> \n> Yes, I've seen it and have improved the test since.\n\nHave you improved it since v4? Stolee's latest email [1] still shows \npush_date() as completely untested. We need a test that gets the \nsequencer to fork git-commit, the easiest way is probably to reword a \ncommit. Also the new code for ignoring the date when we fork 'git merge' \nis untested. Having a test that does an octopus merge or sets a merge \nstrategy (or merge strategy option) should fix that.\n\nBest Wishes\n\nPhillip\n\n[1] \nhttps://public-inbox.org/git/ed8e65a2-72e8-210c-d4a4-eacdb5c7b0e8@gmail.com/\n\n\n> Thanks\n> Rohit\n> \n"},{"id":"385261","messageId":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20190806173638.17510-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v5 0/6] rebase -i: support more options","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-11-01T13:59:57Z","receivedAt":"2019-11-01T14:01:16Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"Hey Everyone\n\nI got really busy lately, posting the patch now.\n - Now handles the combination of --ignore-date and\n   --committer-date-is-author-date properly.\n - Improved code coverage\n - addressed the compatibility of --rebase-merges with --strategy\n\nThanks\nRohit\n\nRohit Ashiwal (6):\n  rebase -i: add --ignore-whitespace flag\n  sequencer: allow callers of read_author_script() to ignore fields\n  rebase -i: support --committer-date-is-author-date\n  sequencer: rename amend_author to author_to_rename\n  rebase -i: support --ignore-date\n  rebase: add --reset-author-date\n\n Documentation/git-rebase.txt            |  25 ++++-\n builtin/rebase.c                        |  48 ++++++--\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 6 files changed, 321 insertions(+), 28 deletions(-)\n create mode 100755 t/t3433-rebase-options-compatibility.sh\n\nRange-diff:\n  2:  77af1d66db ! 491:  e155af5a39 rebase -i: add --ignore-whitespace flag\n    @@ -16,7 +16,7 @@\n      --- a/Documentation/git-rebase.txt\n      +++ b/Documentation/git-rebase.txt\n     @@\n    - default is `--no-fork-point`, otherwise the default is `--fork-point`.\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    @@ -46,9 +46,8 @@\n       * --preserve-merges and --signoff\n       * --preserve-merges and --rebase-merges\n     + * --preserve-merges and --ignore-whitespace\n    -+ * --rebase-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      diff --git a/builtin/rebase.c b/builtin/rebase.c\n    @@ -124,16 +123,6 @@\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    -@@\n    - \t}\n    - \n    - \tif (options.rebase_merges) {\n    -+\t\tif (options.ignore_whitespace)\n    -+\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n    -+\t\t\t      \"'--ignore-whitespace'\"));\n    - \t\tif (strategy_options.nr)\n    - \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n    - \t\t\t      \"'--strategy-option'\"));\n     \n      diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n      --- a/t/t3422-rebase-incompatible-options.sh\n  3:  1f7f1407b2 = 492:  7ec673ebcb sequencer: allow callers of read_author_script() to ignore fields\n  4:  cc1614154e ! 493:  5af0d628de rebase -i: support --committer-date-is-author-date\n    @@ -40,9 +40,9 @@\n       * --preserve-merges and --rebase-merges\n       * --preserve-merges and --ignore-whitespace\n     + * --preserve-merges and --committer-date-is-author-date\n    -  * --rebase-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      diff --git a/builtin/rebase.c b/builtin/rebase.c\n      --- a/builtin/rebase.c\n    @@ -173,10 +173,14 @@\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\treturn error(_(\"malformed ident line\"));\n    -+\t\tif (!ident.date_begin)\n    -+\t\t\treturn error(_(\"corrupted author without date information\"));\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    @@ -296,7 +300,7 @@\n     +\n     +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n     +\tgit checkout side &&\n    -+\tgit merge commit3 &&\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  5:  9e92c79bda = 494:  c7846945dd sequencer: rename amend_author to author_to_rename\n  6:  fc68e55e78 ! 495:  02f797b84d rebase -i: support --ignore-date\n    @@ -17,8 +17,8 @@\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 value\n    -+\tsame as the current time. This implies --force-rebase.\n    ++\tInstead of using the given author date, reset it to the\n    ++\tcurrent time. This implies --force-rebase.\n      +\n      See also INCOMPATIBLE OPTIONS below.\n      \n    @@ -35,9 +35,9 @@\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 --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      diff --git a/builtin/rebase.c b/builtin/rebase.c\n      --- a/builtin/rebase.c\n    @@ -83,10 +83,6 @@\n      \t}\n      \n     -\tif (options.committer_date_is_author_date)\n    -+\tif (options.ignore_date) {\n    -+\t\toptions.committer_date_is_author_date = 0;\n    -+\t\tsetenv(\"GIT_COMMITTER_DATE\", \"\", 1);\n    -+\t}\n     +\tif (options.committer_date_is_author_date ||\n     +\t    options.ignore_date)\n      \t\toptions.flags |= REBASE_FORCE;\n    @@ -128,35 +124,56 @@\n     +\t}\n     +\tlen = ident.mail_end - ident.name_begin + 1;\n     +\n    -+\tstrbuf_addf(&new_author, \"%.*s \", len, author);\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)\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    -+\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_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    +@@\n    + \t                return -1;\n    + \n    + \t        strbuf_addf(&datebuf, \"@%s\", date);\n    +-\t        res = 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        free(date);\n     @@\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);\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     @@\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    +@@\n      \n      \treset_ident_date();\n      \n    @@ -198,7 +215,7 @@\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);\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    @@ -239,31 +256,25 @@\n     +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n     +\tgit rebase --ignore-date HEAD^ &&\n     +\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n    -+\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n    -+\tgrep \"+0000\" authortime &&\n    -+\tgrep \"+0000\" committertime\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 show HEAD --pretty=\"format:%ci\" >committertime &&\n    -+\tgrep \"+0000\" authortime &&\n    -+\tgrep \"+0000\" committertime\n    ++\tgrep \"+0000\" authortime\n     +'\n     +\n     +test_expect_success '--ignore-date works with rebase -r' '\n     +\tgit checkout side &&\n    -+\tgit merge commit3 &&\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\tgit show $HASH --pretty=\"format:%ci\" >committertime\n     +\t\tgrep \"+0000\" authortime\n    -+\t\tgrep \"+0000\" committertime\n     +\tdone <rev_list\n     +'\n     +\n  7:  396d5f16eb ! 496:  7a9fe1e612 rebase: add --reset-author-date\n    @@ -17,8 +17,8 @@\n      \n      --ignore-date::\n     +--reset-author-date::\n    - \tInstead of using the given author date, reset it to the value\n    - \tsame as the current time. This implies --force-rebase.\n    + \tInstead of using the given author date, reset it to the\n    + \tcurrent time. This implies --force-rebase.\n      +\n     \n      diff --git a/builtin/rebase.c b/builtin/rebase.c\n-- \n2.21.0\n\n"},{"id":"385262","messageId":"20191101140003.13960-2-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v5 1/6] rebase -i: add --ignore-whitespace flag","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-11-01T13:59:58Z","receivedAt":"2019-11-01T14:01:19Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"There are two backends available for rebasing, viz, the am and the\ninteractive. Naturally, there shall be some features that are\nimplemented in one but not in the other. One such flag is\n--ignore-whitespace which indicates merge mechanism to treat lines\nwith only whitespace changes as unchanged. Wire the interactive\nrebase to also understand the --ignore-whitespace flag by\ntranslating it to -Xignore-space-change.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 12 ++++-\n builtin/rebase.c                        | 19 ++++++--\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 65 +++++++++++++++++++++++++\n 4 files changed, 90 insertions(+), 7 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 639a4179d1..b4de299e6f 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -393,8 +393,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+'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@@ -542,7 +550,6 @@ The following options:\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 +572,7 @@ 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  * --keep-base and --onto\n  * --keep-base and --root\n \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 4a20582e72..2f2ba3e8e7 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -79,6 +79,7 @@ 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 \tchar *cmd;\n@@ -99,6 +100,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@@ -114,9 +116,15 @@ 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+\tstrbuf_release(&strategy_buf);\n \treturn replay;\n }\n \n@@ -512,6 +520,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@@ -965,6 +975,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@@ -1431,9 +1443,6 @@ 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@@ -1441,6 +1450,8 @@ 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\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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nnew file mode 100755\nindex 0000000000..2e16e00a9d\n--- /dev/null\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -0,0 +1,65 @@\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+# 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 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_done\n-- \n2.21.0\n\n"},{"id":"385263","messageId":"20191101140003.13960-3-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v5 2/6] sequencer: allow callers of read_author_script() to ignore fields","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-11-01T13:59:59Z","receivedAt":"2019-11-01T14:01:21Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The current callers of the read_author_script() function read name,\nemail and date from the author script.  Allow callers to signal that\nthey are not interested in some among these three fields by passing\nNULL.\n\nNote that fields that are ignored still must exist and be formatted\ncorrectly in the author script.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n sequencer.c | 16 +++++++++++++---\n 1 file changed, 13 insertions(+), 3 deletions(-)\n\ndiff --git a/sequencer.c b/sequencer.c\nindex 9d5964fd81..6954b9eea9 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -823,9 +823,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-- \n2.21.0\n\n"},{"id":"385264","messageId":"20191101140003.13960-4-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v5 3/6] rebase -i: support --committer-date-is-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-11-01T14:00:00Z","receivedAt":"2019-11-01T14:01:25Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the committer date\nby changing it to the author date. Let's add the same for\ninteractive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            | 10 ++--\n builtin/rebase.c                        | 17 +++++--\n sequencer.c                             | 65 ++++++++++++++++++++++++-\n sequencer.h                             |  1 +\n t/t3422-rebase-incompatible-options.sh  |  1 -\n t/t3433-rebase-options-compatibility.sh | 37 ++++++++++++++\n 6 files changed, 120 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex b4de299e6f..e948a24433 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -408,9 +408,13 @@ unchanged for the sake of a three-way merge.\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+\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@@ -547,7 +551,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --committer-date-is-author-date\n  * --ignore-date\n  * --whitespace\n  * -C\n@@ -573,6 +576,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 --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 2f2ba3e8e7..9227801ef6 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -82,6 +82,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@@ -114,6 +115,8 @@ 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.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);\n \treplay.strategy = opts->strategy;\n \n@@ -977,6 +980,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@@ -1443,9 +1448,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@@ -1723,10 +1728,12 @@ 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\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\toptions.flags |= REBASE_FORCE;\ndiff --git a/sequencer.c b/sequencer.c\nindex 6954b9eea9..e2c324b3a6 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -147,6 +147,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@@ -878,6 +879,17 @@ 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 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@@ -937,6 +949,24 @@ static int run_git_commit(struct repository *r,\n \n \tcmd.git_cmd = 1;\n \n+        if (opts->committer_date_is_author_date) {\n+\t        int res = -1;\n+\t        struct strbuf datebuf = STRBUF_INIT;\n+\t        char *date = read_author_date_or_null();\n+\n+\t        if (!date)\n+\t                return -1;\n+\n+\t        strbuf_addf(&datebuf, \"@%s\", date);\n+\t        res = setenv(\"GIT_COMMITTER_DATE\", datebuf.buf, 1);\n+\n+\t\tstrbuf_release(&datebuf);\n+\t        free(date);\n+\n+\t        if (res)\n+\t                return -1;\n+        }\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@@ -1330,7 +1360,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\", NULL };\n \t\tconst char *out_enc = get_commit_output_encoding();\n@@ -1358,6 +1387,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\"));\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@@ -2480,6 +2533,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@@ -2562,6 +2620,8 @@ 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->reschedule_failed_exec)\n \t\twrite_file(rebase_path_reschedule_failed_exec(), \"%s\", \"\");\n \n@@ -3769,7 +3829,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 574260f621..ffddf011cc 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -43,6 +43,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex 2e16e00a9d..a98cfe18b7 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -7,6 +7,9 @@ test_description='tests to ensure compatibility between am and interactive backe\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@@ -26,8 +29,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@@ -62,4 +70,33 @@ test_expect_success '--ignore-whitespace works with interactive backend' '\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 test_done\n-- \n2.21.0\n\n"},{"id":"385265","messageId":"20191101140003.13960-5-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v5 4/6] sequencer: rename amend_author to author_to_rename","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-11-01T14:00:01Z","receivedAt":"2019-11-01T14:01:29Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The purpose of amend_author was to free() the malloc()'d string\nobtained from get_author() while 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 e2c324b3a6..34e45246f7 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1353,7 +1353,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@@ -1374,7 +1374,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.21.0\n\n"},{"id":"385266","messageId":"20191101140003.13960-6-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v5 5/6] rebase -i: support --ignore-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-11-01T14:00:02Z","receivedAt":"2019-11-01T14:01:34Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"rebase am already has this flag to \"lie\" about the author date\nby changing it to the committer (current) date. Let's add the same\nfor interactive machinery.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt            |  6 +--\n builtin/rebase.c                        | 14 +++---\n sequencer.c                             | 60 +++++++++++++++++++++++--\n sequencer.h                             |  1 +\n t/t3433-rebase-options-compatibility.sh | 29 ++++++++++++\n 5 files changed, 99 insertions(+), 11 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex e948a24433..3580447f2f 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -413,8 +413,8 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This 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 +\n See also INCOMPATIBLE OPTIONS below.\n \n@@ -551,7 +551,6 @@ INCOMPATIBLE OPTIONS\n \n The following options:\n \n- * --ignore-date\n  * --whitespace\n  * -C\n \n@@ -577,6 +576,7 @@ In addition, the following pairs of options are incompatible:\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 9227801ef6..7edae668f8 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -83,6 +83,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@@ -117,6 +118,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@@ -982,6 +984,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@@ -1451,8 +1455,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@@ -1728,13 +1732,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+\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, \"--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 34e45246f7..a4c6a47bea 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -148,6 +148,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@@ -890,6 +891,36 @@ static char *read_author_date_or_null(void)\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@@ -958,7 +989,8 @@ static int run_git_commit(struct repository *r,\n \t                return -1;\n \n \t        strbuf_addf(&datebuf, \"@%s\", date);\n-\t        res = 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        free(date);\n@@ -982,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@@ -1404,7 +1438,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@@ -1454,6 +1489,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@@ -2538,6 +2582,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@@ -2622,6 +2671,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\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@@ -3557,6 +3608,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@@ -3830,7 +3883,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 ffddf011cc..3e6275272a 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -44,6 +44,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/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh\nindex a98cfe18b7..5166f158dd 100755\n--- a/t/t3433-rebase-options-compatibility.sh\n+++ b/t/t3433-rebase-options-compatibility.sh\n@@ -99,4 +99,33 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '\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.21.0\n\n"},{"id":"385267","messageId":"20191101140003.13960-7-rohit.ashiwal265@gmail.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"[PATCH v5 6/6] rebase: add --reset-author-date","fromName":"Rohit Ashiwal","fromEmail":"rohit.ashiwal265@gmail.com","sentAt":"2019-11-01T14:00:03Z","receivedAt":"2019-11-01T14:01:37Z","isPatch":true,"sender":{"key":"rohit.ashiwal265@gmail.com","avatar":"https://avatars.githubusercontent.com/u/31043830?v=4"},"body":"The previous commit introduced --ignore-date flag to interactive\nrebase, but the name is actually very vague in context of rebase -i\nsince there are two dates we can work with. Add an alias to convey\nthe precise purpose.\n\nSigned-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com>\n---\n Documentation/git-rebase.txt | 1 +\n builtin/rebase.c             | 2 ++\n 2 files changed, 3 insertions(+)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 3580447f2f..cb4ab43998 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -413,6 +413,7 @@ See also INCOMPATIBLE OPTIONS below.\n \tas the committer date. This implies --force-rebase.\n \n --ignore-date::\n+--reset-author-date::\n \tInstead of using the given author date, reset it to the\n \tcurrent time. This implies --force-rebase.\n +\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 7edae668f8..edefdd016b 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1455,6 +1455,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_BOOL(0, \"reset-author-date\", &options.ignore_date,\n+\t\t\t \"ignore author date and use current 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_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_(\"n\"),\n-- \n2.21.0\n\n"},{"id":"385308","messageId":"xmqqa79e3f8v.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20191101140003.13960-6-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v5 5/6] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-02T07:32:32Z","receivedAt":"2019-11-02T07:32:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n\n>  --ignore-date::\n> +\tInstead of using the given author date, reset it to the\n> +\tcurrent time. This implies --force-rebase.\n\nThe first sentence is unclear and puzzles me with \"for what?\".  IOW,\nyou are saying that by default the command uses the given (I presume\nthat you meant what is recorded in the original commits being\nrebased---but we should find a way to explain it more clearly)\nauthor date, but with this option what is used is reset to the\ncurrent time.  It is left unspecified what the command is using that\ntime for.\n\nPerhaps (I am writing this paragraph after writing the rest of the\nmessage, i.e. after reading the patch through):\n\n\tBy default, the author date recorded in the commit being\n\trebased as the author date is used as the author date of the\n\trebased commits.  The option tells Git to use the current\n\ttimestamp as the author date of the rebased commits instead.\n\tThis implies `--force-rebase`.\n\nThe committer-date-is-author-date is indirectly also affected by\nthis option, because it (re)uses the \"author date\", but by making it\nclear where the \"author date\" comes from in the description of this\noption, it would make the interaction between these two options\nobvious, hopefully ;-)\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\nIt probably is a good idea to use dash not underscore for\ncdate-is-adata and ignore-date, the two files you are adding.\n\nIt would be good to eventually fix the existing gpg-sign-opt to\nfollow suit, but not as a part of this series.\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\nI am tempted to suggest adding a /* NEEDSWORK */ comment to remind\nus that we'd want to eventually use date.c::get_time() here, but not\nas part of this series.  But grepping for \"\\<time(\" is easy enough\nso I can live without it.\n\n> +\tstrbuf_addf(&date, \"@%\"PRIuMAX, (uintmax_t)now);\n> +\targv_array_pushf(&child->env_array, \"GIT_AUTHOR_DATE=%s\", date.buf);\n\nOK, so we get author-date of \"now\" (which we do not do normally)\nwhen the caller decides to call us (which is, under\n\"--ignore-date\").\n\n> +\tif (change_committer_date)\n> +\t\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_DATE=%s\", date.buf);\n\nAnd when we are using --committer-date-is-author-date, we muck with\nthe committer-date as well.\n\nMakes sense.\n\n> @@ -958,7 +989,8 @@ static int run_git_commit(struct repository *r,\n>  \t                return -1;\n>  \n>  \t        strbuf_addf(&datebuf, \"@%s\", date);\n> -\t        res = 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\nThis is the codepath that handles committer-date-is-author-date\noption.  We read the author date into \"date\", and used to\nunconditionally use it as the committer date.  With --ignore-date,\nwe behave differently.\n\nIt may happen that an empty string in GIT_COMMITTER_DATE is treated\nthe same way as missing GIT_COMMITTER_DATE, i.e. unspecified.\n\n\tif (opts->ignore_date)\n\t\tres = unsetenv(\"GIT_COMMITTER_DATE\");\n\telse\n        \tres = setenv(...);\n\nwould be conceptually clearer.\n\nBut then we would notice that there is no reason to even read the\nauthor-date into date if ignore-date is set, no?  So the whole thing\nnow becomes\n\n\t-\tif (opts->committer_date_is_author_date) {\n\t+\tif (!opts->ignore_date && opts->committer_date_is_author_date) {\n\nwhich feels even cleaner.  Am I missing some subtleties (e.g. are we\nworried about the case where the user has GIT_COMMITTER_DATE set and\nexported to the environment of the shell that starts \"git rebase\", or\nsomething like that?)???\n\n> @@ -982,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> @@ -1404,7 +1438,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\nThe same comment as the early half of the above, on relying on the\nempty date string instead of an explicit unsetenv().\n\n> @@ -1454,6 +1489,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\nThe helper function called here begins with this comment:\n\n\"Construct a free()able author string with current time as the author date\"\n\nbut without reading (and memorizing) it, ignore_author_date()\nfunction sounds like a boolean that tells us \"are we told to\nignore the author date?\"\n\nIt sorely wants a better name to tell the reader that it is the\nauthor ident with current timestamp.\n\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> @@ -2538,6 +2582,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\nOK.\n\n> @@ -3557,6 +3608,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\nOK, we've seen the callee above already and we know what this does.\n\n> @@ -3830,7 +3883,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\nWe may want to switch this assert(...) and others to \"if (!(...))\nBUG()\" someday, but not as part of this patch.\n\n"},{"id":"385309","messageId":"xmqq5zk23f5d.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20191101140003.13960-7-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v5 6/6] rebase: add --reset-author-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-02T07:34:38Z","receivedAt":"2019-11-02T07:35:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n\n>  --ignore-date::\n> +--reset-author-date::\n>  \tInstead of using the given author date, reset it to the\n>  \tcurrent time. This implies --force-rebase.\n>  +\n> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 7edae668f8..edefdd016b 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -1455,6 +1455,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_BOOL(0, \"reset-author-date\", &options.ignore_date,\n> +\t\t\t \"ignore author date and use current date\"),\n>  \t\tOPT_BOOL(0, \"ignore-date\", &options.ignore_date,\n>  \t\t\t \"ignore author date and use current date\"),\n\nOne of them should say it is a mere synonym to the other (or hide\nfrom the \"git rebase -h\" listing altogether).  Otherwise readers\nwould be puzzled what the difference between the two are.\n\nThanks.\n\n"},{"id":"385310","messageId":"xmqqy2wy1zy5.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"xmqqa79e3f8v.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v5 5/6] rebase -i: support --ignore-date","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-02T07:48:18Z","receivedAt":"2019-11-02T07:48:25Z","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> Rohit Ashiwal <rohit.ashiwal265@gmail.com> writes:\n>\n>>  --ignore-date::\n>> +\tInstead of using the given author date, reset it to the\n>> +\tcurrent time. This implies --force-rebase.\n>\n> The first sentence is unclear and puzzles me with \"for what?\".  IOW,\n> you are saying that by default the command uses the given (I presume\n> that you meant what is recorded in the original commits being\n> rebased---but we should find a way to explain it more clearly)\n> author date, but with this option what is used is reset to the\n> current time.  It is left unspecified what the command is using that\n> time for.\n>\n> Perhaps (I am writing this paragraph after writing the rest of the\n> message, i.e. after reading the patch through):\n\nOops, too much re-editing without final proofreading.  Sorry.\n\n> \tBy default, the author date recorded in the commit being\n> \trebased as the author date is used as the author date of the\n> \trebased commits.  The option tells Git to use the current\n> \ttimestamp as the author date of the rebased commits instead.\n> \tThis implies `--force-rebase`.\n\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\nwould be much less redundant without losing clarity.\n"},{"id":"386702","messageId":"xmqqimnd92nv.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v5 0/6] rebase -i: support more options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-21T06:14:28Z","receivedAt":"2019-11-21T06:14:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"As I hate to leave a mostly done topic hanging around forever, I am\ntempted to queue these fixups on top (instead of squash them in) to\ntie the loose ends after a few weeks' inactivity.\n\nThanks.\n\n-- >8 --\nSubject: rebase -i: finishes touches to --reset-author-date\n\nClarify the way the `--reset-author-date` option is described,\nand mark its usage string translatable.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/git-rebase.txt | 6 ++++--\n builtin/rebase.c             | 6 +++---\n 2 files changed, 7 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex c8d54d221d..03809da835 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -392,8 +392,10 @@ See also INCOMPATIBLE OPTIONS below.\n \n --ignore-date::\n --reset-author-date::\n-\tInstead of using the given author date, reset it to the\n-\tcurrent time. This implies --force-rebase.\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 \ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 44768082b8..d5c09f159c 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1437,9 +1437,9 @@ 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, \"reset-author-date\", &options.ignore_date,\n-\t\t\t \"ignore author date and use current date\"),\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_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n+\t\t\t\tN_(\"synonym of --reset-autohr-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\n\n"},{"id":"386706","messageId":"36162d31-0463-5e21-fbf6-53667fffc000@gmail.com","threadId":"51596","inReplyTo":"xmqqimnd92nv.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v5 0/6] rebase -i: support more options","fromName":"Alban Gruin","fromEmail":"alban.gruin@gmail.com","sentAt":"2019-11-21T08:17:49Z","receivedAt":"2019-11-21T08:18:00Z","isPatch":true,"sender":{"key":"alban.gruin@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6310153?v=4"},"body":"Hi Junio,\n\nLe 21/11/2019 à 07:14, Junio C Hamano a écrit :\n> As I hate to leave a mostly done topic hanging around forever, I am\n> tempted to queue these fixups on top (instead of squash them in) to\n> tie the loose ends after a few weeks' inactivity.\n> \n> Thanks.\n> \n> -- >8 --\n> Subject: rebase -i: finishes touches to --reset-author-date\n> \n> Clarify the way the `--reset-author-date` option is described,\n> and mark its usage string translatable.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  Documentation/git-rebase.txt | 6 ++++--\n>  builtin/rebase.c             | 6 +++---\n>  2 files changed, 7 insertions(+), 5 deletions(-)\n> \n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n> index c8d54d221d..03809da835 100644\n> --- a/Documentation/git-rebase.txt\n> +++ b/Documentation/git-rebase.txt\n> @@ -392,8 +392,10 @@ See also INCOMPATIBLE OPTIONS below.\n>  \n>  --ignore-date::\n>  --reset-author-date::\n> -\tInstead of using the given author date, reset it to the\n> -\tcurrent time. This implies --force-rebase.\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> diff --git a/builtin/rebase.c b/builtin/rebase.c\n> index 44768082b8..d5c09f159c 100644\n> --- a/builtin/rebase.c\n> +++ b/builtin/rebase.c\n> @@ -1437,9 +1437,9 @@ 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, \"reset-author-date\", &options.ignore_date,\n> -\t\t\t \"ignore author date and use current date\"),\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_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n> +\t\t\t\tN_(\"synonym of --reset-autohr-date\")),\n\nThere is a typo here.\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\", &options.ignore_whitespace,\n> \n> \n\nCheers,\nAlban\n\n"},{"id":"386800","messageId":"xmqqlfs84e14.fsf@gitster-ct.c.googlers.com","threadId":"51596","inReplyTo":"36162d31-0463-5e21-fbf6-53667fffc000@gmail.com","subject":"Re: [PATCH v5 0/6] rebase -i: support more options","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-22T06:32:23Z","receivedAt":"2019-11-22T06:32:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alban Gruin <alban.gruin@gmail.com> writes:\n\n>> +\t\tOPT_HIDDEN_BOOL(0, \"ignore-date\", &options.ignore_date,\n>> +\t\t\t\tN_(\"synonym of --reset-autohr-date\")),\n>\n> There is a typo here.\n\nOops. I think you meant s/autohr/author/, so I've fixed it up\nlocally---if you spotted something else, please let me know.\n\nThanks.\n"},{"id":"387274","messageId":"5bab5b95-b8e3-5e63-b592-b5cac30c8068@gmail.com","threadId":"51596","inReplyTo":"20191101140003.13960-1-rohit.ashiwal265@gmail.com","subject":"Re: [PATCH v5 0/6] rebase -i: support more options","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-11-28T11:14:21Z","receivedAt":"2019-11-28T11:14:29Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Rohit\n\nOn 01/11/2019 13:59, Rohit Ashiwal wrote:\n> Hey Everyone\n> \n> I got really busy lately, posting the patch now.\n>   - Now handles the combination of --ignore-date and\n>     --committer-date-is-author-date properly.\n>   - Improved code coverage\n\nLooking at the range-diff there's only a one line change to the tests. I \nsound like a broken record but Stolee's latest test report[1] shows \nthere are still uncovered lines.\n\n > Rohit Ashiwal\tc068bcc5 sequencer: allow callers of \nread_author_script() to ignore fields\n > sequencer.c\n > c068bcc5 840) free(kv.items[date_i].util);\n >\n > Rohit Ashiwal\tcbd8db17 rebase -i: support --committer-date-is-author-date\n > sequencer.c\n > cbd8db17 890) return NULL;\n > cbd8db17 989) return -1;\n > cbd8db17 1428) goto out;\n > cbd8db17 1432) goto out;\n > cbd8db17 2603) opts->allow_ff = 0;\n > cbd8db17 2604) opts->committer_date_is_author_date = 1;\n\nThese last two should be tested I think\n\n > Rohit Ashiwal\t08187b4c rebase -i: support --ignore-date\n > sequencer.c\n > 08187b4c 903) return NULL;\n > 08187b4c 920) argv_array_pushf(&child->env_array, \n\"GIT_COMMITTER_DATE=%s\", date.buf);\n\nThis should be tested\n\n > 08187b4c 1508) res = -1;\n > 08187b4c 1509) goto out;\n > 08187b4c 2608) opts->allow_ff = 0;\n > 08187b4c 2609) opts->ignore_date = 1;\n > 08187b4c 3639) push_dates(&cmd, opts->committer_date_is_author_date);\n\nAs should these three\n\nBest Wishes\n\nPhillip\n\n[1] \nhttps://lore.kernel.org/git/1cb7ddbf-020e-d63a-85b6-5a9267c0a5a3@gmail.com/\n\n\n>   - addressed the compatibility of --rebase-merges with --strategy\n> \n> Thanks\n> Rohit\n> \n> Rohit Ashiwal (6):\n>    rebase -i: add --ignore-whitespace flag\n>    sequencer: allow callers of read_author_script() to ignore fields\n>    rebase -i: support --committer-date-is-author-date\n>    sequencer: rename amend_author to author_to_rename\n>    rebase -i: support --ignore-date\n>    rebase: add --reset-author-date\n> \n>   Documentation/git-rebase.txt            |  25 ++++-\n>   builtin/rebase.c                        |  48 ++++++--\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>   6 files changed, 321 insertions(+), 28 deletions(-)\n>   create mode 100755 t/t3433-rebase-options-compatibility.sh\n> \n> Range-diff:\n>    2:  77af1d66db ! 491:  e155af5a39 rebase -i: add --ignore-whitespace flag\n>      @@ -16,7 +16,7 @@\n>        --- a/Documentation/git-rebase.txt\n>        +++ b/Documentation/git-rebase.txt\n>       @@\n>      - default is `--no-fork-point`, otherwise the default is `--fork-point`.\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>      @@ -46,9 +46,8 @@\n>         * --preserve-merges and --signoff\n>         * --preserve-merges and --rebase-merges\n>       + * --preserve-merges and --ignore-whitespace\n>      -+ * --rebase-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>        diff --git a/builtin/rebase.c b/builtin/rebase.c\n>      @@ -124,16 +123,6 @@\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>      -@@\n>      - \t}\n>      -\n>      - \tif (options.rebase_merges) {\n>      -+\t\tif (options.ignore_whitespace)\n>      -+\t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n>      -+\t\t\t      \"'--ignore-whitespace'\"));\n>      - \t\tif (strategy_options.nr)\n>      - \t\t\tdie(_(\"cannot combine '--rebase-merges' with \"\n>      - \t\t\t      \"'--strategy-option'\"));\n>       \n>        diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh\n>        --- a/t/t3422-rebase-incompatible-options.sh\n>    3:  1f7f1407b2 = 492:  7ec673ebcb sequencer: allow callers of read_author_script() to ignore fields\n>    4:  cc1614154e ! 493:  5af0d628de rebase -i: support --committer-date-is-author-date\n>      @@ -40,9 +40,9 @@\n>         * --preserve-merges and --rebase-merges\n>         * --preserve-merges and --ignore-whitespace\n>       + * --preserve-merges and --committer-date-is-author-date\n>      -  * --rebase-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>        diff --git a/builtin/rebase.c b/builtin/rebase.c\n>        --- a/builtin/rebase.c\n>      @@ -173,10 +173,14 @@\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\treturn error(_(\"malformed ident line\"));\n>      -+\t\tif (!ident.date_begin)\n>      -+\t\t\treturn error(_(\"corrupted author without date information\"));\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>      @@ -296,7 +300,7 @@\n>       +\n>       +test_expect_success '--committer-date-is-author-date works with rebase -r' '\n>       +\tgit checkout side &&\n>      -+\tgit merge commit3 &&\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>    5:  9e92c79bda = 494:  c7846945dd sequencer: rename amend_author to author_to_rename\n>    6:  fc68e55e78 ! 495:  02f797b84d rebase -i: support --ignore-date\n>      @@ -17,8 +17,8 @@\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 value\n>      -+\tsame as the current time. This implies --force-rebase.\n>      ++\tInstead of using the given author date, reset it to the\n>      ++\tcurrent time. This implies --force-rebase.\n>        +\n>        See also INCOMPATIBLE OPTIONS below.\n>        \n>      @@ -35,9 +35,9 @@\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 --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>        diff --git a/builtin/rebase.c b/builtin/rebase.c\n>        --- a/builtin/rebase.c\n>      @@ -83,10 +83,6 @@\n>        \t}\n>        \n>       -\tif (options.committer_date_is_author_date)\n>      -+\tif (options.ignore_date) {\n>      -+\t\toptions.committer_date_is_author_date = 0;\n>      -+\t\tsetenv(\"GIT_COMMITTER_DATE\", \"\", 1);\n>      -+\t}\n>       +\tif (options.committer_date_is_author_date ||\n>       +\t    options.ignore_date)\n>        \t\toptions.flags |= REBASE_FORCE;\n>      @@ -128,35 +124,56 @@\n>       +\t}\n>       +\tlen = ident.mail_end - ident.name_begin + 1;\n>       +\n>      -+\tstrbuf_addf(&new_author, \"%.*s \", len, author);\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)\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>      -+\targv_array_pushf(&child->env_array, \"GIT_COMMITTER_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>      +@@\n>      + \t                return -1;\n>      +\n>      + \t        strbuf_addf(&datebuf, \"@%s\", date);\n>      +-\t        res = 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        free(date);\n>       @@\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);\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>       @@\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>      +@@\n>        \n>        \treset_ident_date();\n>        \n>      @@ -198,7 +215,7 @@\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);\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>      @@ -239,31 +256,25 @@\n>       +\tgit commit --amend --date=\"$GIT_AUTHOR_DATE\" &&\n>       +\tgit rebase --ignore-date HEAD^ &&\n>       +\tgit show HEAD --pretty=\"format:%ai\" >authortime &&\n>      -+\tgit show HEAD --pretty=\"format:%ci\" >committertime &&\n>      -+\tgrep \"+0000\" authortime &&\n>      -+\tgrep \"+0000\" committertime\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 show HEAD --pretty=\"format:%ci\" >committertime &&\n>      -+\tgrep \"+0000\" authortime &&\n>      -+\tgrep \"+0000\" committertime\n>      ++\tgrep \"+0000\" authortime\n>       +'\n>       +\n>       +test_expect_success '--ignore-date works with rebase -r' '\n>       +\tgit checkout side &&\n>      -+\tgit merge commit3 &&\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\tgit show $HASH --pretty=\"format:%ci\" >committertime\n>       +\t\tgrep \"+0000\" authortime\n>      -+\t\tgrep \"+0000\" committertime\n>       +\tdone <rev_list\n>       +'\n>       +\n>    7:  396d5f16eb ! 496:  7a9fe1e612 rebase: add --reset-author-date\n>      @@ -17,8 +17,8 @@\n>        \n>        --ignore-date::\n>       +--reset-author-date::\n>      - \tInstead of using the given author date, reset it to the value\n>      - \tsame as the current time. This implies --force-rebase.\n>      + \tInstead of using the given author date, reset it to the\n>      + \tcurrent time. This implies --force-rebase.\n>        +\n>       \n>        diff --git a/builtin/rebase.c b/builtin/rebase.c\n> \n"}]}