Git objektumok
A git-tárolókban minden objektumként van tárolva. Négy típus létezik: blobok (fájltartalom), fák (könyvtárlisták), commitok (metaadatokkal ellátott pillanatképek) és címkék (annotált hivatkozások). Minden objektumot a tartalmából képzett SHA-1 hash azonosít.
Objektumtípusok
Blob
A blob nyers fájltartalmat tárol metaadatok nélkül (nincs fájlnév és jogosultság).
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)
Fa
A fa egy könyvtárlista. Minden bejegyzéshez mód, név és egy blobra vagy részfára mutató hash tartozik.
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);
A Tree::fromEntries() a megadott sorrendben írja ki a bejegyzéseket, és pontosan a megadott módkarakterláncokat használja, ezért előbb rendezze őket, a könyvtárak módját pedig 40000 alakban adja meg. A 040000 segítségével vagy más sorrendben írt fa hash értéke eltér a git által számítottól, a git fsck --strict pedig nullákkal feltöltött módot jelenít meg.
TreeEntry
A TreeEntry csak olvasható értékobjektum:
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)
Módértékek:
| Mód | Jelentés |
|---|---|
100644 |
Normál fájl |
100755 |
Végrehajtható fájl |
40000 |
Könyvtár (fa); a git ls-tree 040000 formában jeleníti meg |
120000 |
Szimbolikus hivatkozás |
160000 |
Gitlink (almodul) |
A fa bejegyzései név szerint rendezettek; az összehasonlítás során a könyvtárneveket úgy kell tekinteni, mintha / karakterrel végződnének.
Commit
A commit a fát az előzményeihez és metaadataihoz kapcsolja.
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 tartalmának összeállítása
$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",
);
A nyers commit formátuma:
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>
Címke
Az annotált címkék metaadatokat tartalmazó objektumok.
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
A nyers címke formátuma:
object <hex hash>\n
type commit\n
tag <name>\n
tagger <name> <<email>> <timestamp> <tz>\n
\n
<message>
ObjectId
A ObjectId csak olvasható értékobjektum, amely egy SHA-1 (vagy SHA-256) hash-t képvisel.
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);
A hash a tömörítetlen adatokból készül: sha1("{type} {size}, vagy ugyanazon bájtok SHA-256 változatából. A fromHex() és a fromBinary() a hossz alapján választja ki az algoritmust.
ObjectType enum
use Pitmaster\Object\ObjectType;
ObjectType::Blob; // 'blob'
ObjectType::Tree; // 'tree'
ObjectType::Commit; // 'commit'
ObjectType::Tag; // 'tag'
Laza objektumformátum
A laza objektumok egyedi fájlokként tárolódnak a .git/objects/ könyvtárban, a hashük első két hexadecimális karaktere szerint csoportosítva.
.git/objects/a1/b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
A fájltartalom zlib-tömörítésű. A tömörítetlen tartalom:
<type> <decimal size>\0<raw content>
Például a „Hello” szöveget tartalmazó blob tárolása:
zlib_encode("blob 5\0Hello")
Laza objektumok beolvasása
use Pitmaster\Storage\LooseObjectStore;
$store = new LooseObjectStore('/path/to/.git/objects');
$object = $store->read($objectId);
A LooseObjectStore:
- Kiszámítja a fájl elérési útját a hash alapján
- Beolvassa és zlib segítségével kitömöríti a fájlt
- Feldolgozza a fejlécet a típus és a méret kinyeréséhez
- Átadja a megfelelő feldolgozónak (
Blob,Tree,Commit,Tag)
Laza objektumok írása
$store->write($object);
Az írás folyamata:
- Szerializálás:
"{type} {size}\0{content}" - Az objektum
idértékének használata, amelyet az objektum létrehozásakor számít ki (beolvasáskor a hash ellenőrzésre kerül) - Tömörítés:
zlib_encode(serialized) - Kiírás ide:
.git/objects/{hash[0..1]}/{rest of hash} - Atomi írás (ideiglenes fájlba írás, majd átnevezés)
ObjectSerializer
A ObjectSerializer kezeli az objektumok vezetékes formátumának kódolását és dekódolását.
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
A ObjectDatabase összetett tároló, amely először a laza objektumok között, majd a csomagfájlokban keres.
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
A laza tárhelyre történő közvetlen írás szándékos. Hagyja, hogy a git gc csomagfájlokba rendezze az adatokat.
SHA-256 támogatása
A Pitmaster a ObjectId segítségével elvonatkoztatja a hash-algoritmust. Az alapértelmezett a SHA-1. A SHA-256 a tároló létrehozásakor választandó ki:
$repo = Pitmaster::init('/path/to/project', 'sha256');
./vendor/bin/pitmaster init --object-format=sha256
Ez a beállítás a konfigurációba írja a extensions.objectformat = sha256 értéket. A később megnyitott tárolók ebből a bejegyzésből olvassák ki a formátumot, majd minden objektum-, fa-, index- és refművelet 64 karakteres hexadecimális karakterláncokat és 32 bájtos bináris hash értékeket használ. Az algoritmushoz nincs globális kapcsoló vagy konstans.
Ha saját maga hoz létre objektumokat, az objektumosztályoknak argumentumként adja át az algoritmust: Blob::fromContent($content, 'sha256'), Tree::fromEntries($entries, 'sha256'), ObjectId::compute($type, $content, 'sha256'). A Pitmaster::clone() SHA-1 tárolókat hoz létre.
Faelemek bináris formátuma
A faobjektum tartalmában minden bejegyzés kódolása:
<octal mode as ASCII> <space> <filename> \0 <binary hash: 20 bytes SHA-1, 32 bytes SHA-256>
Megjegyzés: a hash nyers bináris adat, nem hexadecimális, ellentétben a commit- és címkeobjektumokban szereplő hexadecimális hash értékekkel.
A bejegyzések rendezésekor a neveket úgy kell összehasonlítani, mintha a könyvtárak végén / állna. A rendezésnek pontosnak kell lennie ahhoz, hogy a fa hash értéke megegyezzen a git által számítottal.