如何更改一系列提交的作者?
当前回答
我们今天遇到了一个问题,作者名中的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机器上重新运行它。
其他回答
当从另一位作者手中接过一份未合并的承诺时,有一种简单的方法来处理。
gitcommit--修改--重置作者
我使用以下方法重写整个存储库(包括标记和所有分支)的作者:
git filter-branch --tag-name-filter cat --env-filter "
export GIT_AUTHOR_NAME='New name';
export GIT_AUTHOR_EMAIL='New email'
" -- --all
然后,如过滤器分支的MAN页面所述,删除过滤器分支备份的所有原始引用(这是破坏性的,首先备份):
git for-each-ref --format="%(refname)" refs/original/ | \
xargs -n 1 git update-ref -d
我想对@Rognon的回答进行修改。如果所选答案或其他答案不适用于您(在我的特定问题中就是这样),则此答案只是另一种选择:
目标:您将在所有历史记录中用正确的作者修复一个或多个作者,并且您将获得无重复的干净历史记录。此方法的工作原理是将“master”分支替换为“clean”分支(它不使用merge/rebase)
注意:任何使用“主”存储库的人都可能需要在推送之前再次签出(执行这些步骤后),因为合并可能会失败。
我们将使用一个名为“clean”的新分支来执行操作(假设您想修复“master”):
git checkout-b clean
(确保您处于“干净”分支:git分支)
修改以下脚本(替换电子邮件地址和名称)。请注意,此脚本需要两个错误的电子邮件/作者(例如),因此如果您只需要修复一个作者,则可以删除条件的第二部分或将其保持原样(因为它将被忽略,因为它不匹配)。
执行脚本。
#/bin/bash
git filter-branch --force --commit-filter '
if [ "$GIT_COMMITTER_EMAIL" = "wrong1@example.com" -o "$GIT_COMMITTER_EMAIL" = "wrong2@example.com" ];
then
export GIT_COMMITTER_NAME="John Doe";
export GIT_AUTHOR_NAME="John Doe";
export GIT_COMMITTER_EMAIL="correct@example.com";
export GIT_AUTHOR_EMAIL="correct@example.com";
fi;
git commit-tree "$@"
' --tag-name-filter cat -- --all
它必须报告:Ref'refs/heads/clean'被重写。如果报告“未更改”,则脚本中输入的电子邮件可能是错误的。
使用:git log确认历史已更正
如果您正在使用github/gitlab(建议=安全):
在remote中创建“clean”分支:
git push—设置上游原点清洁
将“clean”分支设置为默认分支删除“master”(在执行此操作之前,确保一切都符合预期)。基于“clean”分支创建一个新分支“master”。确认一切正常后,您可以立即删除“clean”分支(也可以重命名它)。
如果您没有使用github/gitlab,或者您更喜欢使用命令:
从本地删除主分支:
git分支-d主
重命名分支:
gitbranch-m清理主机
推它(确保你的“主人”没有受到保护)
git push—强制原始主机
一个带过滤器的衬里:
您可以使用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变量更改为正确的值。)
当您没有初始化$HOME/.gitconfig时,就会发生这种情况。您可以将其修复为:
git config --global user.name "you name"
git config --global user.email you@domain.example
git commit --amend --reset-author
使用Git 1.7.5.4版进行测试。
注意,这只修复了最后一次提交。
推荐文章
- Bower: ENOGIT Git未安装或不在PATH中
- Bitbucket上的Git:总是要求密码,即使上传了我的公共SSH密钥
- Git别名-多个命令和参数
- 如何添加一个“打开git-bash这里…”上下文菜单到windows资源管理器?
- Mercurial初学者:最终实用指南
- 是否可以在Git中只提取一个文件?
- 当我做“git diff”的时候,我怎么能得到一个并排的diff ?
- 在git中如何将提交移动到暂存区?
- 如何缩小。git文件夹
- 如何在本地删除分支?
- 找到包含特定提交的合并提交
- Windows上Git文件的权限
- 如何从一个枝头摘到另一个枝头
- 如何获得在两次Git提交之间更改的所有文件的列表?
- 什么是跟踪分支?