@matheusbsbs / matheus-bagliano / commits / 08187b4cba
Fork 0

rebase -i: support --ignore-date

rebase am already has this flag to "lie" about the author date by changing it to the committer (current) date. Let's add the same for interactive machinery. Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Rohit Ashiwal committed Nov 1, 2019 at 19:30 UTC 08187b4cbac2b2f870bb9c786d545b67f0262f74
5 files changed +99 -11
Documentation/git-rebase.txt
+3 -3
@@ -391,8 +391,8 @@ See also INCOMPATIBLE OPTIONS below.
391 as the committer date. This implies --force-rebase.
392
393 --ignore-date::
394 - This flag is passed to 'git am' to change the author date
395 - of each rebased commit (see linkgit:git-am[1]).
394 + Instead of using the given author date, reset it to the
395 + current time. This implies --force-rebase.
396 +
397 See also INCOMPATIBLE OPTIONS below.
398
@@ -529,7 +529,6 @@ INCOMPATIBLE OPTIONS
529
530 The following options:
531
532 - * --ignore-date
532 * --whitespace
533 * -C
534
@@ -555,6 +554,7 @@ In addition, the following pairs of options are incompatible:
554 * --preserve-merges and --rebase-merges
555 * --preserve-merges and --ignore-whitespace
556 * --preserve-merges and --committer-date-is-author-date
557 + * --preserve-merges and --ignore-date
558 * --rebase-merges and --strategy
559 * --rebase-merges and --strategy-option
560
builtin/rebase.c
+9 -5
@@ -83,6 +83,7 @@ struct rebase_options {
83 char *gpg_sign_opt;
84 int autostash;
85 int committer_date_is_author_date;
86 + int ignore_date;
87 char *cmd;
88 int allow_empty_message;
89 int rebase_merges, rebase_cousins;
@@ -117,6 +118,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
118 replay.reschedule_failed_exec = opts->reschedule_failed_exec;
119 replay.committer_date_is_author_date =
120 opts->committer_date_is_author_date;
121 + replay.ignore_date = opts->ignore_date;
122 replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
123 replay.strategy = opts->strategy;
124
@@ -981,6 +983,8 @@ static int run_am(struct rebase_options *opts)
983 argv_array_push(&am.args, "--ignore-whitespace");
984 if (opts->committer_date_is_author_date)
985 argv_array_push(&opts->git_am_opts, "--committer-date-is-author-date");
986 + if (opts->ignore_date)
987 + argv_array_push(&opts->git_am_opts, "--ignore-date");
988 if (opts->action && !strcmp("continue", opts->action)) {
989 argv_array_push(&am.args, "--resolved");
990 argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1432,8 +1436,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1436 OPT_BOOL(0, "committer-date-is-author-date",
1437 &options.committer_date_is_author_date,
1438 N_("make committer date match author date")),
1435 - OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
1436 - N_("passed to 'git am'"), PARSE_OPT_NOARG),
1439 + OPT_BOOL(0, "ignore-date", &options.ignore_date,
1440 + "ignore author date and use current date"),
1441 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
1442 N_("passed to 'git apply'"), 0),
1443 OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
@@ -1706,13 +1710,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1710 state_dir_base, cmd_live_rebase, buf.buf);
1711 }
1712
1709 - if (options.committer_date_is_author_date)
1713 + if (options.committer_date_is_author_date ||
1714 + options.ignore_date)
1715 options.flags |= REBASE_FORCE;
1716
1717 for (i = 0; i < options.git_am_opts.argc; i++) {
1718 const char *option = options.git_am_opts.argv[i], *p;
1714 - if (!strcmp(option, "--ignore-date") ||
1715 - !strcmp(option, "--whitespace=fix") ||
1719 + if (!strcmp(option, "--whitespace=fix") ||
1720 !strcmp(option, "--whitespace=strip"))
1721 options.flags |= REBASE_FORCE;
1722 else if (skip_prefix(option, "-C", &p)) {
sequencer.c
+57 -3
@@ -148,6 +148,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
148 */
149 static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
150 static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
151 +static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
152 static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
153 static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
154 static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -891,6 +892,36 @@ static char *read_author_date_or_null(void)
892 return date;
893 }
894
895 +/* Construct a free()able author string with current time as the author date */
896 +static char *ignore_author_date(const char *author)
897 +{
898 + int len = strlen(author);
899 + struct ident_split ident;
900 + struct strbuf new_author = STRBUF_INIT;
901 +
902 + if (split_ident_line(&ident, author, len) < 0) {
903 + error(_("malformed ident line"));
904 + return NULL;
905 + }
906 + len = ident.mail_end - ident.name_begin + 1;
907 +
908 + strbuf_addf(&new_author, "%.*s ", len, ident.name_begin);
909 + datestamp(&new_author);
910 + return strbuf_detach(&new_author, NULL);
911 +}
912 +
913 +static void push_dates(struct child_process *child, int change_committer_date)
914 +{
915 + time_t now = time(NULL);
916 + struct strbuf date = STRBUF_INIT;
917 +
918 + strbuf_addf(&date, "@%"PRIuMAX, (uintmax_t)now);
919 + argv_array_pushf(&child->env_array, "GIT_AUTHOR_DATE=%s", date.buf);
920 + if (change_committer_date)
921 + argv_array_pushf(&child->env_array, "GIT_COMMITTER_DATE=%s", date.buf);
922 + strbuf_release(&date);
923 +}
924 +
925 static const char staged_changes_advice[] =
926 N_("you have staged changes in your working tree\n"
927 "If these changes are meant to be squashed into the previous commit, run:\n"
@@ -959,7 +990,8 @@ static int run_git_commit(struct repository *r,
990 return -1;
991
992 strbuf_addf(&datebuf, "@%s", date);
962 - res = setenv("GIT_COMMITTER_DATE", datebuf.buf, 1);
993 + res = setenv("GIT_COMMITTER_DATE",
994 + opts->ignore_date ? "" : datebuf.buf, 1);
995
996 strbuf_release(&datebuf);
997 free(date);
@@ -983,6 +1015,8 @@ static int run_git_commit(struct repository *r,
1015 argv_array_push(&cmd.args, "--amend");
1016 if (opts->gpg_sign)
1017 argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
1018 + if (opts->ignore_date)
1019 + push_dates(&cmd, opts->committer_date_is_author_date);
1020 if (defmsg)
1021 argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
1022 else if (!(flags & EDIT_MSG))
@@ -1405,7 +1439,8 @@ static int try_to_commit(struct repository *r,
1439 strbuf_addf(&date, "@%.*s %.*s",
1440 (int)(ident.date_end - ident.date_begin), ident.date_begin,
1441 (int)(ident.tz_end - ident.tz_begin), ident.tz_begin);
1408 - res = setenv("GIT_COMMITTER_DATE", date.buf, 1);
1442 + res = setenv("GIT_COMMITTER_DATE",
1443 + opts->ignore_date ? "" : date.buf, 1);
1444 strbuf_release(&date);
1445
1446 if (res)
@@ -1455,6 +1490,15 @@ static int try_to_commit(struct repository *r,
1490
1491 reset_ident_date();
1492
1493 + if (opts->ignore_date) {
1494 + author = ignore_author_date(author);
1495 + if (!author) {
1496 + res = -1;
1497 + goto out;
1498 + }
1499 + free(author_to_free);
1500 + author_to_free = (char *)author;
1501 + }
1502 if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
1503 oid, author, opts->gpg_sign, extra)) {
1504 res = error(_("failed to write commit object"));
@@ -2538,6 +2582,11 @@ static int read_populate_opts(struct replay_opts *opts)
2582 opts->committer_date_is_author_date = 1;
2583 }
2584
2585 + if (file_exists(rebase_path_ignore_date())) {
2586 + opts->allow_ff = 0;
2587 + opts->ignore_date = 1;
2588 + }
2589 +
2590 if (file_exists(rebase_path_reschedule_failed_exec()))
2591 opts->reschedule_failed_exec = 1;
2592
@@ -2622,6 +2671,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
2671 write_file(rebase_path_signoff(), "--signoff\n");
2672 if (opts->committer_date_is_author_date)
2673 write_file(rebase_path_cdate_is_adate(), "%s", "");
2674 + if (opts->ignore_date)
2675 + write_file(rebase_path_ignore_date(), "%s", "");
2676 if (opts->reschedule_failed_exec)
2677 write_file(rebase_path_reschedule_failed_exec(), "%s", "");
2678
@@ -3439,6 +3490,8 @@ static int do_merge(struct repository *r,
3490 argv_array_push(&cmd.args, git_path_merge_msg(r));
3491 if (opts->gpg_sign)
3492 argv_array_push(&cmd.args, opts->gpg_sign);
3493 + if (opts->ignore_date)
3494 + push_dates(&cmd, opts->committer_date_is_author_date);
3495
3496 /* Add the tips to be merged */
3497 for (j = to_merge; j; j = j->next)
@@ -3711,7 +3764,8 @@ static int pick_commits(struct repository *r,
3764 if (opts->allow_ff)
3765 assert(!(opts->signoff || opts->no_commit ||
3766 opts->record_origin || opts->edit ||
3714 - opts->committer_date_is_author_date));
3767 + opts->committer_date_is_author_date ||
3768 + opts->ignore_date));
3769 if (read_and_refresh_cache(r, opts))
3770 return -1;
3771
sequencer.h
+1
@@ -44,6 +44,7 @@ struct replay_opts {
44 int quiet;
45 int reschedule_failed_exec;
46 int committer_date_is_author_date;
47 + int ignore_date;
48
49 int mainline;
50
t/t3433-rebase-options-compatibility.sh
+29
@@ -99,4 +99,33 @@ test_expect_success '--committer-date-is-author-date works with rebase -r' '
99 done <rev_list
100 '
101
102 +# Checking for +0000 in author time is enough since default
103 +# timezone is UTC, but the timezone used while committing
104 +# sets to +0530.
105 +test_expect_success '--ignore-date works with am backend' '
106 + git commit --amend --date="$GIT_AUTHOR_DATE" &&
107 + git rebase --ignore-date HEAD^ &&
108 + git show HEAD --pretty="format:%ai" >authortime &&
109 + grep "+0000" authortime
110 +'
111 +
112 +test_expect_success '--ignore-date works with interactive backend' '
113 + git commit --amend --date="$GIT_AUTHOR_DATE" &&
114 + git rebase --ignore-date -i HEAD^ &&
115 + git show HEAD --pretty="format:%ai" >authortime &&
116 + grep "+0000" authortime
117 +'
118 +
119 +test_expect_success '--ignore-date works with rebase -r' '
120 + git checkout side &&
121 + git merge --no-ff commit3 &&
122 + git rebase -r --root --ignore-date &&
123 + git rev-list HEAD >rev_list &&
124 + while read HASH
125 + do
126 + git show $HASH --pretty="format:%ai" >authortime
127 + grep "+0000" authortime
128 + done <rev_list
129 +'
130 +
131 test_done