Fixing author/email fields in commit messages
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 know how to make the future commits look as expected.
//Jacob
Quoted 7 lines · Jacob Kroon
When I started my git repository for my project, I never setup
GIT_AUTHOR_NAMEetc. 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 ?
Perhaps "stg uncommit"
Sam.
Quoted 11 lines · Jacob Kroon
When I started my git repository for my project, I never setup
GIT_AUTHOR_NAMEetc. 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.
Quoted 1 line
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).
--
Jon Nelson <[email protected]>
Quoted 13 lines · Jon Nelson
Quoted 11 lines · Jacob Kroon
When I started my git repository for my project, I never setup
GIT_AUTHOR_NAMEetc. 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.
Quoted 4 lines
Quoted 1 line
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 <[email protected]>
convert-objects.c +269 -7
@@ -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>" );
Quoted 5 lines · Jon Nelson
Quoted 4 lines
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).
Quoted 10 lines
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.
Hi Jon,
I've applied your patch to the latest git sources, and it compiles, but I'm not quite sure how to invoke the command. I've setup GIT_* env. variables, and git-convert-objects needs a sha1 identifier. I've tried passing "HEAD", and some other commit id's, but they don't seem to make any difference. Am I doing things right ? How exactly do I invoke the command to clean up the commit messages ?
At least I don't get any error messages.
//Jacob
Quoted 29 lines · Jacob Kroon
Quoted 5 lines · Jon Nelson
Quoted 4 lines
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).
Quoted 11 lines
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.Hi Jon,
I've applied your patch to the latest git sources, and it compiles, but I'm not quite sure how to
invoke the command. I've setup GIT_* env. variables, and git-convert-objects needs a sha1 identifier.
I've tried passing "HEAD", and some other commit id's, but they don't seem to make any difference.
Am I doing things right ? How exactly do I invoke the command to clean up the commit messages ?
Quoted 1 line
At least I don't get any error messages.
If I recall properly, it should be sufficient to invoke it with the sha1 of the HEAD branch.
Thus, you could use:
git-convert-objects $(git-rev-list --max-count=1 HEAD)
To do /all/ of the branches:
for branch in $(cat .git/refs/heads/* | sort | uniq); do
git-convert-objects ${branch}
done
It should work on tags, too, although I only tested on my own git stuff which was converted from cvs.
--
Jon Nelson <[email protected]>
After some more private discussion (I forgot to CC the mailing list) with Jon Nelson, he came up with this strategy for fixing the author/email part of commit messages:
0. Make a backup copy of the repository, just in case.
1. Setup your GIT_AUTHOR_xxx/GIT_COMMITTER_xxx env. variables correctly.
2. Apply the attached patch to recent git sources. (patch made by Jon Nelson).
3. Run the patched git-convert-objects, passing HEAD as argument.
4. Run "git-update-ref HEAD 'newsha1'", where 'newsha1' is the output from the previous command.
5. Run "git-prune" to get rid of the old stale object files.
This worked for me, but I guess there are no warranties 8)
In case you have multiple branches you might need to repeat the procedure for each branch.
thanks Jon
//Jacob
convert-objects.c +269 -7
@@ -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>" );
Hi,
Quoted 10 lines · Jacob Kroon
When I started my git repository for my project, I never setup
GIT_AUTHOR_NAMEetc. 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 ?
Unfortunately not.
However, I'd rather start by enhancing git-rebase. You do not really need to rewrite *all* objects, but only the *commit objects*. Two things seem to be lacking for what you want:
- an option to rebase "onto an empty commit", and
- an optional filter command to run on the commit messages.
Hth,
Dscho