我有一个未损坏的 git 存储库(所有对象文件都保留,我可以提交给它等等)。
最近我注意到一些旧的提交被破坏了,“提交错误”:
git fsck --完整 检查对象目录:100% (256/256),完成。 提交 1e04e033e642f9310bd7b0e6745f3ef775a15f15 中的错误:无效的作者/提交者行 - 错误的电子邮件
我查看了个人提交:
zpipe -d <.git/objects/1e/04e033e642f9310bd7b0e6745f3ef775a15f15 提交 276tree 591e98a0b53880a22f18f5bedefe133166d3e67d 父级 4c33ebce11897dd52528defa41890eabc59135e3 作者马丁·林德 <[电子邮件受保护] > 1382869510 +0100 提交者 Martin Lindhe <[电子邮件受保护] > 1382869510 +0100 提交消息
如此处所示,电子邮件有一个尾随换行符(0x0a,如通过管道传输到 xxd 所示)
是否可以修复对象头?
答案1
在进行所有操作之前,请先备份本地存储库。
假设您损坏的提交是<corrupted>
.
首先,基于损坏的提交对象创建一个新的提交对象:
git commit-tree -m "New message line 1" -m "Line 2" <corrupt>^{tree} -p <corrupt>^1
注意:调整您的命令(-p 用于添加父项,-m 用于提交消息行等)。请参阅 git-commit-tree 手册页来处理作者姓名/电子邮件等。
您将获得一个新的提交 SHA-1: <fixed>
。
现在进行提交替换(移植):
git replace <corrupted> <fixed>
这将创建一个“移植”,它将人为地用固定的提交更改损坏的提交。
此修改是可逆的:您可以删除它或通过git-replace
命令显示它(请参阅其手册页!)或查看.git/refs/replace/
目录。
要使其永久,请使用git filter-branch
但所有更改的部分都将由新的提交对象(即新的 SHA-1)组成。
# HEAD should point to the most recent commit (certainly master)...
git filter-branch <fixed>~1..HEAD
最后,延迟您的替换(现在永久保留在您的历史记录中):
git replace -d <corrupted>
这对于一个主分支效果很好,但如果您有多个活动分支(在 <corrupted> 之后创建),您将必须像这样对所有分支进行变基:
git rebase --onto <new-root-branch> <old-root-branch> <branch>
在哪里:
<new-root-branch>
是分支现在应该开始的提交(新的基本 SHA-1);<old-root-branch>
是在过滤器分支调用之前分支开始的提交;<branch>
是要变基的分支。
使用如下日志命令查找这些 SHA-1:
git log --graph --decorate --all --pretty=oneline
当您仔细检查一切都正常(分支等)并且链接到您的 git 存储库的每个人都完全了解发生了什么时,您可以git push --force
您的修改。