
# PHP API

## `Pitmaster\Pitmaster`

Razred `Pitmaster\Pitmaster` je statična vstopna točka. Ponuja tovarniške metode za odpiranje, ustvarjanje in kloniranje repozitorijev ter pomočnike za zaznavanje.

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

### `open`

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

Odprite obstoječi repozitorij na poti `$path`. Pot mora biti koren delovnega drevesa (vsebuje `.git/`). Podprte so tudi povezane delovne kopije (kjer je `.git` datoteka, ki vsebuje `gitdir: <path>`) in goli repozitoriji (kjer je `$path` sam imenik `.git`).

`$options` sprejema dve logični vrednosti; obe sta privzeto `true`:

- `hooks`: zažene skripte `.git/hooks`. Podajte `false`, da jih za ta ročaj preskočite.
- `processes`: dovoli vse, kar zažene proces ali odpre omrežni transport. Podajte `false`, da onemogočite kljuke, kljuko fsmonitor, kloniranje, prenos, pošiljanje in transport procesov SSH. Lokalno branje in pisanje še naprej delujeta.

Sproži `InvalidArgumentException`, če pot ni repozitorij git.

```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
```

Inicializirajte nov repozitorij na poti `$path`. Ustvari strukturo imenika `.git` z elementi `objects/`, `refs/heads/`, `refs/tags/`, `hooks/`, `info/`, `HEAD` (ki kaže na `refs/heads/main`) in privzetim `config`.

`$objectFormat` je `'sha1'` ali `'sha256'`. Repozitorij SHA-256 dobi v konfiguraciji `repositoryformatversion = 1` in `extensions.objectformat = sha256`. Vsaka druga vrednost sproži `InvalidArgumentException`. `$options` sprejema iste ključe kot `open()`.

Sproži `RuntimeException`, če na poti že obstaja repozitorij.

```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
```

Klonirajte oddaljeni repozitorij. Inicializira nov repozitorij, odkrije oddaljene reference, prenese paketno datoteko, nastavi veje za sledenje oddaljenim vejam in ustvari delovno drevo. URL-ji SSH (`ssh://...` ali `user@host:path`) uporabljajo transport SSH; drugi URL-ji uporabljajo pametni HTTP in ob neuspešni pametni izmenjavi preidejo na preprosti HTTP. Za plitvo kloniranje podajte `$depth`.

Sproži `RuntimeException`, ko je `$options['processes']` `false`. Če kloniranje ne uspe in `$path` prej ni obstajal, se delno ustvarjeni imenik odstrani.

```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
```

Vrne `['processes' => false, 'hooks' => false]` za izvajalna okolja, ki ne smejo zagnati gostiteljskih procesov. Podajte ga metodi `open()` ali `init()`.

### `isRepository`

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

Preverite, ali je pot repozitorij git. Za običajne repozitorije vrne `true` (imenik `.git/`), povezane delovne kopije (datoteka `.git`) in gole repozitorije (če je prisotna datoteka `HEAD`).

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

### `isWorktree`

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

Preverite, ali je pot povezana delovna kopija (ne glavni repozitorij). Vrne `true` samo, če je `.git` datoteka, ki vsebuje referenco `gitdir:`.

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

### `commonGitDir`

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

Razrešite pot do skupnega imenika git iz katere koli poti izpisa. Pri običajnih repozitorijih je to imenik `.git`. Pri povezanih delovnih kopijah je to skupni imenik git, ki vsebuje objekte, konfiguracijo in packed-refs. Če pot ni repozitorij, vrne `null`.

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

---

## `Pitmaster\Repository`

Razred `Pitmaster\Repository` je glavni ročaj za vse operacije git. Pridobite ga z metodo `Pitmaster::open()`, `Pitmaster::init()` ali `Pitmaster::clone()`.

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

### Dostopniki poti

#### `gitDir`

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

Vrne imenik git za posamezno delovno kopijo. Pri običajnih repozitorijih je to `.git/`. Pri povezanih delovnih kopijah je to `.git/worktrees/<name>/`.

#### `commonGitDir`

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

Vrne skupni imenik git. Pri običajnih repozitorijih je enak `gitDir()`. Pri povezanih delovnih kopijah je to imenik `.git/` glavnega repozitorija (v njem so objekti, konfiguracija in packed-refs).

#### `workDir`

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

Vrne pot do korena delovnega drevesa.

#### `isLinkedWorktree`

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

Vrne `true`, če je ta ročaj repozitorija povezana delovna kopija.

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

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

Poroča, ali repozitorij nima delovnega drevesa in kateri možnosti `hooks` / `processes` veljata za ta ročaj. `hooksEnabled()` je `false`, kadar so procesi onemogočeni.

---

### Objekti

#### `readObject`

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

Preberite poljubni objekt z njegovim celotnim šestnajstiškim zgoščevalnim zapisom (40 znakov ali 64 v repozitoriju SHA-256). Skrajšani zgoščevalni zapisi niso sprejeti. Vrne primerek `Blob`, `Tree`, `Commit` ali `Tag`. Najprej poišče nepripete objekte, nato pa paketne datoteke.

Sproži `ObjectNotFoundException`, če zgoščevalni zapis ni najden.

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

#### `writeObject`

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

Zapiše objekt v shrambo nepripetih objektov. Vrne izračunani `ObjectId`.

```php
use Pitmaster\Object\Blob;

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

#### `catFile`

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

Vrne surovo vsebino objekta, kar je enakovredno metodi `git cat-file -p`.

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

#### `objectExists`

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

Preveri, ali objekt obstaja v repozitoriju (kot nepripet ali zapakiran).

#### `listObjects`

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

Izpiše vse zgoščevalne zapise objektov v repozitoriju. Vrne polje šestnajstiških nizov.

---

### Reference

#### `head`

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

Vrne trenutno objavo HEAD. Sledi simbolnim referencam (HEAD -> refs/heads/main -> zgoščevalni zapis objave).

Sproži `RuntimeException`, če HEAD ne kaže na veljavno objavo (e.g., prazen repozitorij).

#### `branch`

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

Brez argumentov vrne ime trenutne veje (e.g, tj. `'main'`) ali `null`, če je HEAD odklopljen.

Z imenom veje jo razreši v njen zgoščevalni zapis objave (šestnajstiški niz) ali vrne `null`, če veja ne obstaja.

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

#### `branches`

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

Vrne razvrščeno polje vseh imen vej (brez predpone `refs/heads/`).

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

#### `tags`

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

Vrne razvrščeno polje vseh imen oznak (brez predpone `refs/tags/`).

#### `resolve`

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

Izraz revizije razreši v `ObjectId`. Podpira:
- Polne šestnajstiške zgoščevalne zapise (40 znakov ali 64 za SHA-256). Skrajšani zgoščevalni zapisi, kot je `abc1234`, se ne razrešijo.
- `HEAD`
- Imena vej (`main`, `feature/login`)
- Imena oznak (`v1.0.0`)
- Polne poti referenc (`refs/heads/main`)
- Izrazi revizij (`HEAD~3`, `main^2`)

Sproži `RuntimeException`, če revizije ni mogoče razrešiti.

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

#### `allRefs`

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

Vrne vse reference kot asociativno polje imen referenc in šestnajstiških zgoščevalnih zapisov.

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

#### `updateRef`

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

Posodobi referenco tako, da kaže na novo tarčo.

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

#### `createBranch`

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

Ustvari novo vejo. Če je `$from` null, jo razveji iz trenutnega HEAD-a.

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

#### `deleteBranch`

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

Izbriše vejo po imenu. Sproži `RuntimeException`, če je veja izpisana ali ne obstaja. V nasprotju z `git branch -d` ne preveri, ali je veja združena.

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

#### `createLightweightTag`

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

Ustvari preprosto oznako. Če je `$target` null, neposredno označi trenutni 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
```

Ustvari označeno oznako. Če je `$target` null, označi trenutni HEAD. Vrne `ObjectId` objekta oznake.

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

#### `deleteTag`

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

Izbriše oznako po imenu.

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

#### `packRefs`

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

Ponovno zapiše skupno datoteko `packed-refs` iz trenutnega nabora nepripetih referenc in odstrani ustrezne skupne nepripete reference. Pri povezanih delovnih kopijah zapisuje v skupni imenik git.

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

#### `defaultBranch`

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

Razreši privzeto vejo repozitorija. Najprej preveri simbolno referenco HEAD oddaljenega repozitorija, nato lokalni HEAD in nazadnje uporabi `main` ali `master`.

#### `isBranchMerged`

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

Preveri, ali je veja v celoti združena z drugo vejo (privzeto s privzeto vejo).

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

#### `checkout`

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

Preklopi veje ali odklopi HEAD. Posodobi HEAD, indeks in delovno drevo. `$target` je lahko ime veje, oznaka, polni zgoščevalni zapis ali izraz revizije; če ne gre za vejo, se HEAD odklopi.

Sproži `RuntimeException`, če je na poti, ki se razlikuje med trenutnim in ciljnim drevesom, lokalna sprememba (pripravljena ali nepripravljena) ali nesledena datoteka.

Nepotrjene spremembe v drugih sledenih datotekah se ne prenesejo: indeks in delovno drevo se znova sestavita iz ciljnega drevesa, zato se izgubijo spremembe datotek, ki so enake na obeh straneh, medtem ko bi jih ohranil git ([#2](https://github.com/inline0/pitmaster/issues/2)). Najprej jih potrdite ali shranite v stash. Tudi `merge()`, `cherryPick()`, `revert()`, `rebase()` in metode bisekcije na enak način znova sestavijo delovno drevo.

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

---

### Indeks

#### `index`

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

Prebere in vrne trenutni indeks (območje priprave) iz `.git/index`.

#### `add`

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

Pripravi datoteke. Vsako datoteko prebere iz delovnega drevesa, ustvari objekt blob in posodobi indeks. Vsak argument mora biti pot do datoteke (ali simbolne povezave) glede na koren delovnega drevesa; imeniki in vzorci se ne razširijo, manjkajoča datoteka pa sproži `RuntimeException`.

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

#### `remove`

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

Odstrani sledene poti iz indeksa in delovnega drevesa. Podpira `--cached` ter `-r` / `--recursive` v seznamu argumentov za vedenje po vzoru 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
```

Premakne/preimenuje datoteko v delovnem drevesu in indeksu.

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

---

### Objave

#### `commit`

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

Ustvari objavo iz trenutnega indeksa. Iz vnosov v indeksu sestavi hierarhijo dreves, ustvari objekt objave z HEAD-om kot nadrejeno objavo (če obstaja) in posodobi HEAD. Vrne `ObjectId` nove objave.

`$message` je lahko `null` samo, ko je združevanje, prenos posamezne objave, razveljavitev ali ponovno utemeljevanje ustavljeno zaradi konflikta; takrat se uporabi pripravljeno sporočilo. Sicer sporočilo `null` sproži `RuntimeException('Commit message required')`. Objava sproži izjemo tudi, če indeks vsebuje nerazrešene poti, če je indeks prazen v repozitoriju brez objav ali če se drevo ne razlikuje od drevesa HEAD-a.

Parameter `$author` je poln avtorski niz git (`Name <email> timestamp timezone`). Če je null, se vrednost razreši iz spremenljivk okolja, konstant in `.git/config`, po vrstnem redu, opisanem v [Uvod](https://pitmaster.inline0.dev/sl/docs/getting-started).

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

#### `show`

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

Prikaže objavi podobno revizijo in njene razlike glede na prvo nadrejeno objavo. Če se revizija razreši v označeno oznako, vrnjena vrednost vključuje tudi `['tag' => Tag]`, pri čemer je `commit` razrešena ciljna objava.

```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
```

Ponastavi HEAD na objavo. Načini:
- `'soft'`: premakne samo HEAD
- `'mixed'`: premakne HEAD in ponastavi indeks (privzeto)
- `'hard'`: premakne HEAD ter ponastavi indeks in delovno drevo

```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
```

Obnovi pot iz indeksa ali določene izvorne revizije. Če ni nastavljena nobena zastavica, Pitmaster obnovi delovno kopijo iz indeksa (ali iz `$source`, če je podan). `staged: true` obnovi indeks iz HEAD-a (ali `$source`) in pusti delovno kopijo nespremenjeno; za obnovitev obeh podajte `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
```

Uporabi objavo kot novo objavo na trenutni veji in ohrani prvotnega avtorja. Če konflikti ustavijo operacijo, jih razrešite, pripravite poti in nato pokličite `cherryPickContinue()` ali `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
```

Ustvari objavo, ki razveljavi drugo objavo. Če konflikti ustavijo razveljavitev, jih razrešite, pripravite poti in nato pokličite `revertContinue()` ali `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
```

Ponovno utemelji trenutno vejo na drugi reviziji. Pitmaster trenutno podpira linearno ponovno utemeljevanje s stanjem ustavitve v obliki Git ob konfliktih ter nadaljevanje, prekinitev in preskok. HEAD mora kazati na vejo.

`rebase()`, `rebaseContinue()` in `rebaseSkip()` vrnejo `['success' => bool, 'commits' => int, 'conflicts' => list<string>]`: ali je ponovno utemeljevanje končano, koliko objav je bilo uporabljenih in katere poti so bile v konfliktu, ko se je postopek ustavil.

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

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

---

### Stanje

#### `status`

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

Izračuna stanje delovnega drevesa. Vrne polje objektov `StatusEntry`, od katerih vsak vsebuje:
- `path`: pot do datoteke
- `index`: naštevalni tip `FileStatus` za spremembe od HEAD-a do indeksa
- `worktree`: naštevalni tip `FileStatus` za spremembe od indeksa do delovnega drevesa
- `origPath`, `renameScore`: nastavljena za preimenovane vnose, sicer `null`

Nesledene datoteke imajo v obeh stolpcih vrednost `FileStatus::Untracked`. Prezrte datoteke niso prikazane.

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

#### `statusPorcelainV2`

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

Strojno berljiv izpis stanja v zapisu porcelain git za v2.

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

---

### Razlike

#### `diff`

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

Primerja delovno drevo z indeksom (nepripravljene spremembe). Vrne polje objektov `DiffResult`. `$pathspec` filtrira po eni natančni poti do datoteke. `$algorithm` je `'myers'` (privzeto), `'patience'`, `'histogram'` ali `'minimal'`; vsaka druga vrednost sproži `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
```

Primerja indeks s HEAD-om (pripravljene spremembe). Vrne `DiffResult[]` z zaznavanjem preimenovanj med izbrisanimi in dodanimi datotekami.

Argument `$pathspec` je trenutno prezrt, zato se vrne vsaka pripravljena datoteka; metoda pa pred prvo objavo vrne prazno polje ([#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
```

Primerja dve drevesi po njunem `ObjectId`. Vrne `DiffResult[]`. Podajte ID-je dreves, ne ID-jev objav: ID objave se ne obravnava kot drevo in zato vrne prazen rezultat.

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

---

### Dnevnik

#### `log`

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

Pregleda zgodovino objav, najprej najnovejše glede na časovni žig avtorja objave. Vrne `Commit[]`. Če je `$from` null, začne pri HEAD-u. Če HEAD še nima objave, vrne prazno polje.

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

#### `logAll`

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

Pregleda objave, dosegljive iz vsake reference in HEAD-a, najprej najnovejše. Vrne `Commit[]`.

#### `logOneline`

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

Vrne vrstice dnevnika v obliki `git log --oneline` (`abc1234 Subject`), od HEAD-a, od vseh referenc (`$all`) ali filtrirane po poti.

#### `logPath`

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

Dnevnik, filtriran po poti do datoteke. Vrne samo objave, katerih razlika glede na prvo nadrejeno objavo doda, spremeni, izbriše ali preimenuje prav to datoteko. Poti do imenikov se ne ujemajo.

Pregleda se samo najnovejših `5 * $limit` objav, zato v rezultatu morda manjkajo starejše objave, ki so spremenile datoteko ([#7](https://github.com/inline0/pitmaster/issues/7)).

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

---

### Združevanje

#### `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
```

Združi vejo (ali katero koli revizijo) v HEAD. Samodejno zazna združitve s hitrim previtjem naprej. Pri drugih združitvah zazna konflikte na ravni drevesa in ob uspehu ustvari objavo združitve. Če pride do konflikta, v indeks in delovno kopijo zapiše stanje združitve v obliki Git; razrešite poti, jih pripravite in nato pokličite `mergeContinue()` ali `mergeAbort()`.

`$strategy` z vrednostjo `'ours'` zabeleži objavo združitve, ki ohrani drevo HEAD-a; katera koli druga vrednost uporabi privzeto rekurzivno združevanje. `mergeOctopus()` združi dve ali več vej v eno objavo. Če je katera koli veja v konfliktu, vrne neuspešen rezultat, ne da bi zapisala stanje združitve ali ustvarila objavo.

Združitev veje, ki je že vsebovana v HEAD, ustvari še enega združitvenega potrditvenega zapisa, namesto da bi sporočila »Already up to date« ([#6](https://github.com/inline0/pitmaster/issues/6)). Nepotrjene spremembe v sledenih datotekah so prepisane, kot je opisano v razdelku `checkout()`.

Vrne `MergeResult` z:
- `clean`: ali je bila združitev uspešna brez sporov
- `commitId`: ID združitvenega potrditvenega zapisa (če ni sporov)
- `conflictPaths`: seznam poti datotek s spori (če so spori)
- `mergedContents`: pot s sporom do vsebine datoteke z označevalniki sporov (če so spori)

```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
```

Poišče osnovo združitve (najnižjega skupnega prednika) dveh potrditvenih zapisov. Če skupni prednik ne obstaja, vrne null.

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

### Bisekcija

```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
```

Z binarnim iskanjem poišče potrditveni zapis, ki je uvedel spremembo. `bisectStart()` zabeleži slabe in dobre revizije, preveri prvo kandidatko in jo vrne. `bisectGood()` in `bisectBad()` označita trenutni HEAD (ali `$revision`), preverita naslednjo kandidatko in jo vrneta. Ko ostane en sam sumljivi potrditveni zapis, se ta vrne in ostane kandidat: to je prvi slab potrditveni zapis. `bisectReset()` konča sejo in se vrne na vejo ali potrditveni zapis, kjer se je začela.

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

---

### Omrežje

#### `fetch`

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

Prenese spremembe iz oddaljenega repozitorija. Prenese nove objekte in posodobi reference za sledenje oddaljenim repozitorijem. Podajte `$depth`, da poglobite ali omejite plitvo zgodovino.

Metodi `fetch()` in `push*()` ob uporabi ročice, odprte z `['processes' => false]`, sprožita `RuntimeException`.

```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
```

Potisne trenutno vejo (ali navedeno vejo) v oddaljeni repozitorij. Na voljo so različice force-with-lease, atomic in mirror za strožje ali širše posodabljanje referenc.

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

---

### Delovna drevesa

#### `addWorktree`

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

Doda povezano delovno drevo. Ustvari vejo, če še ne obstaja, nastavi metapodatke delovnega drevesa in ustvari datoteke delovnega drevesa. Podajte `$name`, kadar potrebujete deterministični metapodatkovni identifikator, ki se razlikuje od osnovnega imena imenika odjave.

```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
```

Odstrani povezano delovno drevo. Uporabite `$force = true` za odstranitev tudi, če je zaklenjeno.

#### `worktrees`

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

Izpiše vsa delovna drevesa (glavno in povezana). Vrne `Worktree[]`.

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

---

### Konfiguracija

#### `config`

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

Dostopa do konfiguracije git repozitorija. Bere in zapisuje konfiguracijske vrednosti.

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

---

### Notranji dostop

Te metode razkrivajo notranje komponente za napredne primere uporabe.

#### `objectDatabase`

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

Dostopa do surove podatkovne zbirke objektov (nepakirani in paketni shrambi).

#### `refDatabase`

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

Dostopa do surove podatkovne zbirke referenc (nepakirane in zapakirane reference).

---

## Razredi nižje ravni

Ti razredi niso oviti z `Repository` in so ustvarjeni iz njegovih notranjih komponent.

### `Pitmaster\Graph\Blame`

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

Vrne en vnos za vsako vrstico `$path` na mestu `$headId`: `['line' => int, 'hash' => string, 'author' => string, 'content' => string]`. `author` je celoten niz identitete (`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
```

Išče po blobih drevesa. Vrne `['path' => string, 'line' => int, 'content' => string]` za vsako ujemajočo se vrstico. Možnosti: `regex` (vzorec obravnava kot vzorec PCRE) in `ignore_case`. Neveljaven regularni izraz sproži `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
```

Bere in zapisuje zapiske git, shranjene pod referenco zapiskov. `listAll()` vrne preslikavo zgoščene vrednosti potrditvenega zapisa v vsebino zapiska.

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