Skip to content

Commit 4e021dc

Browse files
committed
Merge branch 'wh/author-committer-ident-config'
Four new configuration variables {author,committer}.{name,email} have been introduced to override user.{name,email} in more specific cases. * wh/author-committer-ident-config: config: allow giving separate author and committer idents
2 parents 42977bf + 39ab4d0 commit 4e021dc

File tree

10 files changed

+197
-24
lines changed

10 files changed

+197
-24
lines changed

Documentation/config/user.txt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
user.email::
2-
Your email address to be recorded in any newly created commits.
3-
Can be overridden by the `GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_EMAIL`, and
4-
`EMAIL` environment variables. See linkgit:git-commit-tree[1].
5-
61
user.name::
7-
Your full name to be recorded in any newly created commits.
8-
Can be overridden by the `GIT_AUTHOR_NAME` and `GIT_COMMITTER_NAME`
9-
environment variables. See linkgit:git-commit-tree[1].
2+
user.email::
3+
author.name::
4+
author.email::
5+
committer.name::
6+
committer.email::
7+
The `user.name` and `user.email` variables determine what ends
8+
up in the `author` and `committer` field of commit
9+
objects.
10+
If you need the `author` or `committer` to be different, the
11+
`author.name`, `author.email`, `committer.name` or
12+
`committer.email` variables can be set.
13+
Also, all of these can be overridden by the `GIT_AUTHOR_NAME`,
14+
`GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_NAME`,
15+
`GIT_COMMITTER_EMAIL` and `EMAIL` environment variables.
16+
See linkgit:git-commit-tree[1] for more information.
1017

1118
user.useConfigOnly::
1219
Instruct Git to avoid trying to guess defaults for `user.email`

blame.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ static struct commit *fake_working_tree_commit(struct repository *r,
204204

205205
origin = make_origin(commit, path);
206206

207-
ident = fmt_ident("Not Committed Yet", "not.committed.yet", NULL, 0);
207+
ident = fmt_ident("Not Committed Yet", "not.committed.yet",
208+
WANT_BLANK_IDENT, NULL, 0);
208209
strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n");
209210
for (parent = commit->parents; parent; parent = parent->next)
210211
strbuf_addf(&msg, "parent %s\n",

builtin/am.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,7 @@ static void do_commit(const struct am_state *state)
15791579
}
15801580

15811581
author = fmt_ident(state->author_name, state->author_email,
1582+
WANT_AUTHOR_IDENT,
15821583
state->ignore_date ? NULL : state->author_date,
15831584
IDENT_STRICT);
15841585

builtin/commit.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,8 @@ static void determine_author_info(struct strbuf *author_ident)
609609
set_ident_var(&date, strbuf_detach(&date_buf, NULL));
610610
}
611611

612-
strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
612+
strbuf_addstr(author_ident, fmt_ident(name, email, WANT_AUTHOR_IDENT, date,
613+
IDENT_STRICT));
613614
assert_split_ident(&author, author_ident);
614615
export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
615616
export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);

cache.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,10 +1506,19 @@ int date_overflows(timestamp_t date);
15061506
#define IDENT_STRICT 1
15071507
#define IDENT_NO_DATE 2
15081508
#define IDENT_NO_NAME 4
1509+
1510+
enum want_ident {
1511+
WANT_BLANK_IDENT,
1512+
WANT_AUTHOR_IDENT,
1513+
WANT_COMMITTER_IDENT
1514+
};
1515+
15091516
extern const char *git_author_info(int);
15101517
extern const char *git_committer_info(int);
1511-
extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
1512-
extern const char *fmt_name(const char *name, const char *email);
1518+
extern const char *fmt_ident(const char *name, const char *email,
1519+
enum want_ident whose_ident,
1520+
const char *date_str, int);
1521+
extern const char *fmt_name(enum want_ident);
15131522
extern const char *ident_default_name(void);
15141523
extern const char *ident_default_email(void);
15151524
extern const char *git_editor(void);

config.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,9 @@ int git_default_config(const char *var, const char *value, void *cb)
14451445
if (starts_with(var, "core."))
14461446
return git_default_core_config(var, value, cb);
14471447

1448-
if (starts_with(var, "user."))
1448+
if (starts_with(var, "user.") ||
1449+
starts_with(var, "author.") ||
1450+
starts_with(var, "committer."))
14491451
return git_ident_config(var, value, cb);
14501452

14511453
if (starts_with(var, "i18n."))

ident.c

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
static struct strbuf git_default_name = STRBUF_INIT;
1212
static struct strbuf git_default_email = STRBUF_INIT;
1313
static struct strbuf git_default_date = STRBUF_INIT;
14+
static struct strbuf git_author_name = STRBUF_INIT;
15+
static struct strbuf git_author_email = STRBUF_INIT;
16+
static struct strbuf git_committer_name = STRBUF_INIT;
17+
static struct strbuf git_committer_email = STRBUF_INIT;
1418
static int default_email_is_bogus;
1519
static int default_name_is_bogus;
1620

@@ -355,13 +359,19 @@ N_("\n"
355359
"\n");
356360

357361
const char *fmt_ident(const char *name, const char *email,
358-
const char *date_str, int flag)
362+
enum want_ident whose_ident, const char *date_str, int flag)
359363
{
360364
static struct strbuf ident = STRBUF_INIT;
361365
int strict = (flag & IDENT_STRICT);
362366
int want_date = !(flag & IDENT_NO_DATE);
363367
int want_name = !(flag & IDENT_NO_NAME);
364368

369+
if (!email) {
370+
if (whose_ident == WANT_AUTHOR_IDENT && git_author_email.len)
371+
email = git_author_email.buf;
372+
else if (whose_ident == WANT_COMMITTER_IDENT && git_committer_email.len)
373+
email = git_committer_email.buf;
374+
}
365375
if (!email) {
366376
if (strict && ident_use_config_only
367377
&& !(ident_config_given & IDENT_MAIL_GIVEN)) {
@@ -377,6 +387,13 @@ const char *fmt_ident(const char *name, const char *email,
377387

378388
if (want_name) {
379389
int using_default = 0;
390+
if (!name) {
391+
if (whose_ident == WANT_AUTHOR_IDENT && git_author_name.len)
392+
name = git_author_name.buf;
393+
else if (whose_ident == WANT_COMMITTER_IDENT &&
394+
git_committer_name.len)
395+
name = git_committer_name.buf;
396+
}
380397
if (!name) {
381398
if (strict && ident_use_config_only
382399
&& !(ident_config_given & IDENT_NAME_GIVEN)) {
@@ -425,9 +442,25 @@ const char *fmt_ident(const char *name, const char *email,
425442
return ident.buf;
426443
}
427444

428-
const char *fmt_name(const char *name, const char *email)
445+
const char *fmt_name(enum want_ident whose_ident)
429446
{
430-
return fmt_ident(name, email, NULL, IDENT_STRICT | IDENT_NO_DATE);
447+
char *name = NULL;
448+
char *email = NULL;
449+
450+
switch (whose_ident) {
451+
case WANT_BLANK_IDENT:
452+
break;
453+
case WANT_AUTHOR_IDENT:
454+
name = getenv("GIT_AUTHOR_NAME");
455+
email = getenv("GIT_AUTHOR_EMAIL");
456+
break;
457+
case WANT_COMMITTER_IDENT:
458+
name = getenv("GIT_COMMITTER_NAME");
459+
email = getenv("GIT_COMMITTER_EMAIL");
460+
break;
461+
}
462+
return fmt_ident(name, email, whose_ident, NULL,
463+
IDENT_STRICT | IDENT_NO_DATE);
431464
}
432465

433466
const char *git_author_info(int flag)
@@ -438,6 +471,7 @@ const char *git_author_info(int flag)
438471
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
439472
return fmt_ident(getenv("GIT_AUTHOR_NAME"),
440473
getenv("GIT_AUTHOR_EMAIL"),
474+
WANT_AUTHOR_IDENT,
441475
getenv("GIT_AUTHOR_DATE"),
442476
flag);
443477
}
@@ -450,6 +484,7 @@ const char *git_committer_info(int flag)
450484
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
451485
return fmt_ident(getenv("GIT_COMMITTER_NAME"),
452486
getenv("GIT_COMMITTER_EMAIL"),
487+
WANT_COMMITTER_IDENT,
453488
getenv("GIT_COMMITTER_DATE"),
454489
flag);
455490
}
@@ -473,10 +508,45 @@ int author_ident_sufficiently_given(void)
473508
return ident_is_sufficient(author_ident_explicitly_given);
474509
}
475510

476-
int git_ident_config(const char *var, const char *value, void *data)
511+
static int set_ident(const char *var, const char *value)
477512
{
478-
if (!strcmp(var, "user.useconfigonly")) {
479-
ident_use_config_only = git_config_bool(var, value);
513+
if (!strcmp(var, "author.name")) {
514+
if (!value)
515+
return config_error_nonbool(var);
516+
strbuf_reset(&git_author_name);
517+
strbuf_addstr(&git_author_name, value);
518+
author_ident_explicitly_given |= IDENT_NAME_GIVEN;
519+
ident_config_given |= IDENT_NAME_GIVEN;
520+
return 0;
521+
}
522+
523+
if (!strcmp(var, "author.email")) {
524+
if (!value)
525+
return config_error_nonbool(var);
526+
strbuf_reset(&git_author_email);
527+
strbuf_addstr(&git_author_email, value);
528+
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
529+
ident_config_given |= IDENT_MAIL_GIVEN;
530+
return 0;
531+
}
532+
533+
if (!strcmp(var, "committer.name")) {
534+
if (!value)
535+
return config_error_nonbool(var);
536+
strbuf_reset(&git_committer_name);
537+
strbuf_addstr(&git_committer_name, value);
538+
committer_ident_explicitly_given |= IDENT_NAME_GIVEN;
539+
ident_config_given |= IDENT_NAME_GIVEN;
540+
return 0;
541+
}
542+
543+
if (!strcmp(var, "committer.email")) {
544+
if (!value)
545+
return config_error_nonbool(var);
546+
strbuf_reset(&git_committer_email);
547+
strbuf_addstr(&git_committer_email, value);
548+
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
549+
ident_config_given |= IDENT_MAIL_GIVEN;
480550
return 0;
481551
}
482552

@@ -505,6 +575,16 @@ int git_ident_config(const char *var, const char *value, void *data)
505575
return 0;
506576
}
507577

578+
int git_ident_config(const char *var, const char *value, void *data)
579+
{
580+
if (!strcmp(var, "user.useconfigonly")) {
581+
ident_use_config_only = git_config_bool(var, value);
582+
return 0;
583+
}
584+
585+
return set_ident(var, value);
586+
}
587+
508588
static int buf_cmp(const char *a_begin, const char *a_end,
509589
const char *b_begin, const char *b_end)
510590
{

log-tree.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,7 @@ void show_log(struct rev_info *opt)
687687
*/
688688
if (ctx.need_8bit_cte >= 0 && opt->add_signoff)
689689
ctx.need_8bit_cte =
690-
has_non_ascii(fmt_name(getenv("GIT_COMMITTER_NAME"),
691-
getenv("GIT_COMMITTER_EMAIL")));
690+
has_non_ascii(fmt_name(WANT_COMMITTER_IDENT));
692691
ctx.date_mode = opt->date_mode;
693692
ctx.date_mode_explicit = opt->date_mode_explicit;
694693
ctx.abbrev = opt->diffopt.abbrev;

sequencer.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ static const char *read_author_ident(struct strbuf *buf)
837837
}
838838

839839
strbuf_reset(&out);
840-
strbuf_addstr(&out, fmt_ident(name, email, date, 0));
840+
strbuf_addstr(&out, fmt_ident(name, email, WANT_AUTHOR_IDENT, date, 0));
841841
strbuf_swap(buf, &out);
842842
strbuf_release(&out);
843843
free(name);
@@ -4098,8 +4098,7 @@ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
40984098
int has_footer;
40994099

41004100
strbuf_addstr(&sob, sign_off_header);
4101-
strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
4102-
getenv("GIT_COMMITTER_EMAIL")));
4101+
strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
41034102
strbuf_addch(&sob, '\n');
41044103

41054104
if (!ignore_footer)

t/t7517-per-repo-email.sh

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,78 @@ test_expect_success REBASE_P \
8585
test_must_fail git rebase -p master
8686
'
8787

88+
test_expect_success 'author.name overrides user.name' '
89+
test_config user.name user &&
90+
test_config user.email [email protected] &&
91+
test_config author.name author &&
92+
test_commit author-name-override-user &&
93+
echo author [email protected] > expected-author &&
94+
echo user [email protected] > expected-committer &&
95+
git log --format="%an %ae" -1 > actual-author &&
96+
git log --format="%cn %ce" -1 > actual-committer &&
97+
test_cmp expected-author actual-author &&
98+
test_cmp expected-committer actual-committer
99+
'
100+
101+
test_expect_success 'author.email overrides user.email' '
102+
test_config user.name user &&
103+
test_config user.email [email protected] &&
104+
test_config author.email [email protected] &&
105+
test_commit author-email-override-user &&
106+
echo user [email protected] > expected-author &&
107+
echo user [email protected] > expected-committer &&
108+
git log --format="%an %ae" -1 > actual-author &&
109+
git log --format="%cn %ce" -1 > actual-committer &&
110+
test_cmp expected-author actual-author &&
111+
test_cmp expected-committer actual-committer
112+
'
113+
114+
test_expect_success 'committer.name overrides user.name' '
115+
test_config user.name user &&
116+
test_config user.email [email protected] &&
117+
test_config committer.name committer &&
118+
test_commit committer-name-override-user &&
119+
echo user [email protected] > expected-author &&
120+
echo committer [email protected] > expected-committer &&
121+
git log --format="%an %ae" -1 > actual-author &&
122+
git log --format="%cn %ce" -1 > actual-committer &&
123+
test_cmp expected-author actual-author &&
124+
test_cmp expected-committer actual-committer
125+
'
126+
127+
test_expect_success 'committer.email overrides user.email' '
128+
test_config user.name user &&
129+
test_config user.email [email protected] &&
130+
test_config committer.email [email protected] &&
131+
test_commit committer-email-override-user &&
132+
echo user [email protected] > expected-author &&
133+
echo user [email protected] > expected-committer &&
134+
git log --format="%an %ae" -1 > actual-author &&
135+
git log --format="%cn %ce" -1 > actual-committer &&
136+
test_cmp expected-author actual-author &&
137+
test_cmp expected-committer actual-committer
138+
'
139+
140+
test_expect_success 'author and committer environment variables override config settings' '
141+
test_config user.name user &&
142+
test_config user.email [email protected] &&
143+
test_config author.name author &&
144+
test_config author.email [email protected] &&
145+
test_config committer.name committer &&
146+
test_config committer.email [email protected] &&
147+
GIT_AUTHOR_NAME=env_author && export GIT_AUTHOR_NAME &&
148+
[email protected] && export GIT_AUTHOR_EMAIL &&
149+
GIT_COMMITTER_NAME=env_commit && export GIT_COMMITTER_NAME &&
150+
[email protected] && export GIT_COMMITTER_EMAIL &&
151+
test_commit env-override-conf &&
152+
echo env_author [email protected] > expected-author &&
153+
echo env_commit [email protected] > expected-committer &&
154+
git log --format="%an %ae" -1 > actual-author &&
155+
git log --format="%cn %ce" -1 > actual-committer &&
156+
sane_unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
157+
sane_unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL &&
158+
test_cmp expected-author actual-author &&
159+
test_cmp expected-committer actual-committer
160+
'
161+
88162
test_done

0 commit comments

Comments
 (0)