How to delete an entry with null sha1 in the Git tree

I inherited a git repository with null sha1 to write commit in the tree, preventing FishEye from indexing the repository.

$ git fsck Checking object directoriies: 100%(256/256), done. warning in tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9: contains entries pointing to null sha1 Checking objects: 100% (416532/416532), done. Checking connectivity: 416532, done. 

Searching for this tree gives me the following result:

 $ git ls-tree db22a6 100644 blob e615f18b55a39f2719112ce209c2505dd92d8e75 .gitignore 100644 blob ac852f06c5a04420356c1d5efca44d9a864e78b0 .project 160000 commit 0000000000000000000000000000000000000000 SomeDirectory 100644 blob 631c17e28026261a2ccf6bc570842cf4af9f181c GoDeploy.bat 100644 blob 40e992ab5c3868af2910135c3ac4610c3646e7f8 pom.xml 

In history, I found that SomeDirectory was originally a submodule of git and that the commit that seems to be causing the problem is the one that removed both .gitmodules and SomeDirectory . Now there is a real directory called SomeDirectory in the same place where the culprit was.
I, although I can still try to fix the git filter-branch mileage to see that I finish, but it does not work:

 $ git filter-branch --force --index-filter \ $ 'git rm --cached --ignore-unmatch SomeDirectory' \ $ --prune-empty --tag-name-filter cat -- --all [... striped out for clarity] Rewrite c571a3ec94e9f84471577bac41ac7375c729ef08 (76/18522)error: cache enttry has null sha1: SomeDirectory fatal: unable to write new index file Could not initialize the index [... striped out for clarity] 

What should I try next, knowing that there is no backup that I know about before commit, which causes the problem.

+7
git git-filter-branch atlassian-fisheye
source share
2 answers

The message you receive assumes that there is only one tree with a bad submodule. In this case, very little needs to be cleaned. You can create a new fixed tree that does not have this problem:

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

Your question already shows the output of git ls-tree . sed deletes the row with the wrong submodule, and git mktree creates a new tree object from the result.

Once you have a 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 problem commit object in text form. It will start with tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 and continue with the rest of the commit information (parent, author, committer, commit message). sed replaces the reference to the tree line with the old tree with 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 identifier.

Once you commit, you can use git replace :

  $ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (new commit SHA1 here)

It still won't change anything, but tells Git that whenever it reads commit c571a3ec94e9f84471577bac41ac7375c729ef08 , it should instead read a new commit object.

Finally, use git filter-branch to make it persistent. This goes through all the commits, reads them, and writes them back. Usually, without any options for changing commits, this will not have much effect, but due to an earlier git replace it causes all commits with c571a3ec94e9f84471577bac41ac7375c729ef08 as a parent, which will be rewritten to refer to the new commit instead, all the commits that refer to those that have been rewritten, etc.

+13
source share

Maybe it will work with interactive rebase to change the commit containing a reference to the SomeDirectory commit error, for example.

 $ 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 
0
source share

All Articles