Skip to content

Commit a3894aa

Browse files
phillipwoodgitster
authored andcommitted
rebase -i: support --ignore-date
Rebase is implemented with two different backends - 'apply' and 'merge' each of which support a different set of options. In particular the apply backend supports a number of options implemented by 'git am' that are not implemented in the merge backend. This means that the available options are different depending on which backend is used which is confusing. This patch adds support for the --ignore-date option to the merge backend. This option uses the current time as the author date rather than reusing the original author date when rewriting commits. We take care to handle the combination of --ignore-date and --committer-date-is-author-date in the same way as the apply backend. Original-patch-by: Rohit Ashiwal <[email protected]> Signed-off-by: Phillip Wood <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7573cec commit a3894aa

File tree

5 files changed

+123
-20
lines changed

5 files changed

+123
-20
lines changed

Documentation/git-rebase.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,9 @@ See also INCOMPATIBLE OPTIONS below.
450450
date. This option implies `--force-rebase`.
451451

452452
--ignore-date::
453-
This flag is passed to 'git am' to change the author date
454-
of each rebased commit (see linkgit:git-am[1]).
453+
Instead of using the author date of the original commit, use
454+
the current time as the author date of the rebased commit. This
455+
option implies `--force-rebase`.
455456
+
456457
See also INCOMPATIBLE OPTIONS below.
457458

@@ -589,7 +590,6 @@ INCOMPATIBLE OPTIONS
589590
The following options:
590591

591592
* --apply
592-
* --ignore-date
593593
* --whitespace
594594
* -C
595595

@@ -617,6 +617,7 @@ In addition, the following pairs of options are incompatible:
617617
* --preserve-merges and --empty=
618618
* --preserve-merges and --ignore-whitespace
619619
* --preserve-merges and --committer-date-is-author-date
620+
* --preserve-merges and --ignore-date
620621
* --keep-base and --onto
621622
* --keep-base and --root
622623

builtin/rebase.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct rebase_options {
8989
char *gpg_sign_opt;
9090
int autostash;
9191
int committer_date_is_author_date;
92+
int ignore_date;
9293
char *cmd;
9394
int allow_empty_message;
9495
int rebase_merges, rebase_cousins;
@@ -127,6 +128,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
127128
replay.reschedule_failed_exec = opts->reschedule_failed_exec;
128129
replay.committer_date_is_author_date =
129130
opts->committer_date_is_author_date;
131+
replay.ignore_date = opts->ignore_date;
130132
replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
131133
replay.strategy = opts->strategy;
132134

@@ -1503,8 +1505,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
15031505
OPT_BOOL(0, "committer-date-is-author-date",
15041506
&options.committer_date_is_author_date,
15051507
N_("make committer date match author date")),
1506-
OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
1507-
N_("passed to 'git am'"), PARSE_OPT_NOARG),
1508+
OPT_BOOL(0, "ignore-date", &options.ignore_date,
1509+
N_("ignore author date and use current date")),
15081510
OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
15091511
N_("passed to 'git apply'"), 0),
15101512
OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
@@ -1797,13 +1799,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
17971799
options.autosquash) {
17981800
allow_preemptive_ff = 0;
17991801
}
1800-
if (options.committer_date_is_author_date)
1802+
if (options.committer_date_is_author_date || options.ignore_date)
18011803
options.flags |= REBASE_FORCE;
18021804

18031805
for (i = 0; i < options.git_am_opts.argc; i++) {
18041806
const char *option = options.git_am_opts.argv[i], *p;
1805-
if (!strcmp(option, "--ignore-date") ||
1806-
!strcmp(option, "--whitespace=fix") ||
1807+
if (!strcmp(option, "--whitespace=fix") ||
18071808
!strcmp(option, "--whitespace=strip"))
18081809
allow_preemptive_ff = 0;
18091810
else if (skip_prefix(option, "-C", &p)) {
@@ -1862,6 +1863,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
18621863
if (options.committer_date_is_author_date)
18631864
argv_array_push(&options.git_am_opts,
18641865
"--committer-date-is-author-date");
1866+
if (options.ignore_date)
1867+
argv_array_push(&options.git_am_opts, "--ignore-date");
18651868
} else {
18661869
/* REBASE_MERGE and PRESERVE_MERGES */
18671870
if (ignore_whitespace) {

sequencer.c

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
150150
*/
151151
static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
152152
static GIT_PATH_FUNC(rebase_path_cdate_is_adate, "rebase-merge/cdate_is_adate")
153+
static GIT_PATH_FUNC(rebase_path_ignore_date, "rebase-merge/ignore_date")
153154
static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
154155
static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
155156
static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
@@ -959,7 +960,11 @@ static int run_git_commit(struct repository *r,
959960

960961
if (opts->committer_date_is_author_date)
961962
argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
963+
opts->ignore_date ?
964+
"" :
962965
author_date_from_env_array(&cmd.env_array));
966+
if (opts->ignore_date)
967+
argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
963968

964969
argv_array_push(&cmd.args, "commit");
965970

@@ -1434,26 +1439,51 @@ static int try_to_commit(struct repository *r,
14341439
struct ident_split id;
14351440
struct strbuf date = STRBUF_INIT;
14361441

1437-
if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
1438-
res = error(_("invalid author identity '%s'"), author);
1439-
goto out;
1440-
}
1441-
if (!id.date_begin) {
1442-
res = error(_("corrupt author: missing date information"));
1443-
goto out;
1442+
if (!opts->ignore_date) {
1443+
if (split_ident_line(&id, author, (int)strlen(author)) < 0) {
1444+
res = error(_("invalid author identity '%s'"),
1445+
author);
1446+
goto out;
1447+
}
1448+
if (!id.date_begin) {
1449+
res = error(_(
1450+
"corrupt author: missing date information"));
1451+
goto out;
1452+
}
1453+
strbuf_addf(&date, "@%.*s %.*s",
1454+
(int)(id.date_end - id.date_begin),
1455+
id.date_begin,
1456+
(int)(id.tz_end - id.tz_begin),
1457+
id.tz_begin);
1458+
} else {
1459+
reset_ident_date();
14441460
}
1445-
strbuf_addf(&date, "@%.*s %.*s",
1446-
(int)(id.date_end - id.date_begin), id.date_begin,
1447-
(int)(id.tz_end - id.tz_begin), id.tz_begin);
14481461
committer = fmt_ident(opts->committer_name,
14491462
opts->committer_email,
1450-
WANT_COMMITTER_IDENT, date.buf,
1463+
WANT_COMMITTER_IDENT,
1464+
opts->ignore_date ? NULL : date.buf,
14511465
IDENT_STRICT);
14521466
strbuf_release(&date);
14531467
} else {
14541468
reset_ident_date();
14551469
}
14561470

1471+
if (opts->ignore_date) {
1472+
struct ident_split id;
1473+
char *name, *email;
1474+
1475+
if (split_ident_line(&id, author, strlen(author)) < 0) {
1476+
error(_("invalid author identity '%s'"), author);
1477+
goto out;
1478+
}
1479+
name = xmemdupz(id.name_begin, id.name_end - id.name_begin);
1480+
email = xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
1481+
author = fmt_ident(name, email, WANT_AUTHOR_IDENT, NULL,
1482+
IDENT_STRICT);
1483+
free(name);
1484+
free(email);
1485+
}
1486+
14571487
if (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,
14581488
author, committer, opts->gpg_sign, extra)) {
14591489
res = error(_("failed to write commit object"));
@@ -2583,6 +2613,11 @@ static int read_populate_opts(struct replay_opts *opts)
25832613
opts->committer_date_is_author_date = 1;
25842614
}
25852615

2616+
if (file_exists(rebase_path_ignore_date())) {
2617+
opts->allow_ff = 0;
2618+
opts->ignore_date = 1;
2619+
}
2620+
25862621
if (file_exists(rebase_path_reschedule_failed_exec()))
25872622
opts->reschedule_failed_exec = 1;
25882623

@@ -2675,6 +2710,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
26752710
write_file(rebase_path_keep_redundant_commits(), "%s", "");
26762711
if (opts->committer_date_is_author_date)
26772712
write_file(rebase_path_cdate_is_adate(), "%s", "");
2713+
if (opts->ignore_date)
2714+
write_file(rebase_path_ignore_date(), "%s", "");
26782715
if (opts->reschedule_failed_exec)
26792716
write_file(rebase_path_reschedule_failed_exec(), "%s", "");
26802717

@@ -3597,7 +3634,11 @@ static int do_merge(struct repository *r,
35973634

35983635
if (opts->committer_date_is_author_date)
35993636
argv_array_pushf(&cmd.env_array, "GIT_COMMITTER_DATE=%s",
3637+
opts->ignore_date ?
3638+
"" :
36003639
author_date_from_env_array(&cmd.env_array));
3640+
if (opts->ignore_date)
3641+
argv_array_push(&cmd.env_array, "GIT_AUTHOR_DATE=");
36013642

36023643
cmd.git_cmd = 1;
36033644
argv_array_push(&cmd.args, "merge");
@@ -3877,7 +3918,8 @@ static int pick_commits(struct repository *r,
38773918
if (opts->allow_ff)
38783919
assert(!(opts->signoff || opts->no_commit ||
38793920
opts->record_origin || opts->edit ||
3880-
opts->committer_date_is_author_date));
3921+
opts->committer_date_is_author_date ||
3922+
opts->ignore_date));
38813923
if (read_and_refresh_cache(r, opts))
38823924
return -1;
38833925

sequencer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct replay_opts {
4646
int quiet;
4747
int reschedule_failed_exec;
4848
int committer_date_is_author_date;
49+
int ignore_date;
4950

5051
int mainline;
5152

t/t3436-rebase-more-options.sh

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,62 @@ test_expect_success '--committer-date-is-author-date works when committing confl
108108
test_ctime_is_atime -1
109109
'
110110

111+
# Checking for +0000 in the author date is sufficient since the
112+
# default timezone is UTC but the timezone used while committing is
113+
# +0530. The inverted logic in the grep is necessary to check all the
114+
# author dates in the file.
115+
test_atime_is_ignored () {
116+
git log $1 --format=%ai >authortime &&
117+
! grep -v +0000 authortime
118+
}
119+
120+
test_expect_success '--ignore-date works with apply backend' '
121+
git commit --amend --date="$GIT_AUTHOR_DATE" &&
122+
git rebase --apply --ignore-date HEAD^ &&
123+
test_atime_is_ignored -1
124+
'
125+
126+
test_expect_success '--ignore-date works with merge backend' '
127+
git commit --amend --date="$GIT_AUTHOR_DATE" &&
128+
git rebase --ignore-date -m HEAD^ &&
129+
test_atime_is_ignored -1
130+
'
131+
132+
test_expect_success '--ignore-date works after conflict resolution' '
133+
test_must_fail git rebase --ignore-date -m \
134+
--onto commit2^^ commit2^ commit2 &&
135+
echo resolved >foo &&
136+
git add foo &&
137+
git rebase --continue &&
138+
test_atime_is_ignored -1
139+
'
140+
141+
test_expect_success '--ignore-date works with rebase -r' '
142+
git checkout side &&
143+
git merge --no-ff commit3 &&
144+
git rebase -r --root --ignore-date &&
145+
test_atime_is_ignored
146+
'
147+
148+
test_expect_success '--ignore-date with --committer-date-is-author-date works' '
149+
test_must_fail git rebase -m --committer-date-is-author-date \
150+
--ignore-date --onto commit2^^ commit2^ commit3 &&
151+
git checkout --theirs foo &&
152+
git add foo &&
153+
git rebase --continue &&
154+
test_ctime_is_atime -2 &&
155+
test_atime_is_ignored -2
156+
'
157+
158+
test_expect_success '--ignore-date --committer-date-is-author-date works when forking merge' '
159+
GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
160+
PATH="./test-bin:$PATH" git rebase -i --strategy=test \
161+
--ignore-date --committer-date-is-author-date \
162+
side side &&
163+
test_ctime_is_atime -1 &&
164+
test_atime_is_ignored -1
165+
'
166+
111167
# This must be the last test in this file
112168
test_expect_success '$EDITOR and friends are unchanged' '
113169
test_editor_unchanged

0 commit comments

Comments
 (0)