Skip to content

Commit 2c733fb

Browse files
committed
parse_date(): '@' prefix forces git-timestamp
The only place that the issue this series addresses was observed where we read "cat-file commit" output and put it in GIT_AUTHOR_DATE in order to replay a commit with an ancient timestamp. With the previous patch alone, "git commit --date='20100917 +0900'" can be misinterpreted to mean an ancient timestamp, not September in year 2010. Guard this codepath by requring an extra '@' in front of the raw git timestamp on the parsing side. This of course needs to be compensated by updating get_author_ident_from_commit and the code for "git commit --amend" to prepend '@' to the string read from the existing commit in the GIT_AUTHOR_DATE environment variable. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 116eb3a commit 2c733fb

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

builtin/commit.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ static void determine_author_info(struct strbuf *author_ident)
534534

535535
if (author_message) {
536536
const char *a, *lb, *rb, *eol;
537+
size_t len;
537538

538539
a = strstr(author_message_buffer, "\nauthor ");
539540
if (!a)
@@ -554,6 +555,11 @@ static void determine_author_info(struct strbuf *author_ident)
554555
(a + strlen("\nauthor "))));
555556
email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
556557
date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
558+
len = eol - (rb + strlen("> "));
559+
date = xmalloc(len + 2);
560+
*date = '@';
561+
memcpy(date + 1, rb + strlen("> "), len);
562+
date[len + 1] = '\0';
557563
}
558564

559565
if (force_author) {

date.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,8 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
637637
*offset = -1;
638638
tm_gmt = 0;
639639

640-
if (!match_object_header_date(date, timestamp, offset))
640+
if (*date == '@' &&
641+
!match_object_header_date(date + 1, timestamp, offset))
641642
return 0; /* success */
642643
for (;;) {
643644
int match = 0;

git-sh-setup.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ get_author_ident_from_commit () {
200200
s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
201201
202202
g
203-
s/^author [^<]* <[^>]*> \(.*\)$/\1/
203+
s/^author [^<]* <[^>]*> \(.*\)$/@\1/
204204
s/.*/GIT_AUTHOR_DATE='\''&'\''/p
205205
206206
q

t/t3400-rebase.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,27 @@ test_expect_success 'rebase -m can copy notes' '
218218
test "a note" = "$(git notes show HEAD)"
219219
'
220220

221+
test_expect_success 'rebase commit with an ancient timestamp' '
222+
git reset --hard &&
223+
224+
>old.one && git add old.one && test_tick &&
225+
git commit --date="@12345 +0400" -m "Old one" &&
226+
>old.two && git add old.two && test_tick &&
227+
git commit --date="@23456 +0500" -m "Old two" &&
228+
>old.three && git add old.three && test_tick &&
229+
git commit --date="@34567 +0600" -m "Old three" &&
230+
231+
git cat-file commit HEAD^^ >actual &&
232+
grep "author .* 12345 +0400$" actual &&
233+
git cat-file commit HEAD^ >actual &&
234+
grep "author .* 23456 +0500$" actual &&
235+
git cat-file commit HEAD >actual &&
236+
grep "author .* 34567 +0600$" actual &&
237+
238+
git rebase --onto HEAD^^ HEAD^ &&
239+
240+
git cat-file commit HEAD >actual &&
241+
grep "author .* 34567 +0600$" actual
242+
'
243+
221244
test_done

0 commit comments

Comments
 (0)