如何更改一系列提交的作者?
当前回答
对于重置当前用户和当前时间戳的所有提交(包括首次提交):
git rebase --root --exec "git commit --amend --no-edit --date 'now' --reset-author"
其他回答
这是@Brian版本的更详细版本:
要更改作者和提交人,可以执行以下操作(在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
您可能会遇到以下错误之一:
临时目录已存在以Refs/original开头的引用已存在(这意味着先前在存储库上运行了另一个过滤器分支,然后在refs/original处备份原始分支引用)
如果要在出现这些错误的情况下强制运行,请添加--force标志:
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
可能需要对--all选项做一点解释:它使过滤器分支可以处理所有引用(包括所有分支)的所有修订。例如,这意味着标记也被重写,并且在重写的分支上可见。
一个常见的“错误”是使用HEAD,这意味着只过滤当前分支上的所有修订。然后,重写的分支中不存在标记(或其他引用)。
一个带过滤器的衬里:
您可以使用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变量更改为正确的值。)
对于单个提交:
git commit --amend --author="Author Name <email@address.example>"
(摘自阿斯梅勒的回答)
这个答案使用gitfilter分支,文档现在给出了这个警告:gitfilter分支有太多的缺陷,可能会对预期的历史重写造成不明显的影响(而且由于它的性能非常糟糕,因此几乎没有时间调查这些问题)。这些安全和性能问题不能向后兼容地解决,因此不建议使用。请使用其他历史筛选工具,如git filter repo。如果您仍然需要使用git过滤器分支,请仔细阅读安全(和性能)以了解过滤器分支的地雷,然后尽可能小心地避免列出的危险。
更改作者(或提交人)需要重写所有历史。如果您对此感到满意,并认为这是值得的,那么您应该查看gitfilter分支。手册页面包括几个示例,可帮助您入门。还要注意,您可以使用环境变量来更改作者、提交人、日期等的名称——请参阅git手册页面的“环境变量”部分。
具体来说,您可以使用以下命令修复所有分支和标记的所有错误作者名称和电子邮件(来源:GitHub帮助):
#!/bin/sh
git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
对于使用替代历史过滤工具gitfilter repo,您可以首先安装它并根据gitmailmap的格式构造gitmailmap。
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
然后使用创建的mailmap运行过滤器repo:
git filter-repo --mailmap git-mailmap
我们今天遇到了一个问题,作者名中的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机器上重新运行它。
推荐文章
- 如何将git配置存储为存储库的一部分?
- 如何修改GitHub拉请求?
- 如何在Github和本地删除最后n次提交?
- 我如何调试git/git-shell相关的问题?
- 错误:无法使用rebase进行拉取:您有未分阶段的更改
- Git隐藏未缓存:如何把所有未分期的变化?
- 真实的恶魔
- 如何从另一个分支获得更改
- Git:权限被拒绝(publickey)致命-无法从远程存储库读取。克隆Git存储库时
- git reflog和log有什么区别?
- git推挂在Total line之后
- 重命名git子模块
- 结合Git存储库的前两次提交?
- Xcode 6 gitignore文件应该包括什么?
- 我如何从现有回购的分支创建一个新的GitHub回购?