Git Nesneleri
git deposundaki her şey bir nesne olarak saklanır. Dört tür vardır: blob'lar (dosya içeriği), tree'ler (dizin listeleri), commit'ler (üst verili anlık görüntüler) ve tag'ler (açıklamalı referanslar). Her nesne, içeriğinin SHA-1 özetiyle tanımlanır.
Nesne türleri
Blob
Bir blob, üst veri olmadan ham dosya içeriğini tutar (dosya adı veya izinler içermez).
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
Bir tree, dizin listesidir. Her girdide bir mod, ad ve bir blob'a ya da alt tree'ye işaret eden özet bulunur.
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() girdileri verilen sırayla ve mod dizelerini tam olarak belirtildiği gibi yazar; bu nedenle önce sıralayın ve dizin modlarını 40000 olarak yazın. 040000 ile veya başka bir sırada yazılan tree, git'ünkinden farklı bir özete sahip olur; git fsck --strict ise modu başında sıfırlar olacak şekilde bildirir.
TreeEntry
TreeEntry salt okunur bir değer nesnesidir:
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)
Mod değerleri:
| Mod | Anlamı |
|---|---|
100644 |
Normal dosya |
100755 |
Çalıştırılabilir dosya |
40000 |
Dizin (tree); git ls-tree tarafından 040000 olarak gösterilir |
120000 |
Sembolik bağlantı |
160000 |
Gitlink (alt modül) |
Tree girdileri ada göre sıralanır; karşılaştırma yapılırken dizin adlarının sonunda / varmış gibi değerlendirilir.
Commit
Bir commit, bir tree'yi geçmişine ve üst verilerine bağlar.
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 içeriğini oluşturma
$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",
);
Ham commit biçimi:
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
Açıklamalı tag'ler, üst veri içeren nesnelerdir.
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
Ham tag biçimi:
object <hex hash>\n
type commit\n
tag <name>\n
tagger <name> <<email>> <timestamp> <tz>\n
\n
<message>
ObjectId
ObjectId, bir SHA-1 (veya SHA-256) özetini temsil eden salt okunur bir değer nesnesidir.
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);
Özet, sıkıştırılmamış veri üzerinden hesaplanır: sha1("{type} {size} veya aynı baytların SHA-256 biçimi. fromHex() ve fromBinary() algoritmayı uzunluğa göre seçer.
ObjectType enum'u
use Pitmaster\Object\ObjectType;
ObjectType::Blob; // 'blob'
ObjectType::Tree; // 'tree'
ObjectType::Commit; // 'commit'
ObjectType::Tag; // 'tag'
Gevşek nesne biçimi
Gevşek nesneler, .git/objects/ içinde, özetlerinin ilk iki onaltılık karakterine göre düzenlenmiş ayrı dosyalar olarak saklanır.
.git/objects/a1/b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
Dosya içeriği zlib ile sıkıştırılır. Sıkıştırılmamış içerik şöyledir:
<type> <decimal size>\0<raw content>
Örneğin, "Hello" içeren bir blob şu şekilde saklanır:
zlib_encode("blob 5\0Hello")
Gevşek nesneleri okuma
use Pitmaster\Storage\LooseObjectStore;
$store = new LooseObjectStore('/path/to/.git/objects');
$object = $store->read($objectId);
LooseObjectStore:
- Dosya yolunu özetten hesaplar
- Dosyayı okur ve zlib sıkıştırmasını açar
- Türü ve boyutu çıkarmak için başlığı ayrıştırır
- Uygun ayrıştırıcıya devreder (
Blob,Tree,Commit,Tag)
Gevşek nesneleri yazma
$store->write($object);
Yazma işlemi:
- Serileştir:
"{type} {size}\0{content}" - Nesne oluşturulurken hesaplanan
iddeğerini kullan (okumalar özeti doğrular) - Sıkıştır:
zlib_encode(serialized) .git/objects/{hash[0..1]}/{rest of hash}konumuna yaz- Atomik yazma (geçici dosyaya yaz, ardından yeniden adlandır)
ObjectSerializer
ObjectSerializer, nesne kablo biçiminin kodlanmasını ve çözülmesini yönetir.
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, önce gevşek nesneleri, ardından paket dosyalarını arayan bileşik bir depodur.
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
Gevşek depoya doğrudan yazma bilinçli bir tercihtir. Paket dosyalarına yeniden paketleme işini git gc'e bırakın.
SHA-256 desteği
Pitmaster, özet algoritmasını ObjectId üzerinden soyutlar. Varsayılan SHA-1'dir. SHA-256, depo oluşturulurken depo başına seçilir:
$repo = Pitmaster::init('/path/to/project', 'sha256');
./vendor/bin/pitmaster init --object-format=sha256
Bu işlem extensions.objectformat = sha256 değerini yapılandırmaya yazar. Daha sonra açılan depolar biçimi bu girdiden okur; tüm nesne, tree, dizin ve ref işlemleri artık 64 karakterlik onaltılık dizeler ve 32 baytlık ikili özetler kullanır. Algoritma için genel bir anahtar veya sabit yoktur.
Nesneleri kendiniz oluşturduğunuzda nesne sınıfları algoritmayı bağımsız değişken olarak alır: Blob::fromContent($content, 'sha256'), Tree::fromEntries($entries, 'sha256'), ObjectId::compute($type, $content, 'sha256'). Pitmaster::clone(), SHA-1 depolar oluşturur.
Tree girdisinin ikili biçimi
Bir tree nesnesinin içeriğinde her girdi şu şekilde kodlanır:
<octal mode as ASCII> <space> <filename> \0 <binary hash: 20 bytes SHA-1, 32 bytes SHA-256>
Not: commit ve tag nesnelerindeki onaltılık özetlerin aksine, özet ham ikili biçimdedir.
Girdiler, dizin adlarının sonunda / varmış gibi adlar karşılaştırılarak sıralanır. Tree özetinin git'in hesaplamasıyla eşleşmesi için bu sıralama tam olarak uygulanmalıdır.