Membaca Repositori
Pitmaster membaca repositori git dengan mengurai format di disk secara langsung: objek lepas (file terkompresi zlib di .git/objects/), file pack (.git/objects/pack/), ref (file di .git/refs/ dan packed-refs), serta index (.git/index).
Membuka repositori
use Pitmaster\Pitmaster;
$repo = Pitmaster::open('/path/to/project');
Pitmaster mendukung tiga tata letak repositori:
- Repositori reguler:
.gitadalah direktori di root proyek. - Worktree tertaut:
.gitadalah file yang berisigitdir: <path>yang menunjuk ke.git/worktrees/<name>/. - Repositori bare: path itu sendiri berisi
HEAD,objects/, dan seterusnya.
// Detection helpers
Pitmaster::isRepository('/path'); // true for any of the above
Pitmaster::isWorktree('/path'); // true only for linked worktrees
Membaca objek
Setiap data dalam repositori git disimpan sebagai objek yang diidentifikasi oleh hash-nya: SHA-1 (40 karakter heksadesimal) sebagai default, atau SHA-256 (64 karakter heksadesimal) di repositori yang dibuat dengan Pitmaster::init($path, 'sha256'). Ada empat jenis objek: blob, tree, commit, dan tag.
Metode berbasis hash di bawah ini menerima hash heksadesimal lengkap; hash singkat tidak diterima.
readObject
use Pitmaster\Object\Blob;
use Pitmaster\Object\Tree;
use Pitmaster\Object\Commit;
use Pitmaster\Object\Tag;
$object = $repo->readObject('a1b2c3d4e5f6...');
match (true) {
$object instanceof Blob => handleBlob($object),
$object instanceof Tree => handleTree($object),
$object instanceof Commit => handleCommit($object),
$object instanceof Tag => handleTag($object),
};
Objek dicari terlebih dahulu di penyimpanan lepas, lalu di file pack. Pencarian file pack menggunakan tabel fanout .idx untuk pencarian biner O(log n).
catFile
Untuk mengambil konten secara sederhana tanpa pemeriksaan jenis:
$content = $repo->catFile('a1b2c3d4e5f6...');
echo $content;
objectExists
if ($repo->objectExists('a1b2c3d4e5f6...')) {
// Object is in the repository
}
listObjects
$hashes = $repo->listObjects();
// ['a1b2c3d4...', 'f6e5d4c3...', ...]
Mengembalikan hash heksadesimal untuk semua objek (lepas dan yang dikemas).
Bekerja dengan blob
Blob menyimpan konten file mentah.
$blob = $repo->readObject($hash);
echo $blob->content; // Raw file bytes
echo $blob->size(); // Content length
echo $blob->id->hex; // Object hash
Bekerja dengan tree
Tree adalah daftar direktori. Setiap entri memiliki mode, nama, dan hash.
$tree = $repo->readObject($hash);
foreach ($tree->entries as $entry) {
echo "{$entry->mode} {$entry->name} {$entry->hash->hex}\n";
// 100644 README.md abc123...
// 40000 src def456...
// 100755 deploy.sh 789012...
if ($entry->isTree()) {
// Recurse into subdirectory (mode 40000)
} elseif ($entry->isExecutable()) {
// Executable file (mode 100755)
} elseif ($entry->isBlob()) {
// Regular file (any 10xxxx mode, so executables match too)
} elseif ($entry->isSymlink()) {
// Symbolic link (mode 120000)
} elseif ($entry->isGitlink()) {
// Submodule (mode 160000)
}
}
Bekerja dengan commit
Commit menghubungkan snapshot tree dengan induk dan metadatanya.
$commit = $repo->head();
echo $commit->id->hex; // Full object hash
echo $commit->tree->hex; // Tree object hash
echo $commit->author; // "Name <email> timestamp tz"
echo $commit->committer; // "Name <email> timestamp tz"
echo $commit->message; // Full commit message
// Parent commits
foreach ($commit->parents as $parentId) {
$parent = $repo->readObject($parentId->hex);
}
// Merge detection
if ($commit->isMerge()) {
// Two or more parents
}
Bekerja dengan tag
Tag beranotasi adalah objek yang berisi target, jenis, nama, pembuat tag, dan pesan.
$tag = $repo->readObject($hash);
echo $tag->object->hex; // Target object hash
echo $tag->objectType->value; // 'commit', 'tree', 'blob', or 'tag'
echo $tag->name; // Tag name
echo $tag->tagger; // "Name <email> timestamp tz"
echo $tag->message; // Tag message
Membaca ref
HEAD saat ini
$commit = $repo->head();
Menyelesaikan HEAD (dengan mengikuti ref simbolis seperti HEAD -> refs/heads/main -> commit hash) dan mengembalikan objek commit.
Branch saat ini
$branch = $repo->branch(); // 'main' or null if detached
Mencantumkan branch dan tag
$branches = $repo->branches(); // ['bugfix/typo', 'feature/login', 'main']
$tags = $repo->tags(); // ['v1.0.0', 'v1.1.0']
Semua ref
$refs = $repo->allRefs();
// [
// 'refs/heads/main' => 'abc123...',
// 'refs/heads/feature' => 'def456...',
// 'refs/tags/v1.0.0' => '789012...',
// 'refs/remotes/origin/main' => 'abc123...',
// ]
Menyelesaikan revisi
$id = $repo->resolve('HEAD');
$id = $repo->resolve('main');
$id = $repo->resolve('v1.0.0');
$id = $repo->resolve('HEAD~3');
$id = $repo->resolve('main^2');
$id = $repo->resolve('3f2c1e0b9d6a4f8e7c5b2a1d0e9f8c7b6a5d4e3f');
Parser revisi mendukung operator ~N (leluhur) dan ^N (induk), yang dapat dirangkai tanpa batas. Hash harus diberikan secara lengkap.
Menelusuri riwayat commit
log
Commit dikembalikan dari yang terbaru terlebih dahulu, diurutkan berdasarkan stempel waktu committer.
// Last 20 commits from HEAD
$commits = $repo->log(20);
foreach ($commits as $commit) {
$short = substr($commit->id->hex, 0, 7);
echo "{$short} {$commit->message}\n";
}
log dari commit tertentu
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);
log yang difilter berdasarkan path file
$commits = $repo->logPath('src/Repository.php', 20);
Hanya mengembalikan commit yang mengubah file yang ditentukan (ditambahkan, diubah, dihapus, atau diganti namanya) dibandingkan dengan induk pertama. Path harus berupa path file yang persis; direktori tidak cocok. Hanya 5 * $limit commit terbaru yang diperiksa, sehingga kecocokan yang lebih lama mungkin tidak ditemukan (#7).
show
$result = $repo->show('HEAD');
$commit = $result['commit'];
$diffs = $result['diff'];
echo "Author: {$commit->author}\n";
echo "Message: {$commit->message}\n\n";
foreach ($diffs as $diff) {
echo $diff->format();
}
Deteksi branch default
$default = $repo->defaultBranch();
// Checks: remote HEAD symref -> local HEAD -> main/master fallback
Saat remote.origin.url ditetapkan dan proses diaktifkan, pemeriksaan pertama mengirim permintaan HTTP yang cerdas ke remote. Kesalahan jaringan diabaikan dan pemeriksaan lokal dilanjutkan.
Ancestry penggabungan
// Is feature fully merged into main?
$merged = $repo->isBranchMerged('feature/done', 'main');
// Find the merge base of two commits
$base = $repo->mergeBase(
$repo->resolve('main'),
$repo->resolve('feature/login'),
);