Pereiti prie turinio

Git objektai

Viskas git saugykloje saugoma kaip objektas. Yra keturi tipai: blob objektai (failų turinys), medžių objektai (katalogų sąrašai), pakeitimai (momentinės kopijos su metaduomenimis) ir žymos (anotuotos nuorodos). Kiekvienas objektas identifikuojamas pagal jo turinio SHA-1 maišą.

Objektų tipai

Blob

Blob saugo neapdorotą failo turinį be metaduomenų (be failo pavadinimo ir teisių).

PHP
use Pitmaster\Object\Blob;

// Create from content
$blob = Blob::fromContent('Hello, world!');
echo $blob->content;    // 'Hello, world!'
echo $blob->size();     // 13
echo $blob->id->hex;    // SHA-1 hash
echo $blob->type->value; // 'blob' (the property is ObjectType::Blob)

Tree

Tree yra katalogų sąrašas. Kiekvienas įrašas turi režimą, pavadinimą ir maišą, nurodančią blob arba žemesnio lygio tree.

PHP
use Pitmaster\Object\Tree;
use Pitmaster\Object\TreeEntry;

// Read a tree
$tree = $repo->readObject($treeHash);

foreach ($tree->entries as $entry) {
    echo "{$entry->mode} {$entry->name} {$entry->hash->hex}\n";
}

// Look up a specific entry
$entry = $tree->entry('README.md');

// Create a tree (entries already in git's sort order)
$entries = [
    new TreeEntry('100644', 'README.md', $blobId),
    new TreeEntry('100755', 'deploy.sh', $execBlobId),
    new TreeEntry('40000', 'src', $subtreeId),
];

$tree = Tree::fromEntries($entries);

Tree::fromEntries() įrašo pateiktus įrašus nurodyta tvarka ir režimų eilutes tiksliai taip, kaip jos pateiktos, todėl pirmiausia jas surikiuokite, o katalogų režimus nurodykite kaip 40000. Tree, įrašytas naudojant 040000 arba kita tvarka, turės kitokią maišą nei git, o git fsck --strict pateikia režimą su nuliais priekyje.

TreeEntry

TreeEntry yra tik skaitomas reikšmės objektas:

PHP
use Pitmaster\Object\TreeEntry;

$entry->mode;   // '100644', '100755', '40000', '120000', '160000'
$entry->name;   // Filename
$entry->hash;   // ObjectId

// Type checks
$entry->isBlob();        // regular or executable file (mode 10xxxx)
$entry->isExecutable();  // mode 100755
$entry->isTree();        // mode 40000 (also accepts 040000)
$entry->isSymlink();     // mode 120000
$entry->isGitlink();     // mode 160000 (submodule)

Režimų reikšmės:

Režimas Reikšmė
100644 Įprastas failas
100755 Vykdomasis failas
40000 Katalogas (tree); git ls-tree rodo kaip 040000
120000 Simbolinė nuoroda
160000 Gitlink (submodulis)

Tree įrašai rūšiuojami pagal pavadinimą; lyginant katalogų pavadinimus laikoma, kad jų gale yra /.

Commit

Commit susieja tree su jo istorija ir metaduomenimis.

PHP
use Pitmaster\Object\Commit;

$commit = $repo->head();

$commit->id;         // ObjectId
$commit->tree;       // ObjectId of the tree
$commit->parents;    // array of ObjectId (zero for root, one for normal, two+ for merge)
$commit->author;     // 'Name <email> timestamp timezone'
$commit->committer;  // 'Name <email> timestamp timezone'
$commit->message;    // Full commit message

$commit->isMerge();  // true if two or more parents

Commit turinio kūrimas

PHP
$content = Commit::buildContent(
    tree: $treeId,
    parents: [$parentId],
    author: 'Jane <jane@example.com> 1700000000 +0000',
    committer: 'Jane <jane@example.com> 1700000000 +0000',
    message: "Add feature\n",
);

Neapdorotas commit formatas:

Kodas
tree <hex hash>\n
parent <hex hash>\n       (zero or more)
author <name> <<email>> <timestamp> <tz>\n
committer <name> <<email>> <timestamp> <tz>\n
\n
<message>

Tag

Anotuoti tag yra objektai su metaduomenimis.

PHP
use Pitmaster\Object\Tag;

$tag = $repo->readObject($tagHash);

$tag->object;        // ObjectId of the target
$tag->objectType;    // ObjectType enum (ObjectType::Commit, ...)
$tag->name;          // Tag name
$tag->tagger;        // 'Name <email> timestamp timezone'
$tag->message;       // Tag message

Neapdorotas tag formatas:

Kodas
object <hex hash>\n
type commit\n
tag <name>\n
tagger <name> <<email>> <timestamp> <tz>\n
\n
<message>

ObjectId

ObjectId yra tik skaitomas reikšmės objektas, atitinkantis SHA-1 (arba SHA-256) maišą.

PHP
use Pitmaster\Object\ObjectId;
use Pitmaster\Object\ObjectType;

// From hex string
$id = ObjectId::fromHex('a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2');

// From binary (20 bytes for SHA-1, 32 for SHA-256)
$id = ObjectId::fromBinary($rawBytes);

// Compute from content
$id = ObjectId::compute(ObjectType::Blob, 'Hello, world!');
$id = ObjectId::compute(ObjectType::Blob, 'Hello, world!', 'sha256');

// Zero hash
$id = ObjectId::zero();
$id = ObjectId::zero('sha256');

// Properties
$id->hex;      // 40-character hex string (64 for SHA-256)
$id->binary;   // 20-byte raw binary (32 for SHA-256)
$id->algo;     // 'sha1' or 'sha256'
$id->isSha256();
$id->isZero();

// Comparison
$id->equals($otherId);

Maiša apskaičiuojama pagal nesuglaudintus duomenis: sha1("{type} {size}{content}") arba SHA-256 iš tų pačių baitų. fromHex() ir fromBinary() algoritmą parenka pagal ilgį.

ObjectType išvardijimas

PHP
use Pitmaster\Object\ObjectType;

ObjectType::Blob;    // 'blob'
ObjectType::Tree;    // 'tree'
ObjectType::Commit;  // 'commit'
ObjectType::Tag;     // 'tag'

Laisvųjų objektų formatas

Laisvieji objektai saugomi kaip atskiri failai kataloge .git/objects/, suskirstyti pagal pirmuosius du jų maišos šešioliktainius simbolius.

Kodas
.git/objects/a1/b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2

Failo turinys suglaudinamas naudojant zlib. Nesuglaudintas turinys:

Kodas
<type> <decimal size>\0<raw content>

Pavyzdžiui, blob, kuriame yra „Hello“, saugomas taip:

Kodas
zlib_encode("blob 5\0Hello")

Laisvųjų objektų skaitymas

PHP
use Pitmaster\Storage\LooseObjectStore;

$store = new LooseObjectStore('/path/to/.git/objects');
$object = $store->read($objectId);

LooseObjectStore:

  1. Apskaičiuoja failo kelią pagal maišą
  2. Perskaito failą ir išskleidžia zlib suglaudintus duomenis
  3. Išanalizuoja antraštę, kad gautų tipą ir dydį
  4. Perduoda duomenis atitinkamam analizatoriui (Blob, Tree, Commit, Tag)

Laisvųjų objektų įrašymas

PHP
$store->write($object);

Įrašymo eiga:

  1. Serializavimas: "{type} {size}\0{content}"
  2. Naudojama objekto id, apskaičiuota jį sukūrus (skaitant maiša patikrinama)
  3. Suspaudimas: zlib_encode(serialized)
  4. Įrašymas į .git/objects/{hash[0..1]}/{rest of hash}
  5. Atominis įrašymas (įrašoma į laikiną failą, tada jis pervadinamas)

ObjectSerializer

ObjectSerializer tvarko objekto perdavimo formato kodavimą ir dekodavimą.

PHP
use Pitmaster\Storage\ObjectSerializer;

// Encode
$raw = ObjectSerializer::encodeRaw($object);
// "blob 5\0Hello"
$compressed = ObjectSerializer::encode($object);
// zlib-compressed form, as stored in a loose object file

// Decode
$object = ObjectSerializer::decodeRaw($raw);
$object = ObjectSerializer::decode($compressed, $expectedHex); // throws CorruptObjectException on a hash mismatch

ObjectDatabase

ObjectDatabase yra sudėtinė saugykla, kuri pirmiausia ieško laisvųjų objektų, tada paketo failuose.

PHP
use Pitmaster\Storage\ObjectDatabase;

$db = new ObjectDatabase('/path/to/.git/objects');

$object = $db->read($objectId);    // Search loose, then packs
$db->write($object);               // Always writes to loose
$exists = $db->exists($objectId);  // Check loose, then packs
$all = $db->listAll();             // All hashes from loose + packs

Rašymas tiesiai į laisvųjų objektų saugyklą yra tyčinis. Leiskite git gc pergrupuoti objektus į paketo failus.

SHA-256 palaikymas

Pitmaster maišos algoritmą abstrahuoja per ObjectId. Pagal numatytuosius nustatymus naudojama SHA-1. SHA-256 parenkama kuriant saugyklą:

PHP
$repo = Pitmaster::init('/path/to/project', 'sha256');
Shell
./vendor/bin/pitmaster init --object-format=sha256

Taip extensions.objectformat = sha256 įrašomas į konfigūraciją. Vėliau atidarytos saugyklos formatą nuskaito iš šio įrašo, o visos objektų, tree, indekso ir nuorodų operacijos naudoja 64 simbolių šešioliktaines eilutes ir 32 baitų dvejetaines maišas. Nėra bendrojo jungiklio ar konstantos, skirtos algoritmui pakeisti.

Kuriant objektus rankiniu būdu, objekto klasėms algoritmas perduodamas kaip argumentas: Blob::fromContent($content, 'sha256'), Tree::fromEntries($entries, 'sha256'), ObjectId::compute($type, $content, 'sha256'). Pitmaster::clone() kuria SHA-1 saugyklas.

Tree įrašo dvejetainis formatas

Tree objekto turinyje kiekvienas įrašas koduojamas taip:

Kodas
<octal mode as ASCII> <space> <filename> \0 <binary hash: 20 bytes SHA-1, 32 bytes SHA-256>

Pastaba: maiša yra neapdorota dvejetainė seka, o ne šešioliktainė, priešingai nei commit ir tag objektuose esančios šešioliktainės maišos.

Įrašai rūšiuojami lyginant pavadinimus taip, tarsi katalogų pavadinimų gale būtų /. Ši tvarka turi būti tiksli, kad tree maiša sutaptų su git apskaičiuota maiša.