git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Fixing author/email fields in commit messages

From
JNJon Nelson <jnelson-git@jamponi.net>
Date
Feb 19, 2006, 23:01 UTC
Message-ID
<Pine.LNX.4.63.0602191651340.6352@gheavc.wnzcbav.cig>
In-Reply-To
<Pine.LNX.4.63.0602191634480.6352@gheavc.wnzcbav.cig>
On Sun, 19 Feb 2006, Jon Nelson wrote:
Show 17 quoted lines
> On Sun, 19 Feb 2006, Jacob Kroon wrote:
> 
> > When I started my git repository for my project, I never setup GIT_AUTHOR_NAME
> > etc. correctly,
> > so my commit messages used the default information, "<jacob@skeletor.(none)>",
> > "skeletor" being the
> > hostname of the computer I'm working on. I'd like to change it so that the
> > messages will contain correct
> > information about my e-mail and username. I noticed that this question has
> > been brought up here before
> > and that the solution might be to use git-convert-objects, but that it might
> > need some modifications.
> > 
> > Has anyone come up with a working tool for this task ?
> 
> I modified git-convert-objects to perform just that task.
> I'll see if I can dig it up (I'm not able to do so right now).
Attached. Notes:
1. it's ugly
2. it's indented funny
3. it didn't seem to break anything for me, but no guarantees
4. it probably smells of elderberries
5. set your GIT_* environment up properly first or you'll wonder why it 
doesn't work like I did.

-- Jon Nelson <jnelson-git@jamponi.net>

diff --git a/convert-objects.c b/convert-objects.c
index b49bce2..109bfb0 100644
--- a/convert-objects.c
+++ b/convert-objects.c
@@ -263,7 +263,156 @@ static void convert_date(void *buffer, u
 	newlen += size;
 
 	write_sha1_file(new, newlen, "commit", result_sha1);
-	free(new);	
+	free(new);
+}
+
+static int convert_email_line(char *dst, void **buf, unsigned long *sp, const char *name, const char *new_email)
+{
+        unsigned long size = *sp;
+        char *line = *buf;
+        char *space = strchr(line, ' ');
+	char *next = strchr(line, '\n');
+	char *email_start = strchr(line, '<');
+        char *email_end = strchr(line, '>');
+        int len, total = 0;
+
+	// "author|committer xyz <xyz> date"
+        // "committer xyz <xyz> date"
+	if (!space || !next || !email_start || !email_end)
+            die("missing or bad author/committer line %s", line);
+
+        ++space;
+        ++email_start;
+        ++next;
+
+        //fprintf(stderr, "yikes: size; %lu \"%s\"\n", size, line);
+
+        *buf = next;
+        *sp = size - (next - line);
+
+        /* copy the stuff from before the name */
+        len = space - line;
+        memcpy(dst, line, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        /* copy the new name */
+        len = strlen(name);
+        memcpy(dst, name, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        /* put a space in there */
+        *dst = ' ';
+        ++dst;
+        ++total;
+        --size;
+
+        /* put a '<' in there */
+        *dst = '<';
+        ++dst;
+        ++total;
+        --size;
+
+        /* copy the new email */
+        len = strlen(new_email);
+        memcpy(dst, new_email, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        /* copy the rest of the line */
+        len = next - email_end;
+        memcpy(dst, email_end, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        return total;
+}
+
+static void convert_authorcommitter(void *buffer, unsigned long size, unsigned char *result_sha1)
+{
+	char *new = xmalloc(size + 100);
+        unsigned long newlen = 0;
+        char *author_info = strdup(git_author_info());
+        char *committer_info = strdup(git_committer_info());
+        char *author_name, *author_email;
+        char *committer_name, *committer_email;
+        char *temp;
+
+//#define TESTING
+#ifdef TESTING
+        fprintf(stderr, "author_info: \"%s\"\n",
+                author_info);
+        fprintf(stderr, "committer_info: \"%s\"\n",
+                committer_info);
+#endif
+        author_name = author_info;
+        temp = strchr(author_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        author_email = temp;
+        temp = strrchr(author_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+        committer_name = committer_info;
+        temp = strchr(committer_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        committer_email = temp;
+        temp = strrchr(committer_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+#ifdef TESTING
+        fprintf(stderr, "author_name: \"%s\"\n", author_name);
+        fprintf(stderr, "author_email: \"%s\"\n", author_email);
+        fprintf(stderr, "committer_name: \"%s\"\n", committer_name);
+        fprintf(stderr, "committer_email: \"%s\"\n", committer_email);
+        exit(0);
+#endif
+
+	// "tree <sha1>\n"
+	memcpy(new + newlen, buffer, 46);
+	newlen += 46;
+	buffer += 46;
+	size -= 46;
+
+	// "parent <sha1>\n"
+	while (!memcmp(buffer, "parent ", 7)) {
+		memcpy(new + newlen, buffer, 48);
+		newlen += 48;
+		buffer += 48;
+		size -= 48;
+	}
+
+	// "author xyz <xyz> date"
+	// "committer xyz <xyz> date"
+        newlen += convert_email_line(new + newlen, &buffer, &size, author_name, author_email);
+        newlen += convert_email_line(new + newlen, &buffer, &size, committer_name, committer_email);
+
+	// Rest
+	memcpy(new + newlen, buffer, size);
+	newlen += size;
+
+	write_sha1_file(new, newlen, "commit", result_sha1);
+        free(new);
+        free(author_info);
+        free(committer_info);
 }
 
 static void convert_commit(void *buffer, unsigned long size, unsigned char *result_sha1)
@@ -279,7 +428,117 @@ static void convert_commit(void *buffer,
 		convert_ascii_sha1(buffer+7);
 		buffer += 48;
 	}
-	convert_date(orig_buffer, orig_size, result_sha1);
+	convert_authorcommitter(orig_buffer, orig_size, result_sha1);
+}
+
+static void convert_tag(void *buffer, unsigned long size, unsigned char *result_sha1)
+{
+	void *orig_buffer = buffer;
+
+	char *new = xmalloc(size + 100);
+        unsigned long newlen = 0;
+
+        char *author_info = strdup(git_author_info());
+        char *committer_info = strdup(git_committer_info());
+        char *author_name, *author_email;
+        char *committer_name, *committer_email;
+        char *temp;
+        unsigned long len = 0;
+        char *email_start;
+        char *email_end;
+        char *author_start;
+        int has_author = 1;
+
+        author_name = author_info;
+        temp = strchr(author_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        author_email = temp;
+        temp = strrchr(author_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+        committer_name = committer_info;
+        temp = strchr(committer_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        committer_email = temp;
+        temp = strrchr(committer_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+        //* START *//
+
+	if (memcmp(buffer, "object ", 7))
+		die("Bad tag '%s'", (char*) buffer);
+        convert_ascii_sha1(buffer+7);
+//        fprintf(stderr, "converting %s", (char *) (buffer + 7));
+        buffer += 7 + 40 + 1;    /* "object " + "hex sha1" + "\n" */
+        /* type commit
+           tag boa-0.94.14rc6
+           tagger...
+           */
+        /* with tagger, we check for tagger author_name <author_email>
+         * and if so, we convert that, too
+         */
+        temp = strchr(buffer, '\n'); /* end of commit line */
+        if (!temp) {
+            die("Bad tag '%s'", (char *) buffer);
+        }
+        ++temp;
+        temp = strchr(temp, '\n'); /* end of tag line */
+        if (!temp) {
+            die("Bad tag '%s'", (char *) buffer);
+        }
+        ++temp;
+        if (memcmp(temp, "tagger ", 7))
+            die("Bad tag '%s'", (char *) buffer);
+        temp += 7; /* just after 'tagger ' */
+
+        len = (temp - (char *) orig_buffer);
+        memcpy(new, orig_buffer, len);
+        newlen += len;
+        ++temp;
+
+        /* check to see if the next item looks like an name + email */
+        email_start = strchr(temp, '<');
+        if (email_start) {
+            email_end = strchr(email_start, '>');
+            if (email_end) {
+                author_start = strchr(temp, ' ');
+                if (author_start && author_start < email_start) {
+                    has_author = 1;
+                    newlen += sprintf(new + newlen,
+                                      "%s <%s>\n",
+                                      author_name,
+                                      author_email);
+                    len = (email_end - (char *) buffer) + 2;
+                }
+
+            }
+        }
+
+        if (len > size) {
+            memcpy(new + newlen, orig_buffer + len, size - len);
+            newlen += (size - len);
+        }
+//        fprintf(stderr, "About to write: %s", new);
+//        exit(0);
+
+        write_sha1_file(new, newlen, "tag", result_sha1);
+        free(new);
+        free(author_info);
+        free(committer_info);
 }
 
 static struct entry * convert_entry(unsigned char *sha1)
@@ -297,13 +556,15 @@ static struct entry * convert_entry(unsi
 
 	buffer = xmalloc(size);
 	memcpy(buffer, data, size);
-	
+
 	if (!strcmp(type, "blob")) {
 		write_sha1_file(buffer, size, "blob", entry->new_sha1);
-	} else if (!strcmp(type, "tree"))
-		convert_tree(buffer, size, entry->new_sha1);
-	else if (!strcmp(type, "commit"))
-		convert_commit(buffer, size, entry->new_sha1);
+        } else if (!strcmp(type, "tree"))
+            convert_tree(buffer, size, entry->new_sha1);
+        else if (!strcmp(type, "commit"))
+            convert_commit(buffer, size, entry->new_sha1);
+        else if (!strcmp(type, "tag"))
+            convert_tag(buffer, size, entry->new_sha1);
 	else
 		die("unknown object type '%s' in %s", type, sha1_to_hex(sha1));
 	entry->converted = 1;
@@ -318,6 +579,7 @@ int main(int argc, char **argv)
 	struct entry *entry;
 
 	setup_git_directory();
+	setup_ident();
 
 	if (argc != 2 || get_sha1(argv[1], sha1))
 		usage("git-convert-objects <sha1>");
Previous: Jon NelsonNext: Jacob Kroon
Message 5 of 8 in “Fixing author/email fields in commit messages”
  1. Jacob KroonFeb 19, 2006
  2. Johannes SchindelinFeb 19, 2006
  3. Sam VilainFeb 19, 2006
  4. Jon NelsonFeb 19, 2006
  5. Jon NelsonFeb 19, 2006
  6. Jacob KroonFeb 19, 2006
  7. Jon NelsonFeb 19, 2006
  8. Jacob KroonFeb 20, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.