Zápis do repozitářů
Pitmaster zapisuje repozitáře git ve stejných binárních formátech jako kanonický binární soubor git. Objekty se zapisují do úložiště volných objektů (komprimované pomocí zlib), index se zapisuje ve formátu v2 (nebo v3, pokud položky vyžadují rozšířené příznaky; stávající index si zachová svou verzi) a reference se zapisují jako volné soubory. Zapsaná data lze ověřit pomocí git fsck --strict.
Inicializace repozitáře
use Pitmaster\Pitmaster;
$repo = Pitmaster::init('/path/to/new-project');
Tím se vytvoří:
.git/objects/(prázdné úložiště objektů).git/refs/heads/a.git/refs/tags/(prázdné adresáře referencí).git/HEADobsahujícíref: refs/heads/main.git/hooks/,.git/info/excludea.git/description.git/configs výchozím nastavením
Předejte 'sha256' jako druhý argument a vytvořte SHA-256 repozitář: Pitmaster::init($path, 'sha256').
Výchozí konfigurace nenastavuje core.logallrefupdates, takže Pitmaster do vytvořeného repozitáře nezaznamenává žádné položky reflogu, dokud tento klíč nenastavíte na true (#8). Repozitáře vytvořené pomocí git init už tuto hodnotu nastavenou mají.
Příprava souborů
add
$repo->add('src/Feature.php');
$repo->add('src/Feature.php', 'tests/FeatureTest.php', 'README.md');
Každý argument je cesta k souboru vztažená ke kořenovému adresáři pracovního stromu. Adresáře a glob vzory se nerozbalují a při chybějícím souboru se vyvolá RuntimeException. U každého souboru Pitmaster:
- Načte obsah souboru z pracovního stromu
- Vytvoří objekt
Bloba vypočítá jeho hash - Zapíše blob do
.git/objects/(komprimovaný pomocí zlib) - Aktualizuje položku indexu pro danou cestu novým hashem a metadaty souboru
remove
$repo->remove('old-file.txt');
$repo->remove('-r', 'src');
$repo->remove('--cached', 'old-file.txt');
Odebere sledované cesty z indexu i pracovního stromu. Pro odebrání pouze z indexu použijte --cached, pro sledované adresáře pak -r / --recursive.
mv
$repo->mv('old-name.php', 'new-name.php');
Přejmenuje soubor v pracovním stromu, odebere starou položku z indexu a přidá novou.
Vytváření potvrzení
$commitId = $repo->commit('Fix null pointer bug');
echo $commitId->hex;
Postup vytvoření potvrzení:
- Vytvoření stromu z indexu: plochý seznam položek indexu se uspořádá do hierarchie stromů (adresáře se stanou objekty stromu, soubory odkazy na bloby). Každý strom se zapíše do úložiště objektů.
- Určení rodiče: aktuální potvrzení HEAD se stane rodičem. Kořenová potvrzení (první potvrzení v repozitáři) žádné rodiče nemají.
- Určení autora: převezme se z proměnných prostředí
PITMASTER_AUTHOR_*aGIT_AUTHOR_*, poté z konstantPITMASTER_AUTHOR_NAME/PITMASTER_AUTHOR_EMAIL, dále z.git/config(user.name/user.email) a nakonec zPitmaster <pitmaster@localhost>. Stejným způsobem se určí autor potvrzení. - Zápis objektu potvrzení: obsah potvrzení (
tree,parent,author,committer, zpráva) se serializuje, zahashuje a zapíše. - Aktualizace HEAD: reference větve, na kterou HEAD ukazuje, se aktualizuje na nový hash potvrzení.
Před těmito kroky a po nich se spouštějí hooky (pre-commit, prepare-commit-msg, commit-msg, post-commit), pokud úchyt nebyl otevřen pomocí ['hooks' => false]. commit() vyvolá chybu, pokud chybí zpráva, strom se od HEAD nezměnil nebo index obsahuje nesloučené cesty.
Vlastní autor
$author = 'Jane Smith <jane@example.com> 1700000000 +0000';
$commitId = $repo->commit('Add feature', $author);
Ověření pomocí git fsck
Integrační testy Pitmaster ověřují zapsané objekty pomocí git fsck --strict; totéž můžete ověřit ručně:
cd /path/to/repo
git fsck --strict
Pokud Pitmaster zapíše neplatný objekt, git fsck chybu ihned ohlásí.
Správa větví
Vytvoření větve
// Branch from HEAD
$repo->createBranch('feature/new-thing');
// Branch from a specific commit
$repo->createBranch('hotfix', $repo->resolve('v1.0.0'));
Vytvoří soubor reference v .git/refs/heads/<name> obsahující hash cílového potvrzení.
Smazání větve
$repo->deleteBranch('feature/old');
Přepínání větví
$repo->checkout('feature/login');
Aktualizuje HEAD na symbolickou referenci ukazující na větev, resetuje index podle stromu na konci větve a aktualizuje pracovní strom.
Místní změny v cestách, které se mezi oběma stromy liší, zabrání přepnutí větve pomocí RuntimeException. Nepotvrzené změny ve všech ostatních sledovaných souborech se nahradí obsahem větve, kde by je git zachoval (#2). Před přepnutím je potvrďte nebo uložte do stash.
Ověření, zda byla změna sloučena
if ($repo->isBranchMerged('feature/done')) {
$repo->deleteBranch('feature/done');
}
Správa tagů
Lehký tag
$repo->createLightweightTag('v1.0.0'); // At HEAD
$repo->createLightweightTag('v0.9.0', $repo->resolve('HEAD~5'));
Lehký tag je pouze reference, která ukazuje přímo na commit.
Anotovaný tag
$tagId = $repo->createTag('v2.0.0', 'Release version 2.0.0');
Anotovaný tag vytvoří objekt tagu (s označující osobou, zprávou a cílem) a referenci, která na něj ukazuje. Označující osoba je identita aktuálního committera určená stejně jako autor commitu.
Vlastní označující osoba
$tagId = $repo->createTag(
'v2.0.0',
'Release version 2.0.0',
$repo->resolve('HEAD'),
'Jane Smith <jane@example.com> 1700000000 +0000',
);
Přímá aktualizace referencí
$repo->updateRef('refs/heads/main', $commitId);
$repo->updateRef('refs/tags/latest', $commitId);
Přímý zápis objektů
V pokročilých případech použití můžete zapisovat objekty bez využití vysokoúrovňového API.
Zápis blobu
use Pitmaster\Object\Blob;
$blob = Blob::fromContent('Hello, world!');
$id = $repo->writeObject($blob);
echo $id->hex; // SHA-1 of "blob 13\0Hello, world!"
V repozitáři SHA-256 předejte algoritmus: Blob::fromContent('Hello, world!', 'sha256').
Zápis stromu
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() zapisuje položky v zadaném pořadí a řetězce režimů přesně podle zadání. Předejte je v pořadí stromu git (podle názvu, přičemž adresáře se porovnávají, jako by jejich název končil na /) a režimy adresářů zapište jako 40000: git ukládá režimy stromů bez úvodní nuly a git fsck --strict odmítá 040000.
Zápis commitu
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
// 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');
Obnovení
// 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 a revert
// Apply a commit on the current branch
$newId = $repo->cherryPick('feature~1');
// Undo a commit
$revertId = $repo->revert('HEAD~2');
Obě operace přijímají libovolnou revizi, kterou podporuje resolve(). Úplné hashe fungují, zkrácené nikoli.