How to remove an entry with null sha1 in a Git tree

China☆狼群 提交于 2019-11-27 23:09:11

The message you get suggests that there was only a single tree with a bad submodule. In that case, there is very little you have to clean up. You can create a new fixed tree that doesn't have this problem:

$ git ls-tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 |
> sed -e '/0\{40\}/d' |
> git mktree
(new tree SHA1 here)

Your question shows the git ls-tree output already. The sed removes the line with the bad submodule, and git mktree creates a new tree object from the result.

Once you have the fixed tree, you can create a fixed commit using this tree:

$ git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08 |
> sed 's/db22a67df70dc4ff90ec4cd666da91e9c2cb0d9/(new tree SHA1 here)/' |
> git hash-object -t commit -w --stdin
(new commit SHA1 here)

git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08 prints the problematic commit object in a textual form. It will start with tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9, and continues with the rest of the commit info (parent, author, committer, commit message). The sed replaces the tree line's reference to the old tree by the new one. git hash-object -t commit -w --stdin creates a new commit object from the result, writes it to the repository, and prints its ID.

Once you have the fixed commit, you can use git replace:

$ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (new commit SHA1 here)

This doesn't actually change anything yet, but tells Git that whenever it would read commit c571a3ec94e9f84471577bac41ac7375c729ef08, it should read the new commit object instead.

And finally, use git filter-branch to make it permanent. This goes through all commits, reads them, and writes them back. Ordinarily, without any options to modify the commits, this wouldn't have much effect, but because of the earlier git replace, this causes all commits with c571a3ec94e9f84471577bac41ac7375c729ef08 as a parent to be re-written to refer to the new commit instead, all commits which refer to those re-written as well, etc.

Maybe it will work with an interactive rebase to modify the commit that contains the troublesome SomeDirectory commit reference, e.g.

$ git branch backup_branch       # To be able to revert if not satisfied
$ git rebase -i db22a6^          # From parent to db22a6
...
# You then select Edit for commit db22a6 in the editor
...
$ git reset HEAD^             # Reset the commit db22a6 but not its changes
$ git status
...
# should list as modified: .gitignore .project SomeDirectory GoDeploy.bat pom.xml
...
$ git checkout SomeDirectory     # Cancel the troublesome change
$ git add .gitignore .project GoDeploy.bat pom.xml
$ git commit -m "your commit message"
$ git rebase --continue
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!