Skip to contentSkip to conversation

Extend mailmap functionality

PATCH In review Marius Storm-Olsen 1 participant 7 messages Jun 15, 2016 Documentation

lore
Share & tools
lore
#0 lore raw

v5 cover Extend mailmap functionality

v5:
---
* Rename log.mailmap variable to mailmap.file
* Fix mailmap tests using shortlog, by adding HEAD
* Factor out the mailmap documentation, and include it from both git-shortlog.txt and git-blame.txt, since they both use mailmap directly. Link to these from pretty-format.txt, for all commands using the pretty option.
v4:
---
* Refactored out name and email parsing into separate function
* Added support for only email replacement (<new> <old> construct)
* Added "static" to functions local to compile unit only
* Fixed C++ style comment to bash style comment in commit message
* Added more air in the commit messages
* Rebased ontop of latest master
v3:
---
* Make log.mailmap augment repo "/.mailmap" rather than override
* Remove second argument of read_mailmap(<map>, <file>, <abbrev>);
* Wrap commit messages within column 70
v2:
---
* Folded in documentation fixup from patch 4 into patch 3.

This patch series extends the mailmap functionality to:
1) Allow the mailmap file in any location (also outside repo)
2) Enable mailmap to match on both Name and Email

So, why would this be a good thing?

2) Lets you replace both name and email of an author/committer, based on a name and/or email, _and_ replace email only, based on old email. So, should you have done commits with faulty address, or if an old email simply isn't valid anymore, you can add a mapping for that to replace it. So, the old style mapping is
Proper Name <[email protected]>

while this patch series adds support for
<[email protected]> <[email protected]>
Proper Name <[email protected]> <[email protected]> Proper Name <[email protected]> Commit Name <[email protected]>

1) Lets you keep a private mailmap file, which is not distributed with your repository.

This extended mapping is necessary when a company wants to have their repositories open to the public, but needs to protect the identities of the developers. It enables you to only show nicks and standardized emails, like 'Dev123 <[email protected]>' in the public repo, but by using an private mailmap file, map the name back to
'John Doe <[email protected]>' inside the company.

Patch serie applies cleanly on master branch (88ccb9f9), and test run shows no regressions.

Marius Storm-Olsen (5):
Add mailmap.file as configurational option for mailmap location Add find_insert_index, insert_at_index and clear_func functions to
string_list
Add map_user() and clear_mailmap() to mailmap
Change current mailmap usage to do matching on both name and email of
author/committer.
Move mailmap documentation into separate file

 Documentation/config.txt         |    8 ++
 Documentation/git-blame.txt      |    6 +
 Documentation/git-shortlog.txt   |   49 ++-------
 Documentation/mailmap.txt        |   75 +++++++++++++
 Documentation/pretty-formats.txt |    6 +-
 builtin-blame.c                  |   52 ++++++----
 builtin-shortlog.c               |   25 ++++-
 cache.h                          |    1 +
 config.c                         |   12 ++
 mailmap.c                        |  208 +++++++++++++++++++++++++++++++------
 mailmap.h                        |    6 +-
 pretty.c                         |   59 ++++++-----
 string-list.c                    |   43 +++++++-
 string-list.h                    |    9 ++
 t/t4203-mailmap.sh               |  215 ++++++++++++++++++++++++++++++++++++++
 15 files changed, 644 insertions(+), 130 deletions(-)
 create mode 100644 Documentation/mailmap.txt
 create mode 100755 t/t4203-mailmap.sh
#1 lore raw

PATCH v5 1/5 Add mailmap.file as configurational option for mailmap location

This allows us to augment the repo mailmap file, and to use mailmap files elsewhere than the repository root. Meaning that the entries in mailmap.file will override the entries in "./.mailmap", should they match.

---
 Documentation/config.txt       |    8 +++
 Documentation/git-shortlog.txt |    3 +-
 builtin-blame.c                |    2 +-
 builtin-shortlog.c             |    3 +-
 cache.h                        |    1 +
 config.c                       |   12 ++++
 mailmap.c                      |   12 ++++-
 mailmap.h                      |    2 +-
 pretty.c                       |    2 +-
 t/t4203-mailmap.sh             |  109 ++++++++++++++++++++++++++++++++++++++++
 10 files changed, 147 insertions(+), 7 deletions(-)
 create mode 100755 t/t4203-mailmap.sh
Documentation/config.txt +8 -0
index 1dd18c9..3117d65 100644
@@ -1032,6 +1032,14 @@ log.showroot::
 	Tools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which
 	normally hide the root commit will now show it. True by default.
 
+mailmap.file::
+	The location of an augmenting mailmap file. The default
+	mailmap, located in the root of the repository, is loaded
+	first, then the mailmap file pointed to by this variable.
+	The location of the mailmap file may be in a repository
+	subdirectory, or somewhere outside of the repository itself.
+	See linkgit:git-shortlog[1] and linkgit:git-blame[1].
+
 man.viewer::
 	Specify the programs that may be used to display help in the
 	'man' format. See linkgit:git-help[1].
Documentation/git-shortlog.txt +2 -1
index 498bd28..66b6045 100644
@@ -48,7 +48,8 @@ OPTIONS
 FILES
 -----
 
-If a file `.mailmap` exists at the toplevel of the repository,
+If a file `.mailmap` exists at the toplevel of the repository, or at the
+location pointed to by the log.mailmap configuration option,
 it is used to map an author email address to a canonical real name. This
 can be used to coalesce together commits by the same person where their
 name was spelled differently (whether with the same email address or
builtin-blame.c +1 -1
index 9b9f544..9cfa090 100644
@@ -2396,7 +2396,7 @@ parse_done:
 		die("reading graft file %s failed: %s",
 		    revs_file, strerror(errno));
 
-	read_mailmap(&mailmap, ".mailmap", NULL);
+	read_mailmap(&mailmap, NULL);
 
 	if (!incremental)
 		setup_pager();
builtin-shortlog.c +2 -1
index 5f9f3f0..314b6bc 100644
@@ -219,7 +219,7 @@ void shortlog_init(struct shortlog *log)
 {
 	memset(log, 0, sizeof(*log));
 
-	read_mailmap(&log->mailmap, ".mailmap", &log->common_repo_prefix);
+	read_mailmap(&log->mailmap, &log->common_repo_prefix);
 
 	log->list.strdup_strings = 1;
 	log->wrap = DEFAULT_WRAPLEN;
@@ -248,6 +248,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
 	struct parse_opt_ctx_t ctx;
 
 	prefix = setup_git_directory_gently(&nongit);
+	git_config(git_default_config, NULL);
 	shortlog_init(&log);
 	init_revisions(&rev, prefix);
 	parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
cache.h +1 -0
index 2d889de..87d9d8e 100644
@@ -870,6 +870,7 @@ extern int user_ident_explicitly_given;
 
 extern const char *git_commit_encoding;
 extern const char *git_log_output_encoding;
+extern const char *git_mailmap_file;
 
 /* IO helper functions */
 extern void maybe_flush_or_die(FILE *, const char *);
config.c +12 -0
index e5d5b4b..7dc1b0f 100644
@@ -570,6 +570,15 @@ static int git_default_branch_config(const char *var, const char *value)
 	return 0;
 }
 
+static int git_default_mailmap_config(const char *var, const char *value)
+{
+	if (!strcmp(var, "mailmap.file"))
+		return git_config_string(&git_mailmap_file, var, value);
+
+	/* Add other config variables here and to Documentation/config.txt. */
+	return 0;
+}
+
 int git_default_config(const char *var, const char *value, void *dummy)
 {
 	if (!prefixcmp(var, "core."))
@@ -584,6 +593,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
 	if (!prefixcmp(var, "branch."))
 		return git_default_branch_config(var, value);
 
+	if (!prefixcmp(var, "mailmap."))
+		return git_default_mailmap_config(var, value);
+
 	if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
 		pager_use_color = git_config_bool(var,value);
 		return 0;
mailmap.c +10 -2
index 88fc6f3..d006dad 100644
@@ -2,10 +2,11 @@
 #include "string-list.h"
 #include "mailmap.h"
 
-int read_mailmap(struct string_list *map, const char *filename, char **repo_abbrev)
+const char *git_mailmap_file;
+static int read_single_mailmap(struct string_list *map, const char *filename, char **repo_abbrev)
 {
 	char buffer[1024];
-	FILE *f = fopen(filename, "r");
+	FILE *f = (filename == NULL ? NULL : fopen(filename, "r"));
 
 	if (f == NULL)
 		return 1;
@@ -60,6 +61,13 @@ int read_mailmap(struct string_list *map, const char *filename, char **repo_abbr
 	return 0;
 }
 
+int read_mailmap(struct string_list *map, char **repo_abbrev)
+{
+	/* each failure returns 1, so >1 means both calls failed */
+	return read_single_mailmap(map, ".mailmap", repo_abbrev) +
+	       read_single_mailmap(map, git_mailmap_file, repo_abbrev) > 1;
+}
+
 int map_email(struct string_list *map, const char *email, char *name, int maxlen)
 {
 	char *p;
mailmap.h +1 -1
index 6e48f83..ba2ee76 100644
@@ -1,7 +1,7 @@
 #ifndef MAILMAP_H
 #define MAILMAP_H
 
-int read_mailmap(struct string_list *map, const char *filename, char **repo_abbrev);
+int read_mailmap(struct string_list *map, char **repo_abbrev);
 int map_email(struct string_list *mailmap, const char *email, char *name, int maxlen);
 
 #endif
pretty.c +1 -1
index 8d4dbc9..cecd9fc 100644
@@ -313,7 +313,7 @@ static int mailmap_name(struct strbuf *sb, const char *email)
 
 	if (!mail_map) {
 		mail_map = xcalloc(1, sizeof(*mail_map));
-		read_mailmap(mail_map, ".mailmap", NULL);
+		read_mailmap(mail_map, NULL);
 	}
 
 	if (!mail_map->nr)
t/t4203-mailmap.sh new file +109 -0

109 lines not on this page · raw message

Signature · 1 line
1.6.1.2.354.g9a90
#2 lore raw

PATCH v5 2/5 Add find_insert_index, insert_at_index and clear_func functions to string_list

string_list_find_insert_index() and string_list_insert_at_index() enables you to see if an item is in the string_list, and to insert at the appropriate index in the list, if not there. This is usefull if you need to manipulate an existing item, if present, and insert a new item if not.

Future mailmap code will use this construct to enable complex (old_name, old_email) -> (new_name, new_email) lookups.

The string_list_clear_func() allows to call a custom cleanup function on each item in a string_list, which is useful is the util member points to a complex structure.

---
 string-list.c |   43 +++++++++++++++++++++++++++++++++++++++----
 string-list.h |    9 +++++++++
 2 files changed, 48 insertions(+), 4 deletions(-)
string-list.c +39 -4
index ddd83c8..15e14cf 100644
@@ -26,10 +26,10 @@ static int get_entry_index(const struct string_list *list, const char *string,
 }
 
 /* returns -1-index if already exists */
-static int add_entry(struct string_list *list, const char *string)
+static int add_entry(int insert_at, struct string_list *list, const char *string)
 {
-	int exact_match;
-	int index = get_entry_index(list, string, &exact_match);
+	int exact_match = 0;
+	int index = insert_at != -1 ? insert_at : get_entry_index(list, string, &exact_match);
 
 	if (exact_match)
 		return -1 - index;
@@ -53,7 +53,13 @@ static int add_entry(struct string_list *list, const char *string)
 
 struct string_list_item *string_list_insert(const char *string, struct string_list *list)
 {
-	int index = add_entry(list, string);
+	return string_list_insert_at_index(-1, string, list);
+}
+
+struct string_list_item *string_list_insert_at_index(int insert_at,
+						     const char *string, struct string_list *list)
+{
+	int index = add_entry(insert_at, list, string);
 
 	if (index < 0)
 		index = -1 - index;
@@ -68,6 +74,16 @@ int string_list_has_string(const struct string_list *list, const char *string)
 	return exact_match;
 }
 
+int string_list_find_insert_index(const struct string_list *list, const char *string,
+				  int negative_existing_index)
+{
+	int exact_match;
+	int index = get_entry_index(list, string, &exact_match);
+	if (exact_match)
+		index = -1 - (negative_existing_index ? index : 0);
+	return index;
+}
+
 struct string_list_item *string_list_lookup(const char *string, struct string_list *list)
 {
 	int exact_match, i = get_entry_index(list, string, &exact_match);
@@ -94,6 +110,25 @@ void string_list_clear(struct string_list *list, int free_util)
 	list->nr = list->alloc = 0;
 }
 
+void string_list_clear_func(struct string_list *list, string_list_clear_func_t clearfunc)
+{
+	if (list->items) {
+		int i;
+		if (clearfunc) {
+			for (i = 0; i < list->nr; i++)
+				clearfunc(list->items[i].util, list->items[i].string);
+		}
+		if (list->strdup_strings) {
+			for (i = 0; i < list->nr; i++)
+				free(list->items[i].string);
+		}
+		free(list->items);
+	}
+	list->items = NULL;
+	list->nr = list->alloc = 0;
+}
+
+
 void print_string_list(const char *text, const struct string_list *p)
 {
 	int i;
string-list.h +9 -0
index 4d6a705..d32ba05 100644
@@ -15,9 +15,18 @@ struct string_list
 void print_string_list(const char *text, const struct string_list *p);
 void string_list_clear(struct string_list *list, int free_util);
 
+/* Use this function to call a custom clear function on each util pointer */
+/* The string associated with the util pointer is passed as the second argument */
+typedef void (*string_list_clear_func_t)(void *p, const char *str);
+void string_list_clear_func(struct string_list *list, string_list_clear_func_t clearfunc);
+
 /* Use these functions only on sorted lists: */
 int string_list_has_string(const struct string_list *list, const char *string);
+int string_list_find_insert_index(const struct string_list *list, const char *string,
+				  int negative_existing_index);
 struct string_list_item *string_list_insert(const char *string, struct string_list *list);
+struct string_list_item *string_list_insert_at_index(int insert_at,
+						     const char *string, struct string_list *list);
 struct string_list_item *string_list_lookup(const char *string, struct string_list *list);
 
 /* Use these functions only on unsorted lists: */
Signature · 1 line
1.6.1.2.354.g9a90
#3 lore raw

PATCH v5 3/5 Add map_user() and clear_mailmap() to mailmap

map_user() allows to lookup and replace both email and name of a user, based on a new style mailmap file.

The possible mailmap definitions are now:

  proper_name <commit_email>                             # Old style
  <proper_email> <commit_email>                          # New style
  proper_name <proper_email> <commit_email>              # New style
  proper_name <proper_email> commit_name <commit_email>  # New style

map_email() operates the same as before, with the exception that it also will to try to match on a name passed in through the name return buffer.

clear_mailmap() is needed to now clear the more complex mailmap structure.

---
 Documentation/git-shortlog.txt |   87 +++++++++++++-----
 mailmap.c                      |  196 ++++++++++++++++++++++++++++++++++------
 mailmap.h                      |    4 +
 3 files changed, 236 insertions(+), 51 deletions(-)
Documentation/git-shortlog.txt +64 -23
index 66b6045..a0eaab5 100644
@@ -48,24 +48,38 @@ OPTIONS
 FILES
 -----
 
-If a file `.mailmap` exists at the toplevel of the repository, or at the
-location pointed to by the log.mailmap configuration option,
-it is used to map an author email address to a canonical real name. This
-can be used to coalesce together commits by the same person where their
-name was spelled differently (whether with the same email address or
-not).
-
-Each line in the file consists, in this order, of the canonical real name
-of an author, whitespace, and an email address (enclosed by '<' and '>')
-to map to the name. Use hash '#' for comments, either on their own line,
-or after the email address.
-
-A canonical name may appear in more than one line, associated with
-different email addresses, but it doesn't make sense for a given address
-to appear more than once (if that happens, a later line overrides the
-earlier ones).
-
-So, for example, if your history contains commits by two authors, Jane
+If the file `.mailmap` exists at the toplevel of the repository, or at
+the location pointed to by the mailmap.file configuration option, it
+is used to map author and committer names and email addresses to
+canonical real names and email addresses.
+This mapping can be used to coalesce together commits by the same
+person where their name and/or email address was spelled differently.
+
+In the simple form, each line in the file consists of the canonical
+real name of an author, whitespace, and an email address used in the
+commit (enclosed by '<' and '>') to map to the name. Thus, looks like
+this
+--
+	Proper Name <[email protected]>
+--
+
+The more complex forms are
+--
+	<[email protected]> <[email protected]>
+--
+which allows mailmap to replace only the email part of a commit, and
+--
+	Proper Name <[email protected]> <[email protected]>
+--
+which allows mailmap to replace both the name and the email of a
+commit matching the specified commit email address, and
+--
+	Proper Name <[email protected]> Commit Name <[email protected]>
+--
+which allows mailmap to replace both the name and the email of a
+commit matching both the specified commit name and email address.
+
+Example 1: Your history contains commits by two authors, Jane
 and Joe, whose names appear in the repository under several forms:
 
 ------------
@@ -76,16 +90,43 @@ Jane Doe <jane@laptop.(none)>
 Jane D. <jane@desktop.(none)>
 ------------
 
-Then, supposing Joe wants his middle name initial used, and Jane prefers
-her family name fully spelled out, a proper `.mailmap` file would look like:
+Now suppose that Joe wants his middle name initial used, and Jane
+prefers her family name fully spelled out. A proper `.mailmap` file
+would look like:
 
 ------------
-# Note how we don't need an entry for <jane@laptop.(none)>, because the
-# real name of that author is correct already, and coalesced directly.
-Jane Doe <jane@desktop.(none)>
+Jane Doe         <jane@desktop.(none)>
 Joe R. Developer <[email protected]>
 ------------
 
+Note how we don't need an entry for <jane@laptop.(none)>, because the
+real name of that author is correct already, and coalesced directly.
+
+Example 2: Your repository contains commits from the following
+authors:
+
+------------
+nick1 <[email protected]>
+nick2 <[email protected]>
+nick2 <[email protected]>
+santa <[email protected]>
+claus <[email protected]>
+CTO <[email protected]>
+------------
+
+Then, you might want a `.mailmap` file looking like:
+------------
+<[email protected]>                       <[email protected]>
+Some Dude <[email protected]>         nick1 <[email protected]>
+Other Author <[email protected]>   nick2 <[email protected]>
+Other Author <[email protected]>         <[email protected]>
+Santa Claus <[email protected]> <[email protected]>
+------------
+
+Use hash '#' for comments that are either on their own line, or after
+the email address.
+
+
 Author
 ------
 Written by Jeff Garzik <[email protected]>
mailmap.c +168 -28

244 lines not on this page · raw message

mailmap.h +4 -0
index ba2ee76..4b2ca3a 100644
@@ -2,6 +2,10 @@
 #define MAILMAP_H
 
 int read_mailmap(struct string_list *map, char **repo_abbrev);
+void clear_mailmap(struct string_list *map);
+
 int map_email(struct string_list *mailmap, const char *email, char *name, int maxlen);
+int map_user(struct string_list *mailmap,
+	     char *email, int maxlen_email, char *name, int maxlen_name);
 
 #endif
Signature · 1 line
1.6.1.2.354.g9a90
#4 lore raw

PATCH v5 4/5 Change current mailmap usage to do matching on both name and email of author/committer.

---
 Documentation/pretty-formats.txt |    2 +
 builtin-blame.c                  |   50 +++++++++++-------
 builtin-shortlog.c               |   22 ++++++--
 pretty.c                         |   57 +++++++++++----------
 t/t4203-mailmap.sh               |  106 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 186 insertions(+), 51 deletions(-)
Documentation/pretty-formats.txt +2 -0
index 3d87d3e..28808b7 100644
@@ -103,6 +103,7 @@ The placeholders are:
 - '%an': author name
 - '%aN': author name (respecting .mailmap)
 - '%ae': author email
+- '%aE': author email (respecting .mailmap)
 - '%ad': author date (format respects --date= option)
 - '%aD': author date, RFC2822 style
 - '%ar': author date, relative
@@ -111,6 +112,7 @@ The placeholders are:
 - '%cn': committer name
 - '%cN': committer name (respecting .mailmap)
 - '%ce': committer email
+- '%cE': committer email (respecting .mailmap)
 - '%cd': committer date
 - '%cD': committer date, RFC2822 style
 - '%cr': committer date, relative
builtin-blame.c +31 -19

107 lines not on this page · raw message

builtin-shortlog.c +17 -5
index 314b6bc..badd912 100644
@@ -40,6 +40,7 @@ static void insert_one_record(struct shortlog *log,
 	char *buffer, *p;
 	struct string_list_item *item;
 	char namebuf[1024];
+	char emailbuf[1024];
 	size_t len;
 	const char *eol;
 	const char *boemail, *eoemail;
@@ -51,7 +52,19 @@ static void insert_one_record(struct shortlog *log,
 	eoemail = strchr(boemail, '>');
 	if (!eoemail)
 		return;
-	if (!map_email(&log->mailmap, boemail+1, namebuf, sizeof(namebuf))) {
+
+	/* copy author name to namebuf, to support matching on both name and email */
+	memcpy(namebuf, author, boemail - author);
+	len = boemail - author;
+	while(len > 0 && isspace(namebuf[len-1]))
+		len--;
+	namebuf[len] = 0;
+
+	/* copy email name to emailbuf, to allow email replacement as well */
+	memcpy(emailbuf, boemail+1, eoemail - boemail);
+	emailbuf[eoemail - boemail - 1] = 0;
+
+	if (!map_user(&log->mailmap, emailbuf, sizeof(emailbuf), namebuf, sizeof(namebuf))) {
 		while (author < boemail && isspace(*author))
 			author++;
 		for (len = 0;
@@ -67,8 +80,8 @@ static void insert_one_record(struct shortlog *log,
 
 	if (log->email) {
 		size_t room = sizeof(namebuf) - len - 1;
-		int maillen = eoemail - boemail + 1;
-		snprintf(namebuf + len, room, " %.*s", maillen, boemail);
+		int maillen = strlen(emailbuf);
+		snprintf(namebuf + len, room, " <%.*s>", maillen, emailbuf);
 	}
 
 	item = string_list_insert(namebuf, &log->list);
@@ -321,6 +334,5 @@ void shortlog_output(struct shortlog *log)
 
 	log->list.strdup_strings = 1;
 	string_list_clear(&log->list, 1);
-	log->mailmap.strdup_strings = 1;
-	string_list_clear(&log->mailmap, 1);
+	clear_mailmap(&log->mailmap);
 }
pretty.c +30 -27

84 lines not on this page · raw message

t/t4203-mailmap.sh +106 -0

110 lines not on this page · raw message

Signature · 1 line
1.6.1.2.354.g9a90
#5 lore raw

PATCH v5 5/5 Move mailmap documentation into separate file

Include it directly from git-shortlog.txt, and refer to it from pretty-format.txt.

---
 Documentation/git-blame.txt      |    6 +++
 Documentation/git-shortlog.txt   |   89 ++++----------------------------------
 Documentation/mailmap.txt        |   75 ++++++++++++++++++++++++++++++++
 Documentation/pretty-formats.txt |    8 ++--
 4 files changed, 94 insertions(+), 84 deletions(-)
 create mode 100644 Documentation/mailmap.txt
Documentation/git-blame.txt +6 -0
index fba374d..6999cf2 100644
@@ -184,6 +184,12 @@ there is ever added information (like the commit encoding or extended
 commit commentary), a blame viewer won't ever care.
 
 
+MAPPING AUTHORS
+---------------
+
+include::mailmap.txt[]
+
+
 SEE ALSO
 --------
 linkgit:git-annotate[1]
Documentation/git-shortlog.txt +9 -80

95 lines not on this page · raw message

Documentation/mailmap.txt new file +75 -0

76 lines not on this page · raw message

Documentation/pretty-formats.txt +4 -4
index 28808b7..159390c 100644
@@ -101,18 +101,18 @@ The placeholders are:
 - '%P': parent hashes
 - '%p': abbreviated parent hashes
 - '%an': author name
-- '%aN': author name (respecting .mailmap)
+- '%aN': author name (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
 - '%ae': author email
-- '%aE': author email (respecting .mailmap)
+- '%aE': author email (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
 - '%ad': author date (format respects --date= option)
 - '%aD': author date, RFC2822 style
 - '%ar': author date, relative
 - '%at': author date, UNIX timestamp
 - '%ai': author date, ISO 8601 format
 - '%cn': committer name
-- '%cN': committer name (respecting .mailmap)
+- '%cN': committer name (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
 - '%ce': committer email
-- '%cE': committer email (respecting .mailmap)
+- '%cE': committer email (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
 - '%cd': committer date
 - '%cD': committer date, RFC2822 style
 - '%cr': committer date, relative
Signature · 1 line
1.6.1.2.354.g9a90
#6 lore raw
In reply to Marius Storm-Olsen

Marius Storm-Olsen said the following on 08.02.2009 15:34:

Quoted 8 lines

v5:
---
* Rename log.mailmap variable to mailmap.file
* Fix mailmap tests using shortlog, by adding HEAD
* Factor out the mailmap documentation, and include it from both git-shortlog.txt and git-blame.txt, since they both use mailmap directly. Link to these from pretty-format.txt, for all commands using the pretty option.

* Reworded the mailmap documentation a bit. Hopefully a bit easier to read.

--
.marius