How can I fix a Git error broken link from tree to tree?

I got a transaction interrupted and when I try again I was having error with objects that were empty or corrupted, following another question I delete all the empty files and when I run

git fsck --full

I got this error:

Checking object directories: 100% (256/256), done.
Checking objects: 100% (48774/48774), done.
error: d193ccbc48a30e8961e9a2515a708e228d5ea16d: invalid sha1 pointer in cache-tree
error: df084ac4214f1a981481b40080428950865a6b31: invalid sha1 pointer in cache-tree
broken link from    tree 4bf4869299b294be9dee4ecdcb45d2c204ce623b
          to    tree df084ac4214f1a981481b40080428950865a6b31
broken link from    tree 4bf4869299b294be9dee4ecdcb45d2c204ce623b
          to    tree d193ccbc48a30e8961e9a2515a708e228d5ea16d
missing tree df084ac4214f1a981481b40080428950865a6b31
missing blob a632281618ca6895282031732d28397c18038e35
missing tree d193ccbc48a30e8961e9a2515a708e228d5ea16d
missing blob 70aa143b05d1d7560e22f61fb737a1cab4ff74c6
missing blob c21c0545e08f5cac86ce4dde103708a1642f23fb
missing blob 9f341b8a9fcd26af3c44337ee121e2d6f6814088
missing blob 396aaf36f602018f88ce985df85e73a71dea6f14
missing blob 87b9d1933d37cc9eb7618c7984439e3c2e685a11

How can I fix this problem?

Git


Solution 1:

With Git 2.10 (Q3 2016), you can know more about the origin of those broken links.

git fsck --name-objects

See commit 90cf590, commit 1cd772c, commit 7b35efd, commit 993a21b (17 Jul 2016) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit 9db3979, 25 Jul 2016)

fsck: optionally show more helpful info for broken links

When reporting broken links between commits/trees/blobs, it would be quite helpful at times if the user would be told how the object is supposed to be reachable.

With the new --name-objects option, git-fsck will try to do exactly that:
name the objects in a way that shows how they are reachable.

For example, when some reflog got corrupted and a blob is missing that should not be, the user might want to remove the corresponding reflog entry.
This option helps them find that entry: git fsck --name-objects will now report something like this:

  broken link from    tree b5eb6ff...  (refs/stash@{<date>}~37:)
                to    blob ec5cf80...

If those broken links don't come from a local stash but a remote repo, fetching those pack objects can then solve the situation.
See also "How to recover Git objects damaged by hard disk failure?".


With Git 2.31 (Q1 2021), fix "git fsck --name-objects"(man) which apparently has not been used by anybody who is motivated enough to report breakage.

See commit e89f893, commit 8c891ee (10 Feb 2021) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit 9e634a9, 17 Feb 2021)

fsck --name-objects: be more careful parsing generation numbers

Signed-off-by: Johannes Schindelin

In 7b35efd (fsck_walk(): optionally name objects on the go, 2016-07-17, Git v2.10.0-rc0 -- merge listed in batch #7) (fsck_walk(): optionally name objects on the go, 2016-07-17), the fsck machinery learned to optionally name the objects, so that it is easier to see what part of the repository is in a bad shape, say, when objects are missing.

To save on complexity, this machinery uses a parser to determine the name of a parent given a commit's name: any ~<n> suffix is parsed and the parent's name is formed from the prefix together with ~<n+1>.

However, this parser has a bug: if it finds a suffix <n> that is not ~<n>, it will mistake the empty string for the prefix and <n> for the generation number.
In other words, it will generate a name of the form ~<bogus-number>.

Let's fix this.

Solution 2:

What worked for me to fix this "broken link" error was the answer from sehe listed here in response to a question about how to fix an unable to find <insert sha1 code here> error.

Like Adam said, recover the object from another repository/clone.

  1. On a 'complete' Git database:

    git cat-file -p a47058d09b4ca436d65609758a9dba52235a75bd > tempfile
    
  2. and on the receiving end:

    git hash-object -w tempfile
    

One important addition would be that between step 1 and 2, it is important to directly transfer the file from one location to the other. In my experience, it didn't work to move the tempfile using Git push and pull.