修复 git 对象标头

修复 git 对象标头

我有一个未损坏的 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您的修改。

相关内容