Skip to content

Commit c51f6ce

Browse files
erickmattosgitster
authored andcommitted
commit -c/-C/--amend: reset timestamp and authorship to committer with --reset-author
When we use -c, -C, or --amend, we are trying one of two things: using the source as a template or modifying a commit with corrections. When these options are used, the authorship and timestamp recorded in the newly created commit are always taken from the original commit. This is inconvenient when we just want to borrow the commit log message or when our change to the code is so significant that we should take over the authorship (with the blame for bugs we introduce, of course). The new --reset-author option is meant to solve this need by regenerating the timestamp and setting the committer as the new author. Signed-off-by: Erick Mattos <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent c8a58ac commit c51f6ce

File tree

3 files changed

+129
-4
lines changed

3 files changed

+129
-4
lines changed

Documentation/git-commit.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ SYNOPSIS
99
--------
1010
[verse]
1111
'git commit' [-a | --interactive] [-s] [-v] [-u<mode>] [--amend] [--dry-run]
12-
[(-c | -C) <commit>] [-F <file> | -m <msg>]
12+
[(-c | -C) <commit>] [-F <file> | -m <msg>] [--reset-author]
1313
[--allow-empty] [--no-verify] [-e] [--author=<author>]
1414
[--cleanup=<mode>] [--] [[-i | -o ]<file>...]
1515

@@ -69,6 +69,11 @@ OPTIONS
6969
Like '-C', but with '-c' the editor is invoked, so that
7070
the user can further edit the commit message.
7171

72+
--reset-author::
73+
When used with -C/-c/--amend options, declare that the
74+
authorship of the resulting commit now belongs of the committer.
75+
This also renews the author timestamp.
76+
7277
-F <file>::
7378
--file=<file>::
7479
Take the commit message from the given file. Use '-' to

builtin-commit.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static const char *template_file;
5151
static char *edit_message, *use_message;
5252
static char *author_name, *author_email, *author_date;
5353
static int all, edit_flag, also, interactive, only, amend, signoff;
54-
static int quiet, verbose, no_verify, allow_empty, dry_run;
54+
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
5555
static char *untracked_files_arg;
5656
/*
5757
* The default commit message cleanup mode will remove the lines
@@ -91,8 +91,9 @@ static struct option builtin_commit_options[] = {
9191
OPT_FILENAME('F', "file", &logfile, "read log from file"),
9292
OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
9393
OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
94-
OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit "),
94+
OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"),
9595
OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
96+
OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
9697
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
9798
OPT_FILENAME('t', "template", &template_file, "use specified template file"),
9899
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
@@ -381,7 +382,7 @@ static void determine_author_info(void)
381382
email = getenv("GIT_AUTHOR_EMAIL");
382383
date = getenv("GIT_AUTHOR_DATE");
383384

384-
if (use_message) {
385+
if (use_message && !renew_authorship) {
385386
const char *a, *lb, *rb, *eol;
386387

387388
a = strstr(use_message_buffer, "\nauthor ");
@@ -747,6 +748,9 @@ static int parse_and_validate_options(int argc, const char *argv[],
747748
if (force_author && !strchr(force_author, '>'))
748749
force_author = find_author_by_nickname(force_author);
749750

751+
if (force_author && renew_authorship)
752+
die("Using both --reset-author and --author does not make sense");
753+
750754
if (logfile || message.len || use_message)
751755
use_editor = 0;
752756
if (edit_flag)
@@ -780,6 +784,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
780784
use_message = edit_message;
781785
if (amend && !use_message)
782786
use_message = "HEAD";
787+
if (!use_message && renew_authorship)
788+
die("--reset-author can be used only with -C, -c or --amend.");
783789
if (use_message) {
784790
unsigned char sha1[20];
785791
static char utf8[] = "UTF-8";

t/t7509-commit.sh

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2009 Erick Mattos
4+
#
5+
6+
test_description='git commit --reset-author'
7+
8+
. ./test-lib.sh
9+
10+
author_header () {
11+
git cat-file commit "$1" |
12+
sed -n -e '/^$/q' -e '/^author /p'
13+
}
14+
15+
message_body () {
16+
git cat-file commit "$1" |
17+
sed -e '1,/^$/d'
18+
}
19+
20+
test_expect_success '-C option copies authorship and message' '
21+
echo "Initial" >foo &&
22+
git add foo &&
23+
test_tick &&
24+
git commit -m "Initial Commit" --author Frigate\ \<[email protected]\> &&
25+
git tag Initial &&
26+
echo "Test 1" >>foo &&
27+
test_tick &&
28+
git commit -a -C Initial &&
29+
author_header Initial >expect &&
30+
author_header HEAD >actual &&
31+
test_cmp expect actual &&
32+
33+
message_body Initial >expect &&
34+
message_body HEAD >actual &&
35+
test_cmp expect actual
36+
'
37+
38+
test_expect_success '-C option copies only the message with --reset-author' '
39+
echo "Test 2" >>foo &&
40+
test_tick &&
41+
git commit -a -C Initial --reset-author &&
42+
echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
43+
author_header HEAD >actual
44+
test_cmp expect actual &&
45+
46+
message_body Initial >expect &&
47+
message_body HEAD >actual &&
48+
test_cmp expect actual
49+
'
50+
51+
test_expect_success '-c option copies authorship and message' '
52+
echo "Test 3" >>foo &&
53+
test_tick &&
54+
EDITOR=: VISUAL=: git commit -a -c Initial &&
55+
author_header Initial >expect &&
56+
author_header HEAD >actual &&
57+
test_cmp expect actual
58+
'
59+
60+
test_expect_success '-c option copies only the message with --reset-author' '
61+
echo "Test 4" >>foo &&
62+
test_tick &&
63+
EDITOR=: VISUAL=: git commit -a -c Initial --reset-author &&
64+
echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
65+
author_header HEAD >actual &&
66+
test_cmp expect actual &&
67+
68+
message_body Initial >expect &&
69+
message_body HEAD >actual &&
70+
test_cmp expect actual
71+
'
72+
73+
test_expect_success '--amend option copies authorship' '
74+
git checkout Initial &&
75+
echo "Test 5" >>foo &&
76+
test_tick &&
77+
git commit -a --amend -m "amend test" &&
78+
author_header Initial >expect &&
79+
author_header HEAD >actual &&
80+
81+
echo "amend test" >expect &&
82+
message_body HEAD >actual &&
83+
test_cmp expect actual
84+
'
85+
86+
test_expect_success '--reset-author makes the commit ours even with --amend option' '
87+
git checkout Initial &&
88+
echo "Test 6" >>foo &&
89+
test_tick &&
90+
git commit -a --reset-author -m "Changed again" --amend &&
91+
echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
92+
author_header HEAD >actual &&
93+
test_cmp expect actual &&
94+
95+
echo "Changed again" >expect &&
96+
message_body HEAD >actual &&
97+
test_cmp expect actual
98+
'
99+
100+
test_expect_success '--reset-author and --author are mutually exclusive' '
101+
git checkout Initial &&
102+
echo "Test 7" >>foo &&
103+
test_tick &&
104+
test_must_fail git commit -a --reset-author --author="Xyzzy <[email protected]>"
105+
'
106+
107+
test_expect_success '--reset-author should be rejected without -c/-C/--amend' '
108+
git checkout Initial &&
109+
echo "Test 7" >>foo &&
110+
test_tick &&
111+
test_must_fail git commit -a --reset-author -m done
112+
'
113+
114+
test_done

0 commit comments

Comments
 (0)