Lewati ke konten

Menulis ke Repositori

Pitmaster menulis repositori git menggunakan format biner yang sama dengan biner git kanonis. Objek ditulis ke penyimpanan objek lepas (terkompresi zlib), index ditulis dalam format v2 (atau v3 jika entri memerlukan flag tambahan; index yang sudah ada mempertahankan versinya), dan ref ditulis sebagai file lepas. Data yang ditulis dapat diverifikasi dengan git fsck --strict.

Menginisialisasi repositori

PHP
use Pitmaster\Pitmaster;

$repo = Pitmaster::init('/path/to/new-project');

Ini membuat:

  • .git/objects/ (penyimpanan objek kosong)
  • .git/refs/heads/ dan .git/refs/tags/ (direktori ref kosong)
  • .git/HEAD yang berisi ref: refs/heads/main
  • .git/hooks/, .git/info/exclude, dan .git/description
  • .git/config dengan pengaturan default

Berikan 'sha256' sebagai argumen kedua untuk membuat repositori SHA-256: Pitmaster::init($path, 'sha256').

Konfigurasi default tidak menetapkan core.logallrefupdates, sehingga Pitmaster tidak mencatat entri reflog di repositori yang dibuatnya sampai Anda menetapkan kunci tersebut ke true (#8). Repositori yang dibuat oleh git init sudah menetapkannya.

Memasukkan file ke staging

add

PHP
$repo->add('src/Feature.php');
$repo->add('src/Feature.php', 'tests/FeatureTest.php', 'README.md');

Setiap argumen adalah path file yang relatif terhadap root working tree. Direktori dan pola glob tidak diperluas, dan file yang tidak ditemukan akan menimbulkan RuntimeException. Untuk setiap file, Pitmaster:

  1. Membaca konten file dari working tree
  2. Membuat objek Blob dan menghitung hash-nya
  3. Menulis blob ke .git/objects/ (terkompresi zlib)
  4. Memperbarui entri index untuk path tersebut dengan hash dan metadata file yang baru

remove

PHP
$repo->remove('old-file.txt');
$repo->remove('-r', 'src');
$repo->remove('--cached', 'old-file.txt');

Menghapus path yang dilacak dari index dan working tree. Gunakan --cached untuk menghapus dari index saja, atau -r / --recursive untuk direktori yang dilacak.

mv

PHP
$repo->mv('old-name.php', 'new-name.php');

Mengganti nama file di working tree, menghapus entri index lama, lalu menambahkan entri baru.

Membuat commit

PHP
$commitId = $repo->commit('Fix null pointer bug');
echo $commitId->hex;

Proses commit:

  1. Bangun tree dari index: daftar datar entri index disusun menjadi hierarki tree (direktori menjadi objek tree, file menjadi referensi blob). Setiap tree ditulis ke penyimpanan objek.
  2. Tentukan induk: commit HEAD saat ini menjadi induknya. Commit root (commit pertama di repo) tidak memiliki induk.
  3. Tentukan author: diambil dari variabel lingkungan PITMASTER_AUTHOR_* dan GIT_AUTHOR_*, lalu konstanta PITMASTER_AUTHOR_NAME/PITMASTER_AUTHOR_EMAIL, kemudian .git/config (user.name/user.email), lalu Pitmaster <pitmaster@localhost>. Identitas committer ditentukan dengan cara yang sama.
  4. Tulis objek commit: konten commit (tree, parent, author, committer, pesan) diserialisasi, di-hash, lalu ditulis.
  5. Perbarui HEAD: ref branch yang ditunjuk HEAD diperbarui ke hash commit baru.

Hook dijalankan di sekitar langkah-langkah ini (pre-commit, prepare-commit-msg, commit-msg, post-commit), kecuali jika handle dibuka dengan ['hooks' => false]. commit() menimbulkan error jika pesan tidak ada, tree tidak berubah dari HEAD, atau index memiliki path yang belum digabung.

Author khusus

PHP
$author = 'Jane Smith <jane@example.com> 1700000000 +0000';
$commitId = $repo->commit('Add feature', $author);

Memverifikasi dengan git fsck

Cakupan integrasi Pitmaster memeriksa objek yang ditulis dengan git fsck --strict, dan Anda dapat memverifikasi hal yang sama secara manual:

Shell
cd /path/to/repo
git fsck --strict

Jika Pitmaster menulis objek yang tidak valid, git fsck akan segera melaporkan kesalahan tersebut.

Mengelola branch

Membuat branch

PHP
// Branch from HEAD
$repo->createBranch('feature/new-thing');

// Branch from a specific commit
$repo->createBranch('hotfix', $repo->resolve('v1.0.0'));

Membuat file ref di .git/refs/heads/<name> yang berisi hash commit target.

Menghapus branch

PHP
$repo->deleteBranch('feature/old');

Beralih branch

PHP
$repo->checkout('feature/login');

Memperbarui HEAD menjadi ref simbolis yang menunjuk ke branch, mengatur ulang index agar sesuai dengan tree ujung branch, lalu memperbarui working tree.

Perubahan lokal pada path yang berbeda di antara kedua tree akan menghentikan checkout dengan RuntimeException. Perubahan yang belum di-commit pada file terlacak lainnya akan diganti dengan konten branch jika git akan mempertahankannya (#2). Commit atau stash perubahan tersebut sebelum beralih.

Memeriksa apakah sudah digabung

PHP
if ($repo->isBranchMerged('feature/done')) {
    $repo->deleteBranch('feature/done');
}

Mengelola tag

Tag ringan

PHP
$repo->createLightweightTag('v1.0.0');                          // At HEAD
$repo->createLightweightTag('v0.9.0', $repo->resolve('HEAD~5'));

Tag ringan hanyalah ref yang langsung menunjuk ke commit.

Tag beranotasi

PHP
$tagId = $repo->createTag('v2.0.0', 'Release version 2.0.0');

Tag beranotasi membuat objek tag (dengan pembuat tag, pesan, dan target) serta ref yang menunjuk ke objek itu. Pembuat tag adalah identitas committer saat ini, yang ditentukan seperti author commit.

Pembuat tag khusus

PHP
$tagId = $repo->createTag(
    'v2.0.0',
    'Release version 2.0.0',
    $repo->resolve('HEAD'),
    'Jane Smith <jane@example.com> 1700000000 +0000',
);

Memperbarui ref secara langsung

PHP
$repo->updateRef('refs/heads/main', $commitId);
$repo->updateRef('refs/tags/latest', $commitId);

Menulis objek secara langsung

Untuk kasus penggunaan lanjutan, Anda dapat menulis objek tanpa melalui API tingkat tinggi.

Menulis blob

PHP
use Pitmaster\Object\Blob;

$blob = Blob::fromContent('Hello, world!');
$id = $repo->writeObject($blob);
echo $id->hex;  // SHA-1 of "blob 13\0Hello, world!"

Dalam repositori SHA-256, jalankan algoritmanya: Blob::fromContent('Hello, world!', 'sha256').

Menulis tree

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

$entries = [
    new TreeEntry('100644', 'README.md', $blobId),
    new TreeEntry('40000', 'src', $subtreeId),
];

$tree = Tree::fromEntries($entries);
$id = $repo->writeObject($tree);

Tree::fromEntries() menulis entri sesuai urutan yang diberikan dan string mode persis seperti yang diberikan. Berikan entri dalam urutan tree git (berdasarkan nama, dengan direktori dibandingkan seolah namanya diakhiri /) dan tulis mode direktori sebagai 40000: git menyimpan mode tree tanpa nol di depan, dan git fsck --strict menolak 040000.

Menulis commit

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

$content = Commit::buildContent(
    tree: $treeId,
    parents: [$parentId],
    author: 'Name <email> 1700000000 +0000',
    committer: 'Name <email> 1700000000 +0000',
    message: "Commit message\n",
);

$commitId = ObjectId::compute(ObjectType::Commit, $content);
$commit = Commit::parse($content, $commitId);
$repo->writeObject($commit);

Reset

PHP
// Soft: move HEAD only
$repo->reset('HEAD~1', 'soft');

// Mixed: move HEAD + reset index (default)
$repo->reset('HEAD~1');

// Hard: move HEAD + reset index + reset working tree
$repo->reset('HEAD~3', 'hard');

Restore

PHP
// Restore a file from the index into the worktree
$repo->restore('src/File.php');

// Restore the index version from HEAD (the worktree is left alone)
$repo->restore('src/File.php', staged: true);

// Restore from a specific commit
$repo->restore('src/File.php', 'HEAD~1');

// Restore both index and worktree from a specific commit
$repo->restore('src/File.php', 'HEAD~1', staged: true, worktree: true);

Cherry-pick dan revert

PHP
// Apply a commit on the current branch
$newId = $repo->cherryPick('feature~1');

// Undo a commit
$revertId = $repo->revert('HEAD~2');

Keduanya menerima revisi apa pun yang diterima resolve(). Hash lengkap dapat digunakan; hash singkat tidak.