How do I tighten my objects?

2019-09-19 10:42发布

问题:

When I try to pull on Sourcetree I get:

git -c diff.mnemonicprefix=false -c core.quotepath=false fetch origin
error: inflate: data stream error (unknown compression method)
fatal: loose object 982fcbfe3c97cec4319853db4e32bd77f72ae0bf (stored in .git/objects/98/2fcbfe3c97cec4319853db4e32bd77f72ae0bf) is corrupt


fatal: index-pack failed

I got this message previously with a different random string of letters/numbers, and decided to delete that specific file and then I got this one. So I'm assuming that if I delete, pull, delete, pull etc. I will eventually clear all errors and be able to pull.

Is there a way to fix all these errors at once? ie. tighten these objects so they don't produce a "loose object error".

Why am I getting this? What does it actually mean to be a loose object? What is the likely cause of this (ie. what did I do wrong to get this) and how can I avoid this in the future?

Edit: it seems like my assumption was wrong, after deleting several of these files and trying to pull again, I get Fatal: pack has 88 unresolved deltas. fatal: index-pack failed. Note: I didn't actually delete the files I just moved them away, if they're still needed.

回答1:

The problem is not that the objects are loose (they are "loose" but their opposite is "packed", not "tightened") but rather that they are damaged (or, once you remove them, missing entirely).

The weird looking names like 982fcbfe3c97cec4319853db4e32bd77f72ae0bf are in fact SHA-1 IDs, which are the "true names" of the objects, as computed by git's SHA-1 checksum code (which operates on the git header followed by the uncompressed data). Because SHA-1 is a cryptographic checksum, the name itself validates the data: opening the file, de-compressing it, and running the checksum over the resulting data should produce the same SHA-1.

It's not, and this means either the name is wrong, or the stored data have been damaged. This is how git automatically detects damage (well, one of the ways, but they are all based on the same SHA-1 checksum idea).

This in turn means that whatever storage medium (local disk, SSD, cloud storage, or whatever it is you are using) is defective: it's not storing your files correctly. You will need to deal with this first, then go ahead and fix up your repository (usually by restoring a backup or cloning a copy from someplace that still has a good version).

Side topic: what exactly is a "loose object"?

A git repository is just an "object store" database with some special glue.

An object, in git, is one of four file types: commit, tree, blob (file), or tag (annotated tag).

Initially, each object is stored separately, in a file whose name matches the object's SHA-1 checksum, which git uses as the object's name. To retrieve anything from the database, you need this name; you give this to the object store code and it extracts the associated data (decompressing if needed).

Even compressed, however, objects can take a lot of disk space, and many objects—such as source files—are similar to other versions of the same object. So, to save more disk space, git can "pack" a bunch of objects into a "pack file". Inside a pack file, git compresses these objects against each other (this is the "delta compression" that you see now and then). The resulting pack file has its own SHA-1 name, and git keeps an index of all the SHA-1 IDs of all the objects stored within it. If you ask the repository object-extractor for an object, it first checks for a loose object; if not found, it checks the packs (via their index), and extracts it from there.