Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何修改Git提交历史中的author,email和name等信息 - 知乎 #96

Open
HenryTSZ opened this issue Feb 4, 2024 · 1 comment

Comments

@HenryTSZ
Copy link
Owner

HenryTSZ commented Feb 4, 2024

如何修改Git提交历史中的author,email和name等信息 - 知乎

在我们日常工作中,通常由于某种原因,需要更新历史提交的commit信息。一般会有如下几种场景:

  • 修改当前分支最新 commit 的提交信息
  • 修改当前分支某历史commit的提交信息
  • 修改当前分支所有提交的commit信息

对于当次提交来说,我们可以显示指定提交者信息。

git commit -m "Initial commit" --author="mn <mn@furzoom.com>"

通过git commit命令将暂存区内容添加到本地仓库后,git会生成相应的commit id。后续我们就可以针对指定的commit id 进行操作,比如,回退到某个commit id,拉取指定commit id的代码等。

下面我们针对上面的三种情况进行讲述。

修改上次提交的commit信息

git commit --amend --author="果冻<liguodongiot@163.com>"

输入git commit --amend之后,进入编辑模式,修改提交信息,然后按 esc,输入 :wq 保存退出。

如果不想修改提交信息,则添加--no-edit,如下所示:

git commit --amend --author="果冻不吃皮 <mn@furzoom.com>" --no-edit

git commit --amend命令只会修改最后一次commit的信息,之前的commit需要使用git rebase

修改上几次提交的commit信息

git rebase -i说明:
git rebase -i命令可以压缩合并多次提交。
格式:git rebase -i [startpoint] [endpoint]
其中,-i的意思是–interactive,即弹出交互式的界面让用户编辑完成合并操作,[startpoint] [endpoint]则指定了一个编辑区间,如果不指定 [endpoint] ,则该区间的终点默认是当前分支HEAD所指向的commit(该区间指定的是一个前开后闭的区间)。

首先,我们通过git rebase -i选择将哪些提交获得重定位。

例如,合并最近的三次提交:

git rebase -i HEAD~3

或者,合并从当前head到15f745b(commit id)的提交:

git rebase -i 15f745b

然后,在列表中将开头的pick修改为edit,然后重复执行以下命令直到完成:

git commit --amend --author="mn <mn@furzoom.com>"

之后,通过continue命令回到正常状态。

git rebase --continue

修改之前某一个特定的commit信息

查看log,找到上一次提交的commit id

git log

然后,通过git rebase到要修改的commit之前那个commit。

git rebase 928fc8a3686bf5fcf4527873e075703a9998c127 --interactive(与上面git rebase -i类似)

然后,在vi中修改pick为edit,wq保存退出,接着进行内容修改,git addgit commit --amend

修改所有提交的commit信息

前提:重置本项目用户的信息

git config user.name '果冻'
git config user.email 'liguodongiot@163.com'

方案一:git rebase

首先回到当前分支第一个commit。

git rebase -i --root

然后,弹出编辑器,在需要修改的commit处,将picked改变为edit,然后wq,退出vi。

git commit --amend --reset-author

之后,通过continue命令回到正常状态。

git rebase --continue

查看日志,确定是否修改成功

git log

最后,强制push到远程仓库

git push origin master -f

方案二:git filter-branch

使用git rebase方式,步骤比较多,可以直接使用 git filter-branch快速方便。

例如,将提交者liguodongiot@163.com修改为liguodongiot@foxmail.com

# !/bin/sh

git filter-branch --env-filter '

OLD_EMAIL="liguodongiot@163.com"
CORRECT_NAME="吃果冻不吐果冻皮"
CORRECT_EMAIL="liguodongiot@foxmail.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

要执行上述脚本,需要在命令行中进入要修改的Git仓库目录,然后将上述脚本保存为一个.sh文件(比如rename_email.sh),然后在命令行中执行以下命令:

sh rename_email.sh

代码执行前会输出一个警告:

WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.

这个警告是在提醒你,使用git-filter-branch工具进行历史重写时可能会出现一些问题,导致历史记录混乱。它建议你在进行下一步之前按Ctrl-C中止操作,然后考虑使用另一个过滤工具,比如'git filter-repo'。你可以参考filter-branch手册页面获取更多细节,如果想要消除这个警告,可以设置环境变量FILTER_BRANCH_SQUELCH_WARNING=1。

执行完毕后,Git会对所有的提交历史进行重写,并将提交者的邮箱地址修改为新的地址。需要注意的是,这种操作会改变提交的哈希值,因此如果这些提交已经被推送到远程仓库,那么需要谨慎操作,避免影响他人的代码。

如果需要多次执行这段代码,第二次可能会出现这个提示:

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

这个错误说明无法创建新的备份,因为在refs/original/目录下已经存在一个先前的备份。如果你确定要覆盖先前的备份,可以使用-f参数进行强制覆盖。但请注意,强制覆盖可能会导致数据丢失或不可恢复的情况,所以在使用之前请务必谨慎考虑。

如果需要添加 -f 参数来强制执行这个命令,可以将其添加到 git filter-branch 命令之后,例如:

git filter-branch -f --env-filter '
# 这里是原来的环境变量修改脚本
' --tag-name-filter cat -- --branches --tags

添加 -f 参数会在执行 git filter-branch 时强制覆盖先前的操作,所以请确保在使用 -f 参数时,已经仔细考虑可能的后果。

总结

注意:
如需将修改信息同步到远端仓库,可使用 git push -f 命令进行强制同步,该操作会覆盖远端分支的提交历史,请自行确认操作风险。

参考文档


你好,我叫果冻,创作不易,如果觉得我的博文能够帮助到你,期待你的点赞,祝好~~~

@HenryTSZ
Copy link
Owner Author

HenryTSZ commented Feb 5, 2024

修改以后,其他人执行 git pull 命令后,会提示:

fatal: refusing to merge unrelated histories

原因是两个分支是两个不同的版本,具有不同的提交历史

需要使用如下命令:

git pull origin master --allow-unrelated-histories

注意 master 要改成你需要处理的分支名

可以允许不相关历史提,强制合并

参见:解决git中fatal: refusing to merge unrelated histories - 知乎

执行后会提示:

fatal: Not possible to fast-forward, aborting.

还需要使用以下命令:

git pull origin master --rebase

重新校准基础版本,将本地的基础版本更新为git上的基础版本

注意执行这个命令之前你需要将本地代码全部暂存,当然 master 也需要注意更换

参见:git pull 提示Not possible to fast-forward,无法提交也无法更新-CSDN博客

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant