
# PHP API

## `Pitmaster\Pitmaster`

`Pitmaster\Pitmaster` klasė yra statinis pradinis taškas. Joje pateikiami gamykliniai metodai saugykloms atidaryti, kurti ir klonuoti bei aptikimo pagalbinės funkcijos.

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

### `open`

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

Atidarykite esamą saugyklą adresu `$path`. Kelias turėtų būti darbinio medžio šaknis (kurioje yra `.git/`). Taip pat palaikomi susieti darbiniai medžiai (juose `.git` yra failas su `gitdir: <path>`) ir plikosios saugyklos (jose `$path` yra pats `.git` katalogas).

`$options` priima dvi logines reikšmes; abiejų numatytoji reikšmė yra `true`:

- `hooks`: vykdyti `.git/hooks` scenarijus. Perduokite `false`, kad šiame objekte jie būtų praleisti.
- `processes`: leisti viską, kas paleidžia procesą arba atidaro tinklo transportą. Perduokite `false`, kad išjungtumėte kablius, fsmonitor kablį, klonavimą, gavimą, siuntimą ir SSH proceso transportą. Vietinis skaitymas ir rašymas toliau veikia.

Jei kelias nėra git saugykla, išmetama `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
```

Inicijuokite naują saugyklą adresu `$path`. Sukuriama `.git` katalogų struktūra su `objects/`, `refs/heads/`, `refs/tags/`, `hooks/`, `info/`, `HEAD` (nukreipiančiu į `refs/heads/main`) ir numatytuoju `config`.

`$objectFormat` yra `'sha1'` arba `'sha256'`. SHA-256 saugyklos konfigūracijoje nustatomi `repositoryformatversion = 1` ir `extensions.objectformat = sha256`. Bet kokia kita reikšmė sukelia `InvalidArgumentException`. `$options` priima tuos pačius raktus kaip `open()`.

Jei kelyje jau yra saugykla, išmetama `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
```

Klonuokite nuotolinę saugyklą. Sukuriama nauja saugykla, aptinkamos nuotolinės nuorodos, gaunamas paketo failas, nustatomos nuotolinio sekimo šakos ir paruošiamas darbinis medis. URL su SSH (`ssh://...` arba `user@host:path`) naudoja SSH transportą; kiti URL naudoja išmanųjį HTTP, o jam nepavykus – paprastąjį HTTP. Norėdami atlikti negilųjį klonavimą, perduokite `$depth`.

Kai `$options['processes']` yra `false`, išmetama `RuntimeException`. Jei klonavimas nepavyksta, o `$path` prieš tai neegzistavo, iš dalies sukurtas katalogas pašalinamas.

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

Grąžina `['processes' => false, 'hooks' => false]` vykdymo aplinkoms, kuriose negalima paleisti pagrindinio kompiuterio procesų. Perduokite jį `open()` arba `init()`.

### `isRepository`

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

Patikrina, ar kelias yra git saugykla. Įprastoms saugykloms (`.git/` katalogas), susietiems darbiniams medžiams (`.git` failas) ir plikosioms saugykloms (yra `HEAD` failas) grąžina `true`.

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

### `isWorktree`

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

Patikrina, ar kelias yra susietas darbinis medis (ne pagrindinė saugykla). Grąžina `true` tik tada, jei `.git` yra failas su nuoroda `gitdir:`.

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

### `commonGitDir`

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

Iš bet kurio išsiėmimo kelio nustato bendrą git katalogą. Įprastose saugyklose tai yra katalogas `.git`. Susietuose darbiniuose medžiuose tai bendrinamas git katalogas, kuriame yra objektai, konfigūracija ir packed-refs. Jei kelias nėra saugykla, grąžina `null`.

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

---

## `Pitmaster\Repository`

`Pitmaster\Repository` klasė yra pagrindinis visų git operacijų objektas. Jį gaukite per `Pitmaster::open()`, `Pitmaster::init()` arba `Pitmaster::clone()`.

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

### Prieiga prie kelių

#### `gitDir`

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

Grąžina kiekvienam darbiniam medžiui skirtą git katalogą. Įprastose saugyklose tai yra `.git/`, o susietuose darbiniuose medžiuose – `.git/worktrees/<name>/`.

#### `commonGitDir`

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

Grąžina bendrinamą git katalogą. Įprastose saugyklose sutampa su `gitDir()`. Susietuose darbiniuose medžiuose tai yra pagrindinės saugyklos katalogas `.git/`, kuriame saugomi objektai, konfigūracija ir packed-refs.

#### `workDir`

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

Grąžina darbinio medžio šakninį kelią.

#### `isLinkedWorktree`

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

Grąžina `true`, jei ši saugyklos nuoroda priklauso susietam darbiniam medžiui.

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

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

Nurodo, ar saugykla neturi darbinio medžio ir kurios parinktys `hooks` / `processes` taikomos šiam objektui. `hooksEnabled()` yra `false`, kai procesai išjungti.

---

### Objektai

#### `readObject`

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

Perskaito bet kurį objektą pagal visą jo šešioliktainį maišą (40 simbolių arba 64 SHA-256 saugykloje). Sutrumpinti maišai nepriimami. Grąžina `Blob`, `Tree`, `Commit` arba `Tag` egzempliorių. Pirmiausia ieško laisvųjų objektų, tada paketų failuose.

Jei maišos rasti nepavyksta, išmetama `ObjectNotFoundException`.

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

#### `writeObject`

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

Įrašo objektą į laisvųjų objektų saugyklą. Grąžina apskaičiuotą `ObjectId`.

```php
use Pitmaster\Object\Blob;

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

#### `catFile`

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

Grąžina neapdorotą objekto turinį; atitinka `git cat-file -p`.

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

#### `objectExists`

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

Patikrina, ar objektas yra saugykloje (laisvųjų objektų saugykloje arba pakete).

#### `listObjects`

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

Išvardija visų saugyklos objektų maišas. Grąžina šešioliktainių eilučių masyvą.

---

### Nuorodos

#### `head`

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

Grąžina dabartinį HEAD pakeitimą. Sekamos simbolinės nuorodos (HEAD -> refs/heads/main -> pakeitimo maišas).

Jei HEAD nenurodo galiojančio pakeitimo (e.g., tuščia saugykla), išmetama `RuntimeException`.

#### `branch`

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

Be argumentų grąžinamas dabartinės šakos pavadinimas (e.g., `'main'`) arba `null`, jei HEAD atjungtas.

Nurodžius šakos pavadinimą, jis išsprendžiamas į pakeitimo maišą (šešioliktainę eilutę), o jei šakos nėra, grąžinama `null`.

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

#### `branches`

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

Grąžina surikiuotą visų šakų pavadinimų masyvą (be prefikso `refs/heads/`).

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

#### `tags`

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

Grąžina surikiuotą visų žymų pavadinimų masyvą (be prefikso `refs/tags/`).

#### `resolve`

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

Išsprendžia revizijos išraišką į `ObjectId`. Palaikoma:
- Visi šešioliktainiai maišai (40 simbolių arba 64, jei naudojamas SHA-256). Sutrumpinti maišai, pvz., `abc1234`, neišsprendžiami.
- `HEAD`
- Šakų pavadinimai (`main`, `feature/login`)
- Žymų pavadinimai (`v1.0.0`)
- Visi nuorodų keliai (`refs/heads/main`)
- Revizijų išraiškos (`HEAD~3`, `main^2`)

Jei revizijos išspręsti nepavyksta, išmetama `RuntimeException`.

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

#### `allRefs`

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

Grąžina visas nuorodas kaip asociatyvųjį masyvą, kurio raktai yra nuorodų pavadinimai, o reikšmės – šešioliktainės maišos.

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

#### `updateRef`

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

Atnaujina nuorodą, kad ji rodytų į naują tikslą.

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

#### `createBranch`

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

Sukuria naują šaką. Jei `$from` yra null, šaka sukuriama nuo dabartinio HEAD.

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

#### `deleteBranch`

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

Pašalina šaką pagal pavadinimą. Jei šaka išsiimta arba jos nėra, išmetama `RuntimeException`. Kitaip nei `git branch -d`, netikrinama, ar šaka sujungta.

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

#### `createLightweightTag`

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

Sukuria lengvąją žymą. Jei `$target` yra null, žyma tiesiogiai priskiriama dabartiniam 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
```

Sukuria anotuotą žymą. Jei `$target` yra null, žyma priskiriama dabartiniam HEAD. Grąžina žymos objekto `ObjectId`.

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

#### `deleteTag`

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

Pašalina žymą pagal pavadinimą.

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

#### `packRefs`

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

Iš naujo įrašo bendrinamą failą `packed-refs` pagal dabartinį laisvųjų nuorodų rinkinį ir pašalina atitinkamas bendrinamas laisvąsias nuorodas. Susietuose darbiniuose medžiuose įrašoma į bendrą git katalogą.

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

#### `defaultBranch`

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

Nustato numatytąją saugyklos šaką. Pirmiausia tikrinama nuotolinio HEAD simbolinė nuoroda, tada vietinis HEAD, o galiausiai naudojama `main` arba `master`.

#### `isBranchMerged`

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

Patikrina, ar šaka visiškai sujungta su kita šaka (numatyta – numatytoji šaka).

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

#### `checkout`

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

Perjungia šakas arba atjungia HEAD. Atnaujina HEAD, indeksą ir darbinį medį. `$target` gali būti šakos pavadinimas, žyma, visas maišas arba revizijos išraiška; jei tai ne šaka, HEAD atjungiamas.

Išmetama `RuntimeException`, jei kelio, kurio turinys skiriasi tiksliniame medyje, pakeitimas (parengtas arba ne) arba nesekamas failas yra tame kelyje.

Nepatvirtinti kitų sekamų failų pakeitimai neperkeliami: indeksas ir darbinis medis atkuriami iš tikslinio medžio, todėl pakeitimai failuose, kurie abiejose pusėse yra vienodi, prarandami, nors git juos išsaugotų ([#2](https://github.com/inline0/pitmaster/issues/2)). Pirmiausia juos patvirtinkite arba išsaugokite stash. `merge()`, `cherryPick()`, `revert()`, `rebase()` ir bisect metodai darbinį medį atkuria taip pat.

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

---

### Indeksas

#### `index`

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

Perskaito ir grąžina dabartinį indeksą (parengimo sritį) iš `.git/index`.

#### `add`

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

Parengia failus. Perskaito kiekvieną failą iš darbinio medžio, sukuria blob objektą ir atnaujina indeksą. Kiekvienas argumentas turi būti failo (arba simbolinės nuorodos) kelias darbinio medžio šakninio katalogo atžvilgiu; katalogai ir failų šablonai neišplečiami, o jei failo nėra, išmetama `RuntimeException`.

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

#### `remove`

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

Pašalina sekamus kelius ir iš indekso, ir iš darbinio medžio. Argumentų sąraše palaikomi `--cached` bei `-r` / `--recursive`, kad veiksena atitiktų 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
```

Perkelia arba pervadina failą darbiniame medyje ir indekse.

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

---

### Pakeitimai

#### `commit`

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

Sukuria pakeitimą iš dabartinio indekso. Iš indekso įrašų sudaro medžio hierarchiją, sukuria pakeitimo objektą, kurio tėvas (jei yra) yra HEAD, ir atnaujina HEAD. Grąžina naujo pakeitimo `ObjectId`.

`$message` gali būti `null` tik tada, kai sujungimas, cherry-pick, grąžinimas arba rebase sustoja dėl konflikto; tuomet naudojamas paruoštas pranešimas. Kitais atvejais dėl pranešimo `null` išmetama `RuntimeException('Commit message required')`. Pakeitimo kūrimas taip pat nepavyksta, jei indekse yra nesujungtų kelių, jei saugykloje be pakeitimų indeksas tuščias arba jei medis nepasikeitė, palyginti su HEAD.

`$author` parametras yra visa git autoriaus eilutė (`Name <email> timestamp timezone`). Jei reikšmė null, ji nustatoma iš aplinkos kintamųjų, konstantų ir `.git/config` tokia tvarka, kaip aprašyta skiltyje [Darbo pradžia](https://pitmaster.inline0.dev/lt/docs/getting-started).

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

#### `show`

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

Parodo pakeitimą (commit-ish) ir jo skirtumą nuo pirmojo tėvinio pakeitimo. Jei revizija išsprendžiama į anotuotą žymą, grąžinamoje reikšmėje taip pat pateikiama `['tag' => Tag]`, o `commit` yra galutinis tikslinis pakeitimas.

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

Perstato HEAD į pakeitimą. Veiksenos:
- `'soft'`: perkelti tik HEAD
- `'mixed'`: perkelti HEAD ir atkurti indeksą (numatytoji)
- `'hard'`: perkelti HEAD, atkurti indeksą ir darbinį medį

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

Atkuria kelią iš indekso arba nurodytos šaltinio revizijos. Jei nenustatyta nė viena vėliavėlė, Pitmaster atkuria darbinį medį iš indekso (arba iš `$source`, jei nurodytas). `staged: true` atkuria indeksą iš HEAD (arba `$source`) ir darbinio medžio nekeičia; norėdami atkurti abu, perduokite `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
```

Pritaiko pakeitimą kaip naują dabartinės šakos pakeitimą, išsaugodamas pradinį autorių. Jei dėl konfliktų operacija sustoja, išspręskite konfliktus, parenkite kelius, tada iškvieskite `cherryPickContinue()` arba `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
```

Sukuria pakeitimą, kuris panaikina kitą pakeitimą. Jei grąžinimas sustoja dėl konfliktų, juos išspręskite, parenkite kelius, tada iškvieskite `revertContinue()` arba `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
```

Perkelia dabartinę šaką ant kitos revizijos. Pitmaster šiuo metu palaiko linijinius rebase veiksmus su Git formos sustabdymo būsena konfliktams, taip pat tęsimą, nutraukimą ir praleidimą. HEAD turi rodyti į šaką.

`rebase()`, `rebaseContinue()` ir `rebaseSkip()` grąžina `['success' => bool, 'commits' => int, 'conflicts' => list<string>]`: ar rebase baigtas, kiek pakeitimų pritaikyta ir kurie keliai konfliktavo jam sustojus.

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

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

---

### Būsena

#### `status`

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

Apskaičiuoja darbinio medžio būseną. Grąžina objektų `StatusEntry` masyvą, kurių kiekviename yra:
- `path`: failo kelias
- `index`: `FileStatus` reikšmių sąrašas HEAD ir indekso pakeitimams
- `worktree`: `FileStatus` reikšmių sąrašas indekso ir darbinio medžio pakeitimams
- `origPath`, `renameScore`: nustatyti pervadintiems įrašams, kitu atveju `null`

Abiejuose stulpeliuose nesekami failai turi `FileStatus::Untracked`. Ignoruojami failai nepateikiami.

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

#### `statusPorcelainV2`

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

Mašininiu būdu nuskaitoma būsenos išvestis git porcelain v2 formatu.

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

---

### Skirtumas

#### `diff`

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

Palyginama darbinė kopija su indeksu (neįrašyti pakeitimai). Grąžinamas `DiffResult` objektų masyvas. `$pathspec` filtruoja pagal vieną tikslų failo kelią. `$algorithm` yra `'myers'` (numatytoji reikšmė), `'patience'`, `'histogram'` arba `'minimal'`; bet kuri kita reikšmė sukelia `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
```

Palyginamas indeksas su HEAD (įrašyti pakeitimai). Grąžinamas `DiffResult[]` su pervadinimų aptikimu tarp ištrintų ir pridėtų failų.

Šiuo metu argumento `$pathspec` nepaisoma, todėl grąžinamas kiekvienas įrašytas failas, o prieš pirmąjį commit metodas grąžina tuščią masyvą ([#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
```

Palyginami du medžiai pagal jų `ObjectId`. Grąžinamas `DiffResult[]`. Perduokite medžių ID, o ne commit ID: commit ID nelaikomas medžiu, todėl gaunamas tuščias rezultatas.

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

---

### Žurnalas

#### `log`

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

Peržiūrima commit istorija, pradedant naujausiu pagal autoriaus laiko žymą. Grąžinamas `Commit[]`. Jei `$from` yra null, pradedama nuo HEAD. Jei HEAD dar neturi commit, grąžinamas tuščias masyvas.

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

#### `logAll`

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

Peržiūrimi commit, pasiekiami iš kiekvienos nuorodos ir HEAD, pradedant naujausiu. Grąžinamas `Commit[]`.

#### `logOneline`

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

Grąžinkite žurnalo eilutes formatu `git log --oneline` (`abc1234 Subject`), iš HEAD, iš visų nuorodų (`$all`) arba filtruotas pagal kelią.

#### `logPath`

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

Žurnalas filtruojamas pagal failo kelią. Grąžinami tik tie commit, kurių pakeitimai, palyginti su pirmuoju pirminiu commit, prideda, pakeičia, ištrina arba pervadina būtent tą failą. Katalogų keliai neatitinka.

Tikrinami tik naujausi `5 * $limit` commit, todėl senesni commit, kurie keitė failą, gali nepatekti į rezultatą ([#7](https://github.com/inline0/pitmaster/issues/7)).

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

---

### Suliejimas

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

Suliejama šaka (ar bet kuri kita revizija) su HEAD. Greitojo persukimo suliejimai aptinkami automatiškai. Jei greitai persukti negalima, aptinkami medžio lygmens konfliktai ir, jei jų nėra, sukuriamas suliejimo commit. Kilus konfliktui, į indeksą ir darbinę kopiją įrašoma Git formato suliejimo būsena; išspręskite konfliktus, įtraukite failus į indeksą, tada iškvieskite `mergeContinue()` arba `mergeAbort()`.

`$strategy` `'ours'` įrašo suliejimo commit, išlaikantį HEAD medį; bet kuri kita reikšmė naudoja numatytąjį rekursinį suliejimą. `mergeOctopus()` sulieja dvi ar daugiau šakų į vieną commit. Jei kyla konfliktas bet kurioje šakoje, grąžinamas nesėkmingas rezultatas, neįrašant suliejimo būsenos ir nesukuriant commit.

Suliejus šaką, kuri jau įtraukta į HEAD, sukuriamas dar vienas suliejimo commit, užuot pranešus „Jau atnaujinta“ ([#6](https://github.com/inline0/pitmaster/issues/6)). Neįrašyti sekamų failų pakeitimai perrašomi, kaip aprašyta skiltyje `checkout()`.

Grąžinamas `MergeResult` su:
- `clean`: ar suliejimas pavyko be konfliktų
- `commitId`: suliejimo commit ID (jei konfliktų nėra)
- `conflictPaths`: konfliktuojančių failų kelių masyvas (jei konfliktų yra)
- `mergedContents`: konfliktuojančio kelio ir failo turinio su konflikto žymomis atitikmuo (jei konfliktų yra)

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

Randamas dviejų commit suliejimo pagrindas (žemiausias bendras protėvis). Jei bendro protėvio nėra, grąžinama 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
```

Atliekama dvejetainė paieška, siekiant rasti pakeitimą įvedusį commit. `bisectStart()` užfiksuoja blogą ir gerą revizijas, išrenka pirmą kandidatą ir jį grąžina. `bisectGood()` ir `bisectBad()` pažymi dabartinį HEAD (arba `$revision`), tada išrenka ir grąžina kitą kandidatą. Kai lieka vienas įtariamasis, grąžinamas tas commit, kuris lieka kandidatu: tai pirmasis blogas commit. `bisectReset()` užbaigia sesiją ir grįžta į šaką arba commit, kuriame ji prasidėjo.

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

---

### Tinklas

#### `fetch`

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

Gaunami duomenys iš nuotolinės saugyklos. Atsisiunčiami nauji objektai ir atnaujinamos nuotolinio sekimo nuorodos. Perduokite `$depth`, jei norite papildyti arba apriboti seklią istoriją.

`fetch()` ir metodai `push*()` atidarytoje deskriptoriaus nuorodoje su `['processes' => false]` sukelia `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
```

Į nuotolinę saugyklą siunčiama dabartinė šaka (arba nurodyta šaka). Galimi „force-with-lease“, atominiai ir veidrodiniai variantai, skirti griežtesniems ar platesniems nuorodų atnaujinimams.

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

---

### Darbinės kopijos

#### `addWorktree`

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

Pridedama susieta darbinė kopija. Jei šaka neegzistuoja, ji sukuriama, nustatomi darbinės kopijos metaduomenys ir parengiami darbinės kopijos failai. Perduokite `$name`, kai reikia deterministinio metaduomenų identifikatoriaus, kuris skirtųsi nuo išsiregistruoto katalogo bazinio pavadinimo.

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

Pašalinama susieta darbinė kopija. Norėdami pašalinti net ir užrakintą kopiją, naudokite `$force = true`.

#### `worktrees`

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

Išvardijamos visos darbinės kopijos (pagrindinė ir susietos). Grąžinamas `Worktree[]`.

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

---

### Konfigūracija

#### `config`

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

Pasiekite saugyklos git konfigūraciją. Skaitykite ir rašykite konfigūracijos reikšmes.

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

---

### Vidinė prieiga

Šie metodai atveria vidinius komponentus pažangesniems naudojimo atvejams.

#### `objectDatabase`

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

Pasiekiama neapdorota objektų duomenų bazė (atskirieji ir supakuoti įrašai).

#### `refDatabase`

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

Pasiekiama neapdorota nuorodų duomenų bazė (atskirosios ir supakuotos nuorodos).

---

## Žemesnio lygmens klasės

Šios klasės neapgaubtos `Repository` ir sukuriamos iš jos vidinių komponentų.

### `Pitmaster\Graph\Blame`

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

Grąžinamas vienas kiekvienos `$path` eilutės įrašas ties `$headId`: `['line' => int, 'hash' => string, 'author' => string, 'content' => string]`. `author` yra visa tapatybės eilutė (`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
```

Ieškoma medžio blob objektuose. Grąžinamas `['path' => string, 'line' => int, 'content' => string]` kiekvienai atitinkančiai eilutei. Parinktys: `regex` (šablonas laikomas PCRE šablonu) ir `ignore_case`. Netaisyklinga reguliarioji išraiška sukelia `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
```

Skaito ir rašo git pastabas, saugomas pastabų nuorodoje. `listAll()` pateikia pakeitimo maišą ir pastabos turinį.

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