Přejít k obsahu

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

PHP
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/HEAD obsahující ref: refs/heads/main
  • .git/hooks/, .git/info/exclude a .git/description
  • .git/config s 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

PHP
$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:

  1. Načte obsah souboru z pracovního stromu
  2. Vytvoří objekt Blob a vypočítá jeho hash
  3. Zapíše blob do .git/objects/ (komprimovaný pomocí zlib)
  4. Aktualizuje položku indexu pro danou cestu novým hashem a metadaty souboru

remove

PHP
$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

PHP
$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í

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

Postup vytvoření potvrzení:

  1. 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ů.
  2. Určení rodiče: aktuální potvrzení HEAD se stane rodičem. Kořenová potvrzení (první potvrzení v repozitáři) žádné rodiče nemají.
  3. Určení autora: převezme se z proměnných prostředí PITMASTER_AUTHOR_* a GIT_AUTHOR_*, poté z konstant PITMASTER_AUTHOR_NAME/PITMASTER_AUTHOR_EMAIL, dále z .git/config (user.name/user.email) a nakonec z Pitmaster <pitmaster@localhost>. Stejným způsobem se určí autor potvrzení.
  4. Zápis objektu potvrzení: obsah potvrzení (tree, parent, author, committer, zpráva) se serializuje, zahashuje a zapíše.
  5. 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

PHP
$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ě:

Shell
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

PHP
// 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

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

Přepínání větví

PHP
$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

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

Správa tagů

Lehký tag

PHP
$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

PHP
$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

PHP
$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í

PHP
$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

PHP
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

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() 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

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');

Obnovení

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 a revert

PHP
// 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.