如何更改一系列提交的作者?


当前回答

我已经尝试了上面的脚本,但它不适合我,这解决了我的问题:

使用Git的“filter branch”命令。它允许您使用脚本批量处理(可能大量)提交。您可以在存储库中运行以下示例脚本(填写新旧电子邮件和名称的真实值):

git filter-branch --env-filter '
WRONG_EMAIL="wrong@example.com"
NEW_NAME="New Name Value"
NEW_EMAIL="correct@example.com"

if [ "$GIT_COMMITTER_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$NEW_NAME"
    export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$NEW_NAME"
    export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

在此处查看更多详细信息

其他回答

我改编了这个解决方案,它通过摄取一个简单的author conv文件(格式与git cvsimport相同)来工作。它通过在所有分支中更改author conv文件中定义的所有用户来工作。

我们将其与cvs2git结合使用,将存储库从cvs迁移到git。

即示例作者conv文件

john=John Doe <john.doe@hotmail.com>
jill=Jill Doe <jill.doe@hotmail.com>

脚本:

 #!/bin/bash

 export $authors_file=author-conv-file

 git filter-branch -f --env-filter '

 get_name () {
     grep "^$1=" "$authors_file" |
     sed "s/^.*=\(.*\) <.*>$/\1/"
 }

 get_email () {
     grep "^$1=" "$authors_file" |
     sed "s/^.*=.* <\(.*\)>$/\1/"
 }

 GIT_AUTHOR_NAME=$(get_name $GIT_COMMITTER_NAME) &&
     GIT_AUTHOR_EMAIL=$(get_email $GIT_COMMITTER_NAME) &&
     GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME &&
     GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL &&
     export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
     export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 ' -- --all

你的问题很普遍。请参阅“使用Mailmap修复Git中的作者列表”

为了简单起见,我创建了一个脚本来简化这个过程:gitchangemail

将该脚本放到路径上后,可以发出以下命令:

更改当前分支上的作者匹配$git changemail-aold@email.com-n新名称-mnew@email.com更改<branch>和<branch2>上的作者和提交者匹配。将-f传递到筛选器分支以允许重写备份$git changemail-bold@email.com-n新名称-mnew@email.com---f&lt;分支>&lt;分支2>显示回购中的现有用户$git changemail--显示两者

顺便说一下,在进行更改后,使用:gitbackupclean从过滤器分支中清除备份

更改最后N次提交的作者的单个命令:

git rebase -i HEAD~N -x "git commit --amend --author 'Author Name <author.name@mail.example>' --no-edit"

笔记

用引用替换HEAD~N,直到您要重写提交的地方。这可以是哈希、HEAD~4、分支名称。。。--no edit标志确保gitcommit--modify不会要求额外的确认当您使用gitrebase-i时,您可以手动选择要更改作者的提交位置,

您编辑的文件将如下所示:

pick 897fe9e simplify code a little
exec git commit --amend --author 'Author Name <author.name@mail.example>' --no-edit
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.example>' --no-edit
pick dc18f70 bugfix
exec git commit --amend --author 'Author Name <author.name@mail.example>' --no-edit

然后,您仍然可以修改一些行,以查看要更改作者的位置。这为您在自动化和控制之间提供了一个很好的中间地带:您可以看到将要运行的步骤,一旦您保存了所有内容,将立即应用。

请注意,如果您已经使用git-configuser.name<your_name>和git-config user.email<your_email>修复了作者信息,那么也可以使用以下命令:

git rebase -i HEAD~N -x "git commit --amend --reset-author --no-edit"

一个带过滤器的衬里:

您可以使用gitfilter repo的回调功能(推荐替换过滤器分支)来更改与所有提交相关的名称和电子邮件:

git filter-repo --name-callback 'return b"New Name"' --email-callback 'return b"newemail@gmail.com"'

这比使用过滤器分支的解决方案性能更高,可能更可靠。

请注意,上面的命令会更改所有提交的作者(和提交者),如果您想有效地“编辑”某个作者,并且只修改该特定作者的提交,请使用--commit回调选项,如下所示:

git filter-repo --commit-callback '
old_email = b"oldemail@gmail.com"
new_email = b"newemail@gmail.com"
new_name = b"New Author"

if commit.author_email == old_email:
    commit.author_email = new_email
    commit.author_name = new_name

if commit.committer_email == old_email:
    commit.committer_email = new_email
    commit.committer_name = new_name
'

(只需将上面命令中的old_email、new_email和new_name变量更改为正确的值。)

我们今天遇到了一个问题,作者名中的UTF8字符在构建服务器上造成了麻烦,因此我们必须重写历史记录来纠正这个问题。所采取的步骤包括:

步骤1:按照此处的说明,更改所有未来提交的git用户名:https://help.github.com/articles/setting-your-username-in-git/

步骤2:运行以下bash脚本:

#!/bin/sh

REPO_URL=ssh://path/to/your.git
REPO_DIR=rewrite.tmp

# Clone the repository
git clone ${REPO_URL} ${REPO_DIR}

# Change to the cloned repository
cd ${REPO_DIR}

# Checkout all the remote branches as local tracking branches
git branch --list -r origin/* | cut -c10- | xargs -n1 git checkout

# Rewrite the history, use a system that will preseve the eol (or lack of in commit messages) - preferably Linux not OSX
git filter-branch --env-filter '
OLD_EMAIL="me@something.com"
CORRECT_NAME="New Me"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
fi
' --tag-name-filter cat -- --branches --tags

# Force push the rewritten branches + tags to the remote
git push -f

# Remove all knowledge that we did something
rm -rf ${REPO_DIR}

# Tell your colleagues to `git pull --rebase` on all their local remote tracking branches

快速概述:将存储库签出到临时文件,签出所有远程分支,运行将重写历史记录的脚本,强制推送新状态,并告诉所有同事重新启动数据库以获取更改。

我们在OS X上运行它时遇到了问题,因为它在提交消息中以某种方式打乱了行结尾,所以我们不得不在Linux机器上重新运行它。