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.