git学习------>如何修改git已提交的记录中的Author和Email?

一、背景

最近搭建好GitLab后,准备陆陆续续的将之前在SVN仓库中保存的代码迁移到GitLab上,昨天顺利将三个Android组件的代码迁移到GitLab后,其他同事发现迁移是成功了,但是pull下来命令后查看git log 发现所有人的有些都配置成了我的邮箱,尴尬啊。

GitLab上面全部变成了我的提交记录,尴尬。

二、原因分析

下面具体分析下为什么产生这个的原因。

具体原因是因为再做SVN–>Git迁移准备的时候,第一步要建议SVN用户到Git用户的映射文件。而这个映射文件最终我将所有用户的名字改过来了,但是邮箱没有改,全部填了我自己的邮箱。

ouyangpeng = ouyangpeng <ouyangpeng = ouyangpeng <ouyangpeng@csdn.com>>
lihongmeng = lihongmeng <ouyangpeng@oaserver.dw.gdbbk.com>
liyang = liyang <ouyangpeng@oaserver.dw.gdbbk.com>
wangshuyin = wangshuyin <ouyangpeng@oaserver.dw.gdbbk.com>
wuqi = wuqi <ouyangpeng@oaserver.dw.gdbbk.com>
youpeng = youpeng <ouyangpeng@oaserver.dw.gdbbk.com>
zhangjie = zhangjie <ouyangpeng@oaserver.dw.gdbbk.com>

在 Subversion,每个提交者在都在主机上有一个用户名,记录在提交信息中。如果想让已有的信息更好的映射到 Git 作者数据里,则需要 从 Subversion 用户名到 Git 作者的一个映射关系,因为Git是用邮箱来标识一个提交者的。建立一个叫做 userinfo.txt 的文件,每行一条svn作者 = 作者昵称 <邮箱地址>,用如下格式表示映射关系

ouyangpeng = ouyangpeng <ouyangpeng@csdn.com>
abc= abc<abc@csdn.com>

在SVN代码的文件目录下,使用如下命令获取到所有提交者的名字。
获取svn提交的作者名并保存到userinfo.txt

svn log --xml | grep "^<author" | sort -u | \awk -F '<author>' '{print $2}' | awk -F '</author>' '{print $1}' > userinfo.txt

得到以下文本,文本格式如下所示:

ouyangpeng
lihongmeng
liyang
wangshuyin
wuqi
youpeng
zhangjie

然后根据以上的格式编辑作者的邮件信息等,就是在这一步由于粗心,只是替换了对应的Git用户,并没有将邮箱替换过来,编译后的文本如下所示:

ouyangpeng = ouyangpeng <ouyangpeng = ouyangpeng <ouyangpeng@csdn.com>>
lihongmeng = lihongmeng <ouyangpeng@oaserver.dw.gdbbk.com>
liyang = liyang <ouyangpeng@oaserver.dw.gdbbk.com>
wangshuyin = wangshuyin <ouyangpeng@oaserver.dw.gdbbk.com>
wuqi = wuqi <ouyangpeng@oaserver.dw.gdbbk.com>
youpeng = youpeng <ouyangpeng@oaserver.dw.gdbbk.com>
zhangjie = zhangjie <ouyangpeng@oaserver.dw.gdbbk.com>

如上所示,所有的SVN用户名都有对应的Git用户名,但是此用户的邮箱都填了我的oa邮箱,并没有填写对应的git用户的邮箱,尴尬!因此才导致迁移后的git log 里面所有人的邮箱都是我的邮箱。

三、解决方案

具体如何从svn迁移到git的话,在本篇博客不讨论了。本篇博客只记录下如何修改git已提交的记录中的Author和Email?

1、查询解决方案

查询【stack overflow】 网站,

https://stackoverflow.com/questions/750172/change-the-author-and-committer-name-and-e-mail-of-multiple-commits-in-git

得到下面的解决方法:

原文如下:

To change the author and committer, you can do this (with linebreaks in the string which is possible in bash):

git filter-branch --env-filter '
    if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
    then
        GIT_COMMITTER_NAME="<New name>";
        GIT_COMMITTER_EMAIL="<New email>";
        GIT_AUTHOR_NAME="<New name>";
        GIT_AUTHOR_EMAIL="<New email>";
    fi' -- --all

This is a more elaborated version of @Brian’s version:

To change the author and committer, you can do this (with linebreaks in the string which is possible in bash):

git filter-branch –env-filter ’
if [ “$GIT_COMMITTER_NAME” = “” ];
then
GIT_COMMITTER_NAME=””;
GIT_COMMITTER_EMAIL=””;
GIT_AUTHOR_NAME=””;
GIT_AUTHOR_EMAIL=””;
fi’ – –all

You might get one of these errors:

  1. The temporary directory exists already
  2. Refs starting with refs/original exists already
    (this means another filter-branch has been run previously on the repository and the then original branch reference is backed up at refs/original)
git filter-branch --force --env-filter '
    if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
    then
        GIT_COMMITTER_NAME="<New name>";
        GIT_COMMITTER_EMAIL="<New email>";
        GIT_AUTHOR_NAME="<New name>";
        GIT_AUTHOR_EMAIL="<New email>";
    fi' -- --all

A little explanation of the -- --all option might be needed: It makes the filter-branch work on all revisions on all refs (which includes all branches). This means, for example, that tags are also rewritten and is visible on the rewritten branches.

A common “mistake” is to use HEAD instead, which means filtering all revisions on just the current branch. And then no tags (or other refs) would exist in the rewritten branch.

2、编写解决方案脚本

按照上面的思路,我自己改写了下脚本,如下所示,

在git项目下,新建一个shell脚本文件,明明为 modify_email_by_name.sh,shell脚本的内容如下所示:

  #!/bin/bash 

 git filter-branch  --force --env-filter '
     #如果Git用户名等于老的Git用户名 wangshuyin
     if [ "$GIT_COMMITTER_NAME" = "wangshuyin" ] || [ "$GIT_AUTHOR_EMAIL" = "wangshuyin" ];
     then
        #替换用户名为新的用户名,替换邮箱为正确的邮箱
        GIT_AUTHOR_NAME="wangshuyin";
        GIT_AUTHOR_EMAIL="wangshuyin@oaserver.dw.gdbbk.com"; 

        #替换提交的用户名为新的用户名,替换提交的邮箱为正确的邮箱
        GIT_COMMITTER_NAME="wangshuyin";
        GIT_COMMITTER_EMAIL="wangshuyin@oaserver.dw.gdbbk.com";
     fi 

     #如果Git用户名等于老的Git用户名 lihongmeng
     if [ "$GIT_COMMITTER_NAME" = "lihongmeng" ] || [ "$GIT_AUTHOR_EMAIL" = "lihongmeng" ];
     then
        #替换用户名为新的用户名,替换邮箱为正确的邮箱
        GIT_AUTHOR_NAME="lihongmeng";
        GIT_AUTHOR_EMAIL="lihongmeng@oaserver.dw.gdbbk.com";
        #替换提交的用户名为新的用户名,替换提交的邮箱为正确的邮箱
        GIT_COMMITTER_NAME="lihongmeng";
        GIT_COMMITTER_EMAIL="lihongmeng@oaserver.dw.gdbbk.com";
     fi 

     #如果Git用户名等于老的Git用户名 liyang
     if [ "$GIT_COMMITTER_NAME" = "liyang" ] || [ "$GIT_AUTHOR_EMAIL" = "liyang" ];
     then
        #替换用户名为新的用户名,替换邮箱为正确的邮箱
        GIT_AUTHOR_NAME="liyang";
        GIT_AUTHOR_EMAIL="liyang@oaserver.dw.gdbbk.com"; 

        #替换提交的用户名为新的用户名,替换提交的邮箱为正确的邮箱
        GIT_COMMITTER_NAME="liyang";
        GIT_COMMITTER_EMAIL="liyang@oaserver.dw.gdbbk.com";
     fi 

     #如果Git用户名等于老的Git用户名 wuqi
     if [ "$GIT_COMMITTER_NAME" = "wuqi" ] || [ "$GIT_AUTHOR_EMAIL" = "wuqi" ];
     then
        #替换用户名为新的用户名,替换邮箱为正确的邮箱
        GIT_AUTHOR_NAME="wuqi";
        GIT_AUTHOR_EMAIL="wuqi@oaserver.dw.gdbbk.com"; 

        #替换提交的用户名为新的用户名,替换提交的邮箱为正确的邮箱
        GIT_COMMITTER_NAME="wuqi";
        GIT_COMMITTER_EMAIL="wuqi@oaserver.dw.gdbbk.com";
     fi 

     #如果Git用户名等于老的Git用户名 youpeng
     if [ "$GIT_COMMITTER_NAME" = "youpeng" ] || [ "$GIT_AUTHOR_EMAIL" = "youpeng" ];
     then
        #替换用户名为新的用户名,替换邮箱为正确的邮箱
        GIT_AUTHOR_NAME="youpeng";
        GIT_AUTHOR_EMAIL="youpeng@oaserver.dw.gdbbk.com"; 

        #替换提交的用户名为新的用户名,替换提交的邮箱为正确的邮箱
        GIT_COMMITTER_NAME="youpeng";
        GIT_COMMITTER_EMAIL="youpeng@oaserver.dw.gdbbk.com";
     fi 

     #如果Git用户名等于老的Git用户名 zhangjie
     if [ "$GIT_COMMITTER_NAME" = "zhangjie" ] || [ "$GIT_AUTHOR_EMAIL" = "zhangjie" ];
     then
        #替换用户名为新的用户名,替换邮箱为正确的邮箱
        GIT_AUTHOR_NAME="zhangjie";
        GIT_AUTHOR_EMAIL="zhangjierj@oaserver.dw.gdbbk.com"; 

        #替换提交的用户名为新的用户名,替换提交的邮箱为正确的邮箱
        GIT_COMMITTER_NAME="zhangjie";
        GIT_COMMITTER_EMAIL="zhangjierj@oaserver.dw.gdbbk.com";
     fi
 '  --tag-name-filter cat -- --branches --tags

因为项目人数总共就6个,因此我全部列出来,然后遍历的去改变git log 已经提交的日志中的用户名和密码。如下所示:

3、执行解决方案脚本

在执行脚本之前,先查看本地分支和远程分支是否同步

使用如下Git命令查看所有远程分支:

git branch -r

使用如下Git命令查看所有本地分支:

git branch

如下图所示:

然后再使用命令如下命令,拉取远程分支并建立并切换到本地分支

git checkout -b 本地分支名x origin/远程分支名x

使用该方式会在本地新建分支x,并自动切换到该本地分支x。

如上图所示,拉取完毕之后,并保证和远程分支都相同了,然后再执行modify_email_by_name.sh脚本文件

然后执行命令,使modify_email_by_name.sh脚本文件可执行

chmod +x modify_email_by_name.sh

接着执行modify_email_by_name.sh脚本文件

./modify_email_by_name.sh

如上所示,所有的分支都被重写了一遍。

接着使用git log 命令查看一下被修改后的提交记录,如下所示:

由上图可以看到,所有的邮箱都改为正常映射的邮箱了。

4、执行过程错误

在执行编写脚本过程中,不停改脚本不停执行脚本,因此可能出现问题。
当执行脚本的时候,报了如下的错误

.git-rewrite already exists,please remove it

解决方法是:
参考文档:http://alistairboettiger.info/wordpress/?p=6171

 $ rm -rf .git-rewrite
 $ git filter-branch --tree-filter 'rm -rf ./External' HEAD

如下图所示:

在执行脚本的时候,有一次我只是写了一个用户的替换方案,执行完后改变脚本文件再执行的时候,报了如下错误:

Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f

解决方法是:

参考文档:
http://www.davidverhasselt.com/git-how-to-remove-your-password-from-a-repository/

https://stackoverflow.com/questions/6403601/purging-file-from-git-repo-failed-unable-to-create-new-backup

执行代码:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch Rakefile' HEAD

如下图所示:

5、提交正确的历史记录到GitLab服务器

执行命令

git push --force --tags origin 'refs/heads/*'

改掉之后,再次查看GitLab上的提交记录,会发现都正常换过来了,如下所示:

对比下修改之前的gitlab记录

四、参考文档

  1. https://stackoverflow.com/questions/750172/change-the-author-and-committer-name-and-e-mail-of-multiple-commits-in-git
  2. https://help.github.com/articles/changing-author-info/
  3. http://blog.csdn.net/diu_brother/article/details/51982993
  4. http://www.jianshu.com/p/b6add8187c06
  5. http://lmbj.net/blog/how-do-i-change-the-author-of-a-commit-in-git/
  6. http://www.davidverhasselt.com/git-how-to-remove-your-password-from-a-repository/
  7. https://stackoverflow.com/questions/6403601/purging-file-from-git-repo-failed-unable-to-create-new-backup
  8. http://alistairboettiger.info/wordpress/?p=6171


作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/ouyang_peng/article/details/75329779

如果本文对您有所帮助,欢迎您扫码下图所示的支付宝和微信支付二维码对本文进行打赏。

时间: 2025-01-02 23:50:59

git学习------&gt;如何修改git已提交的记录中的Author和Email?的相关文章

Git学习--&gt;GitLab如何修改时区?

一.背景 今天有同事在GitLab上查看时间的时候,发现GitLab上显示的时间和提交的时间不一致. 本地时间现在为:2017-11-28 11:43 查看本地代码提交的时间为:2017-11-28 11:23 本地时间现在为:2017-11-28 11:43,查看本地代码提交的时间为:2017-11-28 10:23,确实是一个小时之前,但是在GitLab平台上显示的世界为2017-11-28 02:23. 正好相差八个小时,因此我怀疑是GitLab服务器的时区我没有进行设置导致的.下面我就将

git学习------&amp;gt;写给 Git 初学者的7个建议

PS:本文转载于(http://blog.jobbole.com/50603/),本文由 伯乐在线 - 吴鹏煜 翻译. 英文出处:(http://sixrevisions.com/web-development/git-tips/) 当我刚刚开始使用Git的版本控制时,我根本不确定我付出那么多时间是不是会得到回报.Branch.Stage.Stash,这些Git名词对我来说都非常陌生. 而今天的我已不能想象生活没有Git会变成什么样.Git不仅提供了我非常需要的版本控制功能,还让我变成一个更优秀

修改eclipse自动生成的comments中的author名字

这几天要对项目的源代码生成JavaDoc,而Eclipse自动生成的comments中的author名字默认是当前系统的用户名,例如我的系统用户名是user /** * @author user * */ 我总是要改为我自己的姓名,这多繁琐啊!现在算有空了,百度看看,网上有人说新建一个code Template,目前只看到这种网上提供的方法! 后来我决定自己探索Eclipse的配置页面,最终找到了不用新建code Template,而是直接修改code Template! 1. 先看看Eclip

git学习------&amp;gt;如何用git log命令来查看某个指定文件的提交历史记录

       有时候接手一份新代码时,看到某些文件的改动,但不清楚这个改动的作者和原因,想查看该文件的具体提交历史记录.        今天一个同事是这样做的,直接敲git log命令,然后再使用vim命令的搜索关键字的方法来查看该文件的提交记录,如下所示: 例如:我想查看frameworks/base/packages/SystemUI/AndroidManifest.xml该文件的提交记录,敲了git log命令后,直接按"/"然后加入该文件的路径,后就可以搜索该文件名作为关键字,

git学习——Git 基础要点【转】

转自:http://blog.csdn.net/zeroboundary/article/details/10549555 简单地说,Git 究竟是怎样的一个系统呢?请注意,接下来的内容非常重要,若是理解了 Git 的思想和基本的工作原理,用起来就会知其所以然,游刃有余.在开始学习 Git 的时候,请不要尝试把各种概念和其他的版本控制系统诸如 Subversion 和 Perforce 等相比拟,否则容易混淆每个操作的实际意义.Git 在保存和处理各种信息的时候,虽然操作起来的命令形式非常相近,

Git学习备忘

    本文参考廖雪峰写的精彩的git学习文档,大家可以直接去官网看原版,我这里只是便于自己记录梳理 原版地址:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000     ubuntu下可以直接sudo apt-get install git来安装git.如果是mac,Xcode自带git,但是版本可能比较低.你可以到git官网下载最新的git src或较旧的dmg文件到本地安装.安

Git学习--&amp;gt;如何通过Shell脚本自动定时将Gitlab备份文件复制到远程服务器?

一.背景 在我之前的博客 git学习--> Gitlab如何进行备份恢复与迁移? (地址:http://blog.csdn.net/ouyang_peng/article/details/77070977) 里面已经写清楚了如何使用Gitlab自动备份功能. 但是之前的备份功能只是备份到Gitlab服务运行的那台服务器上,如果哪一天那台服务器的磁盘损坏了的话,数据无法取出,那么对于公司来说是一匹无法想象的损失,因为 代码是公司的重要资产,需要以防万一. 代码是公司的重要资产,需要以防万一. 代码

Git 学习笔记

  Git/'ɡɪt/,  Linus的第二个伟大作品.Git这个词有点儿意思,Linus自嘲说 "I'm an egotistical bastard,  and I name all my projects after myself. First Linux, now Git. "  感叹我生不逢时,错过了版本控制的"史前黑暗"时代,刚刚接触版本控制,Linus就站在前边,笑嘻嘻的说:"版本控制? 什么是版本控制 .. ".真希望Linus身

Git学习笔记

创建版本库 1 初始化一个Git仓库:git init. 2 添加文件到Git仓库,分两步: 第一步,git add <file>,可反复使用,也可一次添加多个文件. 第二部,git commit -m "commit description",完成. 3 掌握工作区的状态:git status. 4 如果git status告诉你有文件被修改过,用git diff可以查看修改内容. 时光机穿梭 版本回退 1 HEAD指向的版本就是当前版本,Git允许我们再版本的历史之间穿