Scrierea în depozite
Pitmaster scrie depozite git folosind aceleași formate binare ca binarul canonic git. Obiectele sunt scrise în depozitul de obiecte libere (comprimate cu zlib), indexul este scris în format v2 (sau v3 când intrările necesită marcaje extinse; un index existent își păstrează versiunea), iar referințele sunt scrise ca fișiere libere. Datele scrise pot fi verificate cu git fsck --strict.
Inițializarea unui depozit
use Pitmaster\Pitmaster;
$repo = Pitmaster::init('/path/to/new-project');
Aceasta creează:
.git/objects/(depozit de obiecte gol).git/refs/heads/și.git/refs/tags/(directoare de referințe goale).git/HEADcare conțineref: refs/heads/main.git/hooks/,.git/info/excludeși.git/description.git/configcu setările implicite
Transmiteți 'sha256' ca al doilea argument pentru a crea un depozit SHA-256: Pitmaster::init($path, 'sha256').
Configurația implicită nu setează core.logallrefupdates, așa că Pitmaster nu înregistrează nicio intrare reflog în depozitul pe care l-a creat până când nu setați acea cheie la true (#8). Depozitele create de git init o au deja setată.
Adăugarea fișierelor în zona de pregătire
add
$repo->add('src/Feature.php');
$repo->add('src/Feature.php', 'tests/FeatureTest.php', 'README.md');
Fiecare argument este o cale de fișier relativă la rădăcina arborelui de lucru. Directoarele și modelele glob nu sunt extinse, iar un fișier lipsă generează RuntimeException. Pentru fiecare fișier, Pitmaster:
- Citește conținutul fișierului din arborele de lucru
- Creează un obiect
Blobși îi calculează hashul - Scrie blobul în
.git/objects/(comprimat cu zlib) - Actualizează intrarea din index pentru calea respectivă cu noul hash și metadatele fișierului
remove
$repo->remove('old-file.txt');
$repo->remove('-r', 'src');
$repo->remove('--cached', 'old-file.txt');
Elimină căile urmărite din index și din arborele de lucru. Folosiți --cached pentru eliminarea doar din index sau -r / --recursive pentru directoare urmărite.
mv
$repo->mv('old-name.php', 'new-name.php');
Redenumește fișierul în arborele de lucru, elimină vechea intrare din index și o adaugă pe cea nouă.
Crearea commiturilor
$commitId = $repo->commit('Fix null pointer bug');
echo $commitId->hex;
Procesul de creare a commitului:
- Construirea arborelui din index: lista plată de intrări din index este organizată într-o ierarhie de arbori (directoarele devin obiecte arbore, iar fișierele, referințe către bloburi). Fiecare arbore este scris în depozitul de obiecte.
- Determinarea părintelui: commitul HEAD curent devine părintele. Commiturile rădăcină (primul commit dintr-un depozit) nu au părinți.
- Determinarea autorului: preluat din variabilele de mediu
PITMASTER_AUTHOR_*șiGIT_AUTHOR_*, apoi din constantelePITMASTER_AUTHOR_NAME/PITMASTER_AUTHOR_EMAIL, apoi din.git/config(user.name/user.email), apoi dinPitmaster <pitmaster@localhost>. Identitatea autorului commitului este rezolvată în același mod. - Scrierea obiectului commit: conținutul commitului (
tree,parent,author,committer, mesajul) este serializat, i se calculează hashul și este scris. - Actualizarea HEAD: referința ramurii către care indică HEAD este actualizată cu noul hash al commitului.
Hookurile rulează în jurul acestor pași (pre-commit, prepare-commit-msg, commit-msg, post-commit), cu excepția cazului în care handle-ul a fost deschis cu ['hooks' => false]. commit() generează o eroare dacă lipsește mesajul, dacă arborele este neschimbat față de HEAD sau dacă indexul conține căi necomasate.
Autor personalizat
$author = 'Jane Smith <jane@example.com> 1700000000 +0000';
$commitId = $repo->commit('Add feature', $author);
Verificarea cu fsck din git
Testele de integrare ale Pitmaster verifică obiectele scrise în raport cu git fsck --strict, iar dumneavoastră le puteți verifica și manual:
cd /path/to/repo
git fsck --strict
Dacă Pitmaster scrie un obiect invalid, git fsck va raporta imediat eroarea.
Gestionarea ramurilor
Crearea unei ramuri
// Branch from HEAD
$repo->createBranch('feature/new-thing');
// Branch from a specific commit
$repo->createBranch('hotfix', $repo->resolve('v1.0.0'));
Creează un fișier de referință în .git/refs/heads/<name> care conține hashul commitului țintă.
Ștergerea unei ramuri
$repo->deleteBranch('feature/old');
Schimbarea ramurilor
$repo->checkout('feature/login');
Actualizează HEAD cu o referință simbolică către ramură, resetează indexul pentru a corespunde arborelui de la vârful ramurii și actualizează arborele de lucru.
Modificările locale din căile care diferă între cei doi arbori opresc operația de checkout cu o RuntimeException. Modificările necomise din toate celelalte fișiere urmărite sunt înlocuite cu conținutul ramurii, pe care git le-ar păstra (#2). Comiteți-le sau puneți-le deoparte înainte de a schimba ramura.
Verificarea dacă a fost comasată
if ($repo->isBranchMerged('feature/done')) {
$repo->deleteBranch('feature/done');
}
Gestionarea etichetelor
Etichetă simplă
$repo->createLightweightTag('v1.0.0'); // At HEAD
$repo->createLightweightTag('v0.9.0', $repo->resolve('HEAD~5'));
O etichetă simplă este doar o referință care indică direct către un commit.
Etichetă adnotată
$tagId = $repo->createTag('v2.0.0', 'Release version 2.0.0');
O etichetă adnotată creează un obiect etichetă (cu autorul etichetei, un mesaj și o țintă) și o referință către acesta. Identitatea autorului etichetei este cea a autorului commitului curent, rezolvată la fel ca autorul commitului.
Autor personalizat al etichetei
$tagId = $repo->createTag(
'v2.0.0',
'Release version 2.0.0',
$repo->resolve('HEAD'),
'Jane Smith <jane@example.com> 1700000000 +0000',
);
Actualizarea directă a referințelor
$repo->updateRef('refs/heads/main', $commitId);
$repo->updateRef('refs/tags/latest', $commitId);
Scrierea directă a obiectelor
Pentru cazuri de utilizare avansate, puteți scrie obiecte fără a trece prin interfața de nivel înalt API.
Scrierea unui blob
use Pitmaster\Object\Blob;
$blob = Blob::fromContent('Hello, world!');
$id = $repo->writeObject($blob);
echo $id->hex; // SHA-1 of "blob 13\0Hello, world!"
Într-un depozit SHA-256, transmiteți algoritmul: Blob::fromContent('Hello, world!', 'sha256').
Scrierea unui arbore
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() scrie intrările în ordinea furnizată și șirurile de mod în forma furnizată. Transmiteți-le în ordinea arborilor din git (după nume, comparând directoarele ca și cum numele lor s-ar termina în /) și scrieți modurile directoarelor ca 40000: git stochează modurile arborilor fără zero-ul de la început, iar git fsck --strict respinge 040000.
Scrierea unui commit
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);
Resetare
// 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');
Restaurare
// 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 și revert
// Apply a commit on the current branch
$newId = $repo->cherryPick('feature~1');
// Undo a commit
$revertId = $repo->revert('HEAD~2');
Ambele acceptă orice revizie acceptată de resolve(). Hashurile complete funcționează; cele abreviate nu.