
# PHP API

## `Pitmaster\Pitmaster`

Trieda `Pitmaster\Pitmaster` je statickým vstupným bodom. Poskytuje továrenské metódy na otváranie, vytváranie a klonovanie úložísk, ako aj pomocné funkcie na detekciu.

```php
use Pitmaster\Pitmaster;
```

### `open`

```php
public static function open(string $path, array $options = []): Repository
```

Otvorte existujúce úložisko v `$path`. Cesta by mala viesť ku koreňu pracovného stromu (ktorý obsahuje `.git/`). Podporuje aj prepojené pracovné stromy (v ktorých je `.git` súbor obsahujúci `gitdir: <path>`) a holé úložiská (v ktorých je `$path` samotný adresár `.git`).

`$options` prijíma dve logické hodnoty; predvolene sú obe `true`:

- `hooks`: spúšťať skripty `.git/hooks`. Ak ich chcete pre túto inštanciu vynechať, zadajte `false`.
- `processes`: povoliť všetko, čo spúšťa proces alebo otvára sieťový prenos. Ak chcete zakázať hooky, hook fsmonitor, klonovanie, načítavanie, odosielanie a prenos procesov SSH, zadajte `false`. Lokálne čítanie a zápis zostávajú funkčné.

Ak cesta nevedie k úložisku git, vyvolá `InvalidArgumentException`.

```php
$repo = Pitmaster::open('/home/user/project');
$repo = Pitmaster::open('/home/user/project', ['hooks' => false]);
$repo = Pitmaster::open('/home/user/project', Pitmaster::processFreeOptions());
```

### `init`

```php
public static function init(string $path, string $objectFormat = 'sha1', array $options = []): Repository
```

Inicializuje nové úložisko v `$path`. Vytvorí štruktúru adresára `.git` s položkami `objects/`, `refs/heads/`, `refs/tags/`, `hooks/`, `info/`, `HEAD` (s odkazom na `refs/heads/main`) a predvoleným `config`.

`$objectFormat` je `'sha1'` alebo `'sha256'`. Úložisko SHA-256 dostane v konfigurácii `repositoryformatversion = 1` a `extensions.objectformat = sha256`. Každá iná hodnota vyvolá `InvalidArgumentException`. `$options` používa rovnaké kľúče ako `open()`.

Ak už úložisko na tejto ceste existuje, vyvolá `RuntimeException`.

```php
$repo = Pitmaster::init('/home/user/new-project');
$repo = Pitmaster::init('/home/user/sha256-project', 'sha256');
```

### `clone`

```php
public static function clone(string $url, string $path, ?int $depth = null, array $options = []): Repository
```

Naklonuje vzdialené úložisko. Inicializuje nové úložisko, zistí vzdialené odkazy, načíta súbor balíka, nastaví vzdialené sledovacie vetvy a vytvorí pracovný strom. URL SSH (`ssh://...` alebo `user@host:path`) používajú prenos SSH; ostatné URL používajú inteligentný HTTP a pri zlyhaní inteligentnej výmeny prejdú na jednoduchý HTTP. Ak chcete plytké klonovanie, zadajte `$depth`.

Vyvolá `RuntimeException`, keď je `$options['processes']` `false`. Ak klonovanie zlyhá a `$path` predtým neexistoval, čiastočne vytvorený adresár sa odstráni.

```php
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/tmp/repo');
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/tmp/shallow', 1);
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/tmp/repo', null, ['hooks' => false]);
```

### `processFreeOptions`

```php
public static function processFreeOptions(): array
```

Vráti `['processes' => false, 'hooks' => false]` pre prostredia, ktoré nesmú spúšťať procesy hostiteľa. Odovzdajte ho funkcii `open()` alebo `init()`.

### `isRepository`

```php
public static function isRepository(string $path): bool
```

Skontroluje, či cesta vedie k úložisku git. Pre bežné úložiská (adresár `.git/`), prepojené pracovné stromy (súbor `.git`) a holé úložiská (prítomný súbor `HEAD`) vráti `true`.

```php
if (Pitmaster::isRepository('/path/to/check')) {
    // It's a git repo
}
```

### `isWorktree`

```php
public static function isWorktree(string $path): bool
```

Skontroluje, či cesta vedie k prepojenému pracovnému stromu (nie k hlavnému úložisku). Vráti `true` iba vtedy, ak je `.git` súbor obsahujúci odkaz `gitdir:`.

```php
if (Pitmaster::isWorktree('/path/to/worktree')) {
    // It's a linked worktree
}
```

### `commonGitDir`

```php
public static function commonGitDir(string $path): ?string
```

Z ľubovoľnej cesty checkoutu určí spoločný adresár git. Pri bežných úložiskách ide o adresár `.git`. Pri prepojených pracovných stromoch ide o zdieľaný adresár git, ktorý obsahuje objekty, konfiguráciu a packed-refs. Ak cesta nevedie k úložisku, vráti `null`.

```php
$common = Pitmaster::commonGitDir('/path/to/worktree');
// '/path/to/main-repo/.git'
```

---

## `Pitmaster\Repository`

Trieda `Pitmaster\Repository` je hlavnou inštanciou pre všetky operácie git. Získate ju pomocou `Pitmaster::open()`, `Pitmaster::init()` alebo `Pitmaster::clone()`.

```php
use Pitmaster\Repository;
```

### Prístup k cestám

#### `gitDir`

```php
public function gitDir(): string
```

Vráti adresár git konkrétneho pracovného stromu. Pri bežných úložiskách ide o `.git/`. Pri prepojených pracovných stromoch ide o `.git/worktrees/<name>/`.

#### `commonGitDir`

```php
public function commonGitDir(): string
```

Vráti zdieľaný adresár git. Pri bežných úložiskách je rovnaký ako `gitDir()`. Pri prepojených pracovných stromoch ide o adresár `.git/` hlavného úložiska (kde sa nachádzajú objekty, konfigurácia a packed-refs).

#### `workDir`

```php
public function workDir(): string
```

Vráti cestu ku koreňu pracovného stromu.

#### `isLinkedWorktree`

```php
public function isLinkedWorktree(): bool
```

Vráti `true`, ak ide o inštanciu prepojeného pracovného stromu.

#### `isBare`, `hooksEnabled`, `processesEnabled`

```php
public function isBare(): bool
public function hooksEnabled(): bool
public function processesEnabled(): bool
```

Zistí, či úložisko nemá pracovný strom a ktoré z možností `hooks` / `processes` sú pre túto inštanciu aktívne. Keď sú procesy zakázané, `hooksEnabled()` je vždy `false`.

---

### Objekty

#### `readObject`

```php
public function readObject(string $hash): GitObject
```

Načíta ľubovoľný objekt podľa úplného hexadecimálneho hashu (40 znakov alebo 64 v úložisku SHA-256). Skrátené hashe sa neprijímajú. Vráti inštanciu typu `Blob`, `Tree`, `Commit` alebo `Tag`. Najprv prehľadá voľné objekty a potom súbory balíkov.

Ak sa hash nenájde, vyvolá `ObjectNotFoundException`.

```php
$object = $repo->readObject('a1b2c3d4e5f6...');
```

#### `writeObject`

```php
public function writeObject(GitObject $object): ObjectId
```

Zapíše objekt do úložiska voľných objektov. Vráti vypočítaný `ObjectId`.

```php
use Pitmaster\Object\Blob;

$blob = Blob::fromContent('Hello, world!');
$id = $repo->writeObject($blob);
```

#### `catFile`

```php
public function catFile(string $hash): string
```

Vráti nespracovaný obsah objektu, rovnako ako `git cat-file -p`.

```php
echo $repo->catFile('a1b2c3d4...');
```

#### `objectExists`

```php
public function objectExists(string $hash): bool
```

Skontroluje, či objekt v úložisku existuje (medzi voľnými alebo zabalenými objektmi).

#### `listObjects`

```php
public function listObjects(): array
```

Vypíše hashe všetkých objektov v úložisku. Vráti pole hexadecimálnych reťazcov.

---

### Odkazy

#### `head`

```php
public function head(): Commit
```

Vráti aktuálny commit HEAD. Sleduje symbolické odkazy (HEAD -> refs/heads/main -> hash commitu).

Vyvolá `RuntimeException`, ak HEAD neukazuje na platný commit (napríklad e.g, prázdne úložisko).

#### `branch`

```php
public function branch(?string $name = null): ?string
```

Bez argumentov vráti názov aktuálnej vetvy (napríklad e.g, `'main'`) alebo `null`, ak je HEAD odpojený.

Ak zadáte názov vetvy, rozpozná jej hash commitu (hexadecimálny reťazec) alebo vráti `null`, ak vetva neexistuje.

```php
$current = $repo->branch();        // 'main'
$hash = $repo->branch('feature');   // 'abc123...' or null
```

#### `branches`

```php
public function branches(): array
```

Vráti zoradené pole názvov všetkých vetiev (bez predpony `refs/heads/`).

```php
$branches = $repo->branches();
// ['bugfix/typo', 'feature/login', 'main']
```

#### `tags`

```php
public function tags(): array
```

Vráti zoradené pole názvov všetkých značiek (bez predpony `refs/tags/`).

#### `resolve`

```php
public function resolve(string $revision): ObjectId
```

Prevedie výraz revízie na `ObjectId`. Podporuje:
- úplné hexadecimálne hashe (40 znakov alebo 64 pre SHA-256). Skrátené hashe, napríklad `abc1234`, sa nerozpoznajú.
- `HEAD`
- názvy vetiev (`main`, `feature/login`)
- názvy značiek (`v1.0.0`)
- úplné cesty odkazov (`refs/heads/main`)
- výrazy revízií (`HEAD~3`, `main^2`)

Ak sa revíziu nepodarí rozpoznať, vyvolá `RuntimeException`.

```php
$id = $repo->resolve('HEAD~3');
$id = $repo->resolve('v1.0.0');
$id = $repo->resolve('feature/login');
```

#### `allRefs`

```php
public function allRefs(): array
```

Vráti všetky odkazy ako asociatívne pole, ktoré mapuje názvy odkazov na hexadecimálne hashe.

```php
$refs = $repo->allRefs();
// ['refs/heads/main' => 'abc123...', 'refs/tags/v1.0.0' => 'def456...']
```

#### `updateRef`

```php
public function updateRef(string $name, ObjectId $target): void
```

Aktualizuje odkaz tak, aby smeroval na nový cieľ.

```php
$repo->updateRef('refs/heads/main', $commitId);
```

#### `createBranch`

```php
public function createBranch(string $name, ?ObjectId $from = null): void
```

Vytvorí novú vetvu. Ak je `$from` null, vetva sa vytvorí z aktuálneho HEAD.

```php
$repo->createBranch('feature/new-thing');
$repo->createBranch('hotfix', $repo->resolve('v1.0.0'));
```

#### `deleteBranch`

```php
public function deleteBranch(string $name): void
```

Odstráni vetvu podľa názvu. Ak má vetva checkout alebo neexistuje, vyvolá `RuntimeException`. Na rozdiel od `git branch -d` nekontroluje, či je vetva zlúčená.

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

#### `createLightweightTag`

```php
public function createLightweightTag(string $name, ?ObjectId $target = null): void
```

Vytvorí ľahkú značku. Ak je `$target` null, označí priamo aktuálny HEAD.

```php
$repo->createLightweightTag('v2.0.0');
$repo->createLightweightTag('hotfix-start', $repo->resolve('main~2'));
```

#### `createTag`

```php
public function createTag(string $name, string $message, ?ObjectId $target = null, ?string $tagger = null): ObjectId
```

Vytvorí anotovanú značku. Ak je `$target` null, označí aktuálny HEAD. Vráti `ObjectId` objektu značky.

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

#### `deleteTag`

```php
public function deleteTag(string $name): void
```

Odstráni značku podľa názvu.

```php
$repo->deleteTag('v1.0.0');
```

#### `packRefs`

```php
public function packRefs(): void
```

Prepíše zdieľaný súbor `packed-refs` podľa aktuálnej množiny voľných odkazov a odstráni príslušné zdieľané voľné odkazy. Pri prepojených pracovných stromoch zapisuje do spoločného adresára git.

```php
$repo->packRefs();
```

#### `defaultBranch`

```php
public function defaultBranch(): string
```

Určí predvolenú vetvu úložiska. Najprv skontroluje symbolický odkaz vzdialeného HEAD, potom lokálny HEAD a napokon použije `main` alebo `master`.

#### `isBranchMerged`

```php
public function isBranchMerged(string $branch, ?string $target = null): bool
```

Skontroluje, či je vetva úplne zlúčená do inej vetvy (predvolene do predvolenej vetvy).

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

#### `checkout`

```php
public function checkout(string $target): void
```

Prepne vetvy alebo odpojí HEAD. Aktualizuje HEAD, index a pracovný strom. `$target` je názov vetvy, značka, úplný hash alebo výraz revízie; ak nejde o vetvu, HEAD sa odpojí.

Vyvolá `RuntimeException`, ak sa v ceste, ktorá sa líši medzi aktuálnym a cieľovým stromom, nachádza lokálna zmena (pripravená na commit alebo nie) alebo nesledovaný súbor.

Nepotvrdené zmeny v iných sledovaných súboroch sa neprenesú: index a pracovný strom sa znova vytvoria z cieľového stromu, takže úpravy súborov, ktoré sú na oboch stranách totožné, sa stratia. git by ich zachoval ([#2](https://github.com/inline0/pitmaster/issues/2)). Najprv ich potvrďte commitom alebo odložte. Metódy `merge()`, `cherryPick()`, `revert()`, `rebase()` a bisect obnovujú pracovný strom rovnakým spôsobom.

```php
$repo->checkout('feature/login');
$repo->checkout($repo->resolve('v1.0.0')->hex);  // Detached HEAD
```

---

### Index

#### `index`

```php
public function index(): Index
```

Načíta a vráti aktuálny index (oblasť prípravy) z `.git/index`.

#### `add`

```php
public function add(string ...$paths): void
```

Pripraví súbory na commit. Načíta každý súbor z pracovného stromu, vytvorí objekt blob a aktualizuje index. Každý argument musí byť cesta k súboru (alebo symbolickému odkazu) relatívna ku koreňu pracovného stromu; adresáre ani glob vzory sa nerozširujú a pri chýbajúcom súbore vyvolá `RuntimeException`.

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

#### `remove`

```php
public function remove(string ...$paths): void
public function removeCached(string ...$paths): void
```

Odstráni sledované cesty z indexu aj pracovného stromu. V zozname argumentov podporuje `--cached` a `-r` / `--recursive` na dosiahnutie správania v štýle Git.

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

#### `mv`

```php
public function mv(string $source, string $destination): void
```

Presunie/premenuje súbor v pracovnom strome aj indexe.

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

---

### Commity

#### `commit`

```php
public function commit(?string $message = null, ?string $author = null): ObjectId
```

Vytvorí commit z aktuálneho indexu. Zo záznamov indexu zostaví hierarchiu stromov, vytvorí objekt commitu s HEAD ako rodičom (ak existuje) a aktualizuje HEAD. Vráti `ObjectId` nového commitu.

Hodnota `$message` môže byť `null` iba vtedy, keď sa zlučovanie, cherry-pick, revert alebo rebase zastaví pri konflikte; vtedy sa použije pripravená správa. V opačnom prípade správa `null` vyvolá `RuntimeException('Commit message required')`. Commit tiež vyvolá chybu, ak index obsahuje nezlúčené cesty, ak je index prázdny v úložisku bez commitov alebo ak sa strom od HEAD nezmenil.

Parameter `$author` je úplný reťazec autora vo formáte git (`Name <email> timestamp timezone`). Ak je null, určí sa z premenných prostredia, konštánt a `.git/config` v poradí opísanom v časti [Začíname](https://pitmaster.inline0.dev/sk/docs/getting-started).

```php
$id = $repo->commit('Fix null pointer bug');
```

#### `show`

```php
public function show(string $revision): array
```

Zobrazí commit alebo jeho obdobu a rozdiel oproti prvému rodičovi. Keď sa revízia rozpozná ako anotovaná značka, návratová hodnota obsahuje aj `['tag' => Tag]` a `commit` je cieľový commit po rozbalení značky.

```php
$result = $repo->show('HEAD');
echo $result['commit']->message;

foreach ($result['diff'] as $diff) {
    echo $diff->format();
}
```

#### `reset`

```php
public function reset(string $revision, string $mode = 'mixed'): void
```

Resetuje HEAD na commit. Režimy:
- `'soft'`: presunie iba HEAD
- `'mixed'`: presunie HEAD a resetuje index (predvolené)
- `'hard'`: presunie HEAD a resetuje index aj pracovný strom

```php
$repo->reset('HEAD~1', 'soft');
$repo->reset('main', 'hard');
```

#### `restore`

```php
public function restore(string $path, ?string $source = null, bool $staged = false, bool $worktree = false): void
```

Obnoví cestu z indexu alebo zo zadanej zdrojovej revízie. Ak nie je nastavený žiadny príznak, Pitmaster obnoví pracovný strom z indexu (alebo z `$source`, ak je zadaný). `staged: true` obnoví index z HEAD (alebo z `$source`) a pracovný strom ponechá bez zmeny; ak chcete obnoviť oboje, zadajte `staged: true, worktree: true`.

```php
$repo->restore('src/File.php');                                        // Worktree from index
$repo->restore('src/File.php', staged: true);                          // Index from HEAD
$repo->restore('src/File.php', 'HEAD~1');                              // Worktree from another commit
$repo->restore('src/File.php', 'HEAD~1', staged: true, worktree: true); // Index + worktree from another commit
```

#### `cherryPick`

```php
public function cherryPick(string $revision): ObjectId
public function cherryPickContinue(): ObjectId
public function cherryPickAbort(): void
```

Aplikuje commit ako nový commit v aktuálnej vetve a zachová pôvodného autora. Ak sa operácia zastaví pre konflikty, vyriešte ich, pripravte cesty na commit a potom zavolajte `cherryPickContinue()` alebo `cherryPickAbort()`.

```php
$newId = $repo->cherryPick('feature~2');

// After resolving conflicts:
$repo->add('src/File.php');
$repo->cherryPickContinue();
```

#### `revert`

```php
public function revert(string $revision): ObjectId
public function revertContinue(): ObjectId
public function revertAbort(): void
```

Vytvorí commit, ktorý zruší účinok iného commitu. Ak sa revert zastaví pre konflikty, vyriešte ich, pripravte cesty na commit a potom zavolajte `revertContinue()` alebo `revertAbort()`.

```php
$revertId = $repo->revert('HEAD~1');

// After resolving conflicts:
$repo->add('src/File.php');
$repo->revertContinue();
```

#### `rebase`

```php
public function rebase(string $onto): array
public function rebaseContinue(): array
public function rebaseAbort(): void
public function rebaseSkip(): array
```

Rebasuje aktuálnu vetvu na inú revíziu. Pitmaster aktuálne podporuje lineárny rebase so stavom zastavenia pri konfliktoch podľa vzoru Git a tiež pokračovanie, prerušenie a vynechanie. HEAD musí ukazovať na vetvu.

Funkcie `rebase()`, `rebaseContinue()` a `rebaseSkip()` vracajú `['success' => bool, 'commits' => int, 'conflicts' => list<string>]`: informáciu, či sa rebase dokončil, počet aplikovaných commitov a konfliktné cesty, ak sa zastavil.

```php
$result = $repo->rebase('main');

if (!$result['success']) {
    // Resolve conflicts, then continue or skip/abort.
    $repo->add('src/File.php');
    $repo->rebaseContinue();
}
```

---

### Stav

#### `status`

```php
public function status(): array
```

Vypočíta stav pracovného stromu. Vráti pole objektov `StatusEntry`, z ktorých každý obsahuje:
- `path`: cestu k súboru
- `index`: enum `FileStatus` pre zmeny medzi HEAD a indexom
- `worktree`: enum `FileStatus` pre zmeny medzi indexom a pracovným stromom
- `origPath`, `renameScore`: nastavené pre premenované záznamy, inak `null`

Pri nesledovaných súboroch je v oboch stĺpcoch uvedené `FileStatus::Untracked`. Ignorované súbory sa nevypisujú.

```php
foreach ($repo->status() as $entry) {
    echo $entry->shortFormat() . "\n"; // "M  src/File.php", "?? notes.txt"
}
```

#### `statusPorcelainV2`

```php
public function statusPorcelainV2(): string
```

Strojovo čitateľný stavový výstup vo formáte porcelain git v2.

```php
echo $repo->statusPorcelainV2();
// 1 M. N... 000000 000000 000000 0000...0000 0000...0000 modified-file.txt
// ? untracked-file.txt
```

---

### Rozdiel

#### `diff`

```php
public function diff(?string $pathspec = null, string $algorithm = 'myers'): array
```

Porovná pracovný strom s indexom (nezaznamenané zmeny). Vráti pole objektov `DiffResult`. `$pathspec` filtruje podľa jednej presnej cesty k súboru. `$algorithm` je `'myers'` (predvolená hodnota), `'patience'`, `'histogram'` alebo `'minimal'`; akákoľvek iná hodnota vyvolá `InvalidArgumentException`.

```php
$diffs = $repo->diff();

foreach ($diffs as $diff) {
    echo $diff->format();  // Unified diff output
}
```

#### `diffStaged`

```php
public function diffStaged(?string $pathspec = null, string $algorithm = 'myers'): array
```

Porovná index s HEAD (zaznamenané zmeny). Vráti `DiffResult[]`, pričom zisťuje premenovania medzi odstránenými a pridanými súbormi.

Argument `$pathspec` sa momentálne ignoruje, takže sa vrátia všetky súbory v indexe a pred prvým commitom metóda vráti prázdne pole ([#5](https://github.com/inline0/pitmaster/issues/5)).

```php
$staged = $repo->diffStaged();
```

#### `diffTree`

```php
public function diffTree(ObjectId $a, ObjectId $b, string $algorithm = 'myers'): array
```

Porovná dva stromy podľa ich `ObjectId`. Vráti `DiffResult[]`. Zadajte ID stromov, nie ID commitov: ID commitu sa nenačíta ako strom a výsledkom bude prázdny výstup.

```php
$old = $repo->readObject($repo->resolve('HEAD~1')->hex);
$new = $repo->head();
$diffs = $repo->diffTree($old->tree, $new->tree);
```

---

### História

#### `log`

```php
public function log(int $limit = 50, ?ObjectId $from = null): array
```

Prejde históriu commitov od najnovšieho podľa časovej pečiatky autora commitu. Vráti `Commit[]`. Ak je `$from` null, začne od HEAD. Ak HEAD ešte neobsahuje žiadny commit, vráti prázdne pole.

```php
$commits = $repo->log(10);
```

#### `logAll`

```php
public function logAll(int $limit = 50): array
```

Prejde commity dostupné z každého refu a HEAD, od najnovšieho. Vráti `Commit[]`.

#### `logOneline`

```php
public function logOneline(int $limit = 50, bool $all = false, ?string $path = null): array
```

Vráti riadky histórie vo formáte `git log --oneline` (`abc1234 Subject`), od HEAD, zo všetkých refov (`$all`) alebo filtrované podľa cesty.

#### `logPath`

```php
public function logPath(string $path, int $limit = 50): array
```

História filtrovaná podľa cesty k súboru. Vráti iba commity, ktorých rozdiel oproti prvému rodičovi pridáva, upravuje, odstraňuje alebo premenuje daný súbor. Cesty k adresárom sa nezhodujú.

Skúma sa iba najnovších `5 * $limit` commitov, takže vo výsledku môžu chýbať staršie commity, ktoré sa súboru týkajú ([#7](https://github.com/inline0/pitmaster/issues/7)).

```php
$commits = $repo->logPath('src/Repository.php', 20);
```

---

### Zlučovanie

#### `merge`

```php
public function merge(string $branch, string $strategy = 'recursive'): MergeResult
public function mergeOctopus(array $branches): MergeResult
public function mergeContinue(): ObjectId
public function mergeAbort(): void
```

Zlúči vetvu (alebo ľubovoľnú revíziu) do HEAD. Automaticky rozpoznáva zlúčenia typu fast-forward. Pri zlúčeniach, ktoré nie sú typu fast-forward, zisťuje konflikty na úrovni stromu a pri ich absencii vytvorí zlučovací commit. Konflikt zastaví zápis stavu zlúčenia v tvare Git do indexu a pracovného stromu; vyriešte konflikty v cestách, pridajte ich do indexu a potom zavolajte `mergeContinue()` alebo `mergeAbort()`.

`$strategy` `'ours'` zaznamenáva zlučovací commit, ktorý zachováva strom HEAD; každá iná hodnota použije predvolené rekurzívne zlučovanie. `mergeOctopus()` zlúči dve alebo viac vetiev do jedného commitu. Ak dôjde ku konfliktu v ktorejkoľvek vetve, vráti nečistý výsledok bez zápisu stavu zlúčenia a vytvorenia commitu.

Zlúčením vetvy, ktorá už je súčasťou HEAD, vznikne ďalší zlučovací commit namiesto správy „Already up to date“ ([#6](https://github.com/inline0/pitmaster/issues/6)). Nepotvrdené zmeny v sledovaných súboroch sa prepíšu, ako je opísané v časti `checkout()`.

Vráti `MergeResult` s položkami:
- `clean`: informácia, či sa zlúčenie dokončilo bez konfliktov
- `commitId`: ID zlučovacieho commitu (ak prebehlo čisto)
- `conflictPaths`: pole ciest ku konfliktným súborom (ak prebehlo s konfliktmi)
- `mergedContents`: cesta ku konfliktnému súboru s obsahom označeným značkami konfliktu (ak prebehlo s konfliktmi)

```php
$result = $repo->merge('feature/login');

if ($result->clean) {
    echo "Merged: {$result->commitId->hex}\n";
} else {
    echo "Conflicts in: " . implode(', ', $result->conflictPaths) . "\n";
    $repo->add('src/File.php');
    $repo->mergeContinue();
}
```

#### `mergeBase`

```php
public function mergeBase(ObjectId $a, ObjectId $b): ?ObjectId
```

Nájde základňu zlúčenia (najnižšieho spoločného predka) dvoch commitov. Ak neexistuje spoločný predok, vráti null.

```php
$base = $repo->mergeBase(
    $repo->resolve('main'),
    $repo->resolve('feature/login'),
);
```

### Bisekcia

```php
public function bisectStart(string $bad, string $good): ObjectId
public function bisectGood(?string $revision = null): ?ObjectId
public function bisectBad(?string $revision = null): ?ObjectId
public function bisectReset(): void
```

Binárnym vyhľadávaním nájde commit, ktorý zaviedol zmenu. `bisectStart()` zaznamená chybné a dobré revízie, skontroluje prvého kandidáta a vráti ho. Pomocou `bisectGood()` a `bisectBad()` označíte aktuálny HEAD (alebo `$revision`), potom sa skontroluje a vráti ďalší kandidát. Keď zostane jediný podozrivý commit, vráti sa a zostane kandidátom: je to prvý chybný commit. `bisectReset()` ukončí reláciu a vráti sa na vetvu alebo commit, na ktorom sa začala.

```php
$candidate = $repo->bisectStart('HEAD', 'v1.0.0');
// test $candidate ...
$candidate = $repo->bisectBad();
$candidate = $repo->bisectGood();
$repo->bisectReset();
```

---

### Sieť

#### `fetch`

```php
public function fetch(string $remote = 'origin', ?int $depth = null): void
```

Načíta zmeny zo vzdialeného úložiska. Stiahne nové objekty a aktualizuje refy sledovania vzdialených vetiev. Zadajte `$depth` na prehĺbenie alebo obmedzenie plytkej histórie.

`fetch()` a metódy `push*()` vyvolajú `RuntimeException` pri spracovaní deskriptora otvoreného pomocou `['processes' => false]`.

```php
$repo->fetch();
$repo->fetch('upstream');
```

#### `push`

```php
public function push(string $remote = 'origin', ?string $branch = null): void
public function pushForceWithLease(string $remote = 'origin', ?string $branch = null, ?ObjectId $expected = null): void
public function pushAtomic(string $remote = 'origin', array $branches = []): void
public function pushMirror(string $remote = 'origin'): void
```

Odošle aktuálnu vetvu (alebo zadanú vetvu) do vzdialeného úložiska. K dispozícii sú varianty force-with-lease, atomic a mirror na prísnejšiu alebo širšiu aktualizáciu refov.

```php
$repo->push();
$repo->push('origin', 'feature/login');
$repo->pushForceWithLease('origin', 'main', $repo->resolve('refs/remotes/origin/main'));
$repo->pushAtomic('origin', ['main', 'release']);
$repo->pushMirror();
```

---

### Pracovné stromy

#### `addWorktree`

```php
public function addWorktree(string $path, string $branch, ?ObjectId $from = null, ?string $name = null): Worktree
```

Pridá prepojený pracovný strom. Ak vetva neexistuje, vytvorí ju, nastaví metadáta pracovného stromu a vytvorí súbory pracovného stromu. Zadajte `$name`, ak potrebujete deterministický identifikátor metadát odlišný od názvu adresára checkoutu.

```php
$wt = $repo->addWorktree('/tmp/review', 'feature/review');
$wt = $repo->addWorktree('/tmp/checkouts/review', 'feature/review', name: 'review-wt');
```

#### `removeWorktree`

```php
public function removeWorktree(string $pathOrName, bool $force = false): void
```

Odstráni prepojený pracovný strom. Pomocou `$force = true` ho odstránite aj v prípade, že je uzamknutý.

#### `worktrees`

```php
public function worktrees(): array
```

Vypíše všetky pracovné stromy (hlavný aj prepojené). Vráti `Worktree[]`.

```php
foreach ($repo->worktrees() as $wt) {
    echo "{$wt->path} [{$wt->branch}]\n";
}
```

---

### Konfigurácia

#### `config`

```php
public function config(): GitConfig
```

Pristupuje ku konfigurácii git úložiska. Číta a zapisuje konfiguračné hodnoty.

```php
$config = $repo->config();
$name = $config->get('user.name');
$config->set('user.email', 'new@example.com');
```

---

### Interný prístup

Tieto metódy sprístupňujú interné komponenty na pokročilé použitie.

#### `objectDatabase`

```php
public function objectDatabase(): ObjectDatabase
```

Pristupuje k surovej databáze objektov (voľné objekty a balíky).

#### `refDatabase`

```php
public function refDatabase(): RefDatabase
```

Pristupuje k surovej databáze refov (voľné a zabalené refy).

---

## Triedy nižšej úrovne

Tieto triedy nie sú obalené v `Repository` a vytvárajú sa z jeho interných komponentov.

### `Pitmaster\Graph\Blame`

```php
public function blame(ObjectId $headId, string $path): array
```

Vráti jednu položku na každý riadok `$path` v `$headId`: `['line' => int, 'hash' => string, 'author' => string, 'content' => string]`. `author` je úplný reťazec identity (`Name <email> timestamp timezone`).

```php
use Pitmaster\Graph\Blame;

$blame = new Blame($repo->objectDatabase());

foreach ($blame->blame($repo->resolve('HEAD'), 'src/File.php') as $line) {
    echo substr($line['hash'], 0, 8) . " {$line['content']}\n";
}
```

### `Pitmaster\Graph\Grep`

```php
public function grep(ObjectId $treeId, string $pattern, string $prefix = '', array $options = []): array
```

Vyhľadáva v bloboch stromu. Vráti `['path' => string, 'line' => int, 'content' => string]` pre každý zodpovedajúci riadok. Možnosti: `regex` (považuje vzor za vzor PCRE) a `ignore_case`. Neplatný regulárny výraz vyvolá `InvalidArgumentException`.

```php
use Pitmaster\Graph\Grep;

$grep = new Grep($repo->objectDatabase());
$matches = $grep->grep($repo->head()->tree, 'TODO', '', ['ignore_case' => true]);
```

### `Pitmaster\Ref\Notes`

```php
public function get(ObjectId $commitId, string $notesRef = 'refs/notes/commits'): ?string
public function set(ObjectId $commitId, string $noteContent, string $notesRef = 'refs/notes/commits'): void
public function remove(ObjectId $commitId, string $notesRef = 'refs/notes/commits'): void
public function listAll(string $notesRef = 'refs/notes/commits'): array
public function merge(string $sourceRef, string $targetRef = 'refs/notes/commits'): void
```

Číta a zapisuje poznámky git uložené pod refom poznámok. `listAll()` vracia hash commitu k obsahu poznámky.

```php
use Pitmaster\Ref\Notes;

$notes = new Notes($repo->objectDatabase(), $repo->refDatabase());
$notes->set($repo->resolve('HEAD'), "Reviewed\n");
echo $notes->get($repo->resolve('HEAD'));
```
