
# PHP API

## `Pitmaster\Pitmaster`

Klassen `Pitmaster\Pitmaster` är den statiska startpunkten. Den tillhandahåller fabrikmetoder för att öppna, skapa och klona arkiv, samt hjälpfunktioner för identifiering.

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

### `open`

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

Öppna ett befintligt arkiv på `$path`. Sökvägen ska vara arbetskatalogens rot (som innehåller `.git/`). Stöder även länkade worktrees (där `.git` är en fil som innehåller `gitdir: <path>`) och nakna arkiv (där `$path` är själva katalogen `.git`).

`$options` tar emot två booleska värden, båda `true` som standard:

- `hooks`: kör skript för `.git/hooks`. Skicka `false` för att hoppa över dem för det här handtaget.
- `processes`: tillåt allt som startar en process eller öppnar en nätverkstransport. Skicka `false` för att inaktivera hooks, fsmonitor-hooken, kloning, hämtning, push och processtransporten SSH. Lokal läsning och skrivning fortsätter att fungera.

Kastar `InvalidArgumentException` om sökvägen inte är ett git-arkiv.

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

Initiera ett nytt arkiv på `$path`. Skapar katalogstrukturen `.git` med `objects/`, `refs/heads/`, `refs/tags/`, `hooks/`, `info/`, `HEAD` (som pekar på `refs/heads/main`) och en standard-`config`.

`$objectFormat` är `'sha1'` eller `'sha256'`. Ett SHA-256-arkiv får `repositoryformatversion = 1` och `extensions.objectformat = sha256` i sin konfiguration. Alla andra värden kastar `InvalidArgumentException`. `$options` använder samma nycklar som `open()`.

Kastar `RuntimeException` om ett arkiv redan finns på sökvägen.

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

Klona ett fjärrarkiv. Initierar ett nytt arkiv, hittar fjärrreferenser, hämtar packfilen, konfigurerar fjärrspårningsgrenar och skapar arbetskatalogen. URL:er för SSH (`ssh://...` eller `user@host:path`) använder transporten SSH; andra URL:er använder smart HTTP och faller tillbaka på dum HTTP om det smarta utbytet misslyckas. Skicka `$depth` för en grund kloning.

Kastar `RuntimeException` när `$options['processes']` är `false`. Om kloningen misslyckas och `$path` inte fanns sedan tidigare tas den delvis skapade katalogen bort.

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

Returnerar `['processes' => false, 'hooks' => false]` för körmiljöer som inte får starta värdprocesser. Skicka det till `open()` eller `init()`.

### `isRepository`

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

Kontrollera om en sökväg är ett git-arkiv. Returnerar `true` för vanliga arkiv (katalogen `.git/`), länkade worktrees (filen `.git`) och nakna arkiv (när filen `HEAD` finns).

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

### `isWorktree`

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

Kontrollera om en sökväg är en länkad worktree (inte huvudarkivet). Returnerar `true` endast om `.git` är en fil som innehåller en referens till `gitdir:`.

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

### `commonGitDir`

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

Hitta den gemensamma katalogen git från valfri utcheckningssökväg. För vanliga arkiv är det katalogen `.git`. För länkade worktrees är det den delade katalogen git som innehåller objekt, konfiguration och packed-refs. Returnerar `null` om sökvägen inte är ett arkiv.

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

---

## `Pitmaster\Repository`

Klassen `Pitmaster\Repository` är huvudhandtaget för alla git-åtgärder. Hämta ett via `Pitmaster::open()`, `Pitmaster::init()` eller `Pitmaster::clone()`.

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

### Sökvägsaccessorer

#### `gitDir`

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

Returnerar katalogen git för den enskilda worktreen. För vanliga arkiv är detta `.git/`. För länkade worktrees är det `.git/worktrees/<name>/`.

#### `commonGitDir`

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

Returnerar den delade katalogen git. Samma som `gitDir()` för vanliga arkiv. För länkade worktrees är detta huvudarkivets katalog `.git/` (där objekt, konfiguration och packed-refs finns).

#### `workDir`

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

Returnerar arbetskatalogens rotsökväg.

#### `isLinkedWorktree`

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

Returnerar `true` om det här arkivhandtaget är en länkad worktree.

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

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

Ange om arkivet saknar arbetskatalog och vilka av alternativen `hooks` / `processes` som gäller för det här handtaget. `hooksEnabled()` är `false` när processer är inaktiverade.

---

### Objekt

#### `readObject`

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

Läs valfritt objekt med dess fullständiga hexadecimala hash (40 tecken, eller 64 i ett SHA-256-arkiv). Förkortade hashvärden godtas inte. Returnerar en instans av `Blob`, `Tree`, `Commit` eller `Tag`. Söker först bland lösa objekt och därefter i packfiler.

Kastar `ObjectNotFoundException` om hashen inte hittas.

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

#### `writeObject`

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

Skriv ett objekt till lagret för lösa objekt. Returnerar den beräknade `ObjectId`.

```php
use Pitmaster\Object\Blob;

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

#### `catFile`

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

Returnera ett objekts råinnehåll, motsvarande `git cat-file -p`.

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

#### `objectExists`

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

Kontrollera om ett objekt finns i arkivet (löst eller packat).

#### `listObjects`

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

Lista alla objektens hashvärden i arkivet. Returnerar en array med hexadecimala strängar.

---

### Referenser

#### `head`

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

Returnerar den aktuella HEAD-incheckningen. Följer symboliska referenser (HEAD -> refs/heads/main -> incheckningens hash).

Kastar `RuntimeException` om HEAD inte pekar på en giltig incheckning (e.g., tomt arkiv).

#### `branch`

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

Utan argument returneras det aktuella grennamnet (e.g., `'main'`), eller `null` om HEAD är frikopplad.

Med ett grennamn löses det upp till dess incheckningshash (hexadecimal sträng), eller så returneras `null` om grenen inte finns.

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

#### `branches`

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

Returnerar en sorterad array med alla grennamn (utan prefixet `refs/heads/`).

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

#### `tags`

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

Returnerar en sorterad array med alla taggnamn (utan prefixet `refs/tags/`).

#### `resolve`

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

Lös ett revisionsuttryck till en `ObjectId`. Stöder:
- Fullständiga hexadecimala hashvärden (40 tecken, eller 64 för SHA-256). Förkortade hashvärden som `abc1234` löses inte upp.
- `HEAD`
- Grennamn (`main`, `feature/login`)
- Taggnamn (`v1.0.0`)
- Fullständiga referenssökvägar (`refs/heads/main`)
- Revisionsuttryck (`HEAD~3`, `main^2`)

Kastar `RuntimeException` om revisionen inte kan lösas upp.

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

#### `allRefs`

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

Returnerar alla referenser som en associativ array från referensnamn till hexadecimal hash.

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

#### `updateRef`

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

Uppdatera en referens så att den pekar på ett nytt mål.

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

#### `createBranch`

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

Skapa en ny gren. Om `$from` är null skapas grenen från aktuell HEAD.

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

#### `deleteBranch`

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

Ta bort en gren med namn. Kastar `RuntimeException` om grenen är utcheckad eller inte finns. Till skillnad från `git branch -d` kontrollerar den inte om grenen har slagits samman.

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

#### `createLightweightTag`

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

Skapa en lättviktstagg. Om `$target` är null taggas aktuell HEAD direkt.

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

Skapa en annoterad tagg. Om `$target` är null taggas aktuell HEAD. Returnerar taggobjektets `ObjectId`.

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

#### `deleteTag`

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

Ta bort en tagg med namn.

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

#### `packRefs`

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

Skriv om den delade filen `packed-refs` utifrån den aktuella uppsättningen lösa referenser och rensa motsvarande delade lösa referenser. För länkade worktrees skrivs detta till den gemensamma katalogen git.

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

#### `defaultBranch`

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

Lös upp arkivets standardgren. Kontrollerar först fjärrarkivets HEAD-symref, sedan lokal HEAD och använder till sist `main` eller `master` som reserv.

#### `isBranchMerged`

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

Kontrollera om en gren har slagits samman helt med en annan gren (standardgrenen används som standard).

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

#### `checkout`

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

Byt gren eller koppla loss HEAD. Uppdaterar HEAD, indexet och arbetskatalogen. `$target` kan vara ett grennamn, ett taggnamn, en fullständig hash eller ett revisionsuttryck; allt som inte är en gren kopplar loss HEAD.

Kastar `RuntimeException` när en lokal ändring (staged eller inte) eller en ospårad fil finns i en sökväg som skiljer sig mellan det aktuella trädet och måltädet.

Ej incheckade ändringar i andra spårade filer förs inte över: indexet och arbetskatalogen byggs om från måltädet, så ändringar i filer som är identiska på båda sidor går förlorade, medan git skulle bevara dem ([#2](https://github.com/inline0/pitmaster/issues/2)). Checka in eller stash:a dem först. `merge()`, `cherryPick()`, `revert()`, `rebase()` och bisect-metoderna bygger om arbetskatalogen på samma sätt.

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

---

### Index

#### `index`

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

Läs och returnera det aktuella indexet (stagingområdet) från `.git/index`.

#### `add`

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

Stage:a filer. Läser varje fil från arbetskatalogen, skapar ett blob-objekt och uppdaterar indexet. Varje argument måste vara en filsökväg (eller en sökväg till en symbolisk länk) relativ till arbetskatalogens rot; kataloger och globmönster expanderas inte, och en saknad fil utlöser `RuntimeException`.

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

#### `remove`

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

Ta bort spårade sökvägar från både indexet och arbetskatalogen. Stöder `--cached` och `-r` / `--recursive` i argumentlistan för beteende som motsvarar 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
```

Flytta/byta namn på en fil i både arbetskatalogen och indexet.

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

---

### Incheckningar

#### `commit`

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

Skapa en incheckning från det aktuella indexet. Bygger en trädstruktur från indexposterna, skapar incheckningsobjektet med HEAD som förälder (om det finns) och uppdaterar HEAD. Returnerar den nya incheckningens `ObjectId`.

`$message` får vara `null` endast när en merge, cherry-pick, revert eller rebase har stannat på grund av en konflikt; då används det förberedda meddelandet. I andra fall utlöser ett meddelande av typen `null` `RuntimeException('Commit message required')`. En incheckning utlöser också ett fel om indexet innehåller olösta sökvägar, om indexet är tomt i ett arkiv utan incheckningar eller om trädet är oförändrat jämfört med HEAD.

Parametern `$author` är en fullständig författarsträng i formatet git (`Name <email> timestamp timezone`). Om värdet är null hämtas det från miljövariabler, konstanter och `.git/config`, i den ordning som beskrivs i [Kom igång](https://pitmaster.inline0.dev/sv/docs/getting-started).

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

#### `show`

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

Visa en incheckning och dess diff mot den första föräldern. När revisionen löses upp till en annoterad tagg innehåller returvärdet också `['tag' => Tag]`, och `commit` är den skalade mål-incheckningen.

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

Återställ HEAD till en incheckning. Lägen:
- `'soft'`: flytta endast HEAD
- `'mixed'`: flytta HEAD + återställ indexet (standard)
- `'hard'`: flytta HEAD + återställ indexet + återställ arbetskatalogen

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

Återställ en sökväg från indexet eller en angiven källrevision. Om ingen av flaggorna anges återställer Pitmaster worktreen från indexet (eller från `$source` om det anges). `staged: true` återställer indexet från HEAD (eller `$source`) och lämnar worktreen orörd; skicka `staged: true, worktree: true` för att återställa båda.

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

Tillämpa en incheckning som en ny incheckning på den aktuella grenen och bevara den ursprungliga författaren. Om konflikter stoppar åtgärden löser du dem, stage:ar sökvägarna och anropar sedan `cherryPickContinue()` eller `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
```

Skapa en incheckning som upphäver en annan incheckning. Om konflikter stoppar återställningen löser du dem, stage:ar sökvägarna och anropar sedan `revertContinue()` eller `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
```

Gör rebase av den aktuella grenen mot en annan revision. Pitmaster stöder för närvarande linjära rebaser med stopptillstånd för konflikter i formatet Git, samt fortsättning, avbrytning och överhoppning. HEAD måste peka på en gren.

`rebase()`, `rebaseContinue()` och `rebaseSkip()` returnerar `['success' => bool, 'commits' => int, 'conflicts' => list<string>]`: om rebasen slutfördes, hur många incheckningar som tillämpades och vilka sökvägar som hade konflikter när den stoppades.

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

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

---

### Status

#### `status`

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

Beräkna arbetskatalogens status. Returnerar en array med objekt av typen `StatusEntry`, som vart och ett innehåller:
- `path`: filsökvägen
- `index`: enum `FileStatus` för ändringar från HEAD till index
- `worktree`: enum `FileStatus` för ändringar från index till worktree
- `origPath`, `renameScore`: anges för namnbytta poster, annars `null`

Ospårade filer har `FileStatus::Untracked` i båda kolumnerna. Ignorerade filer rapporteras inte.

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

#### `statusPorcelainV2`

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

Maskinläsbar statusutdata i git:s porcelain-format v2.

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

---

### Diff

#### `diff`

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

Visa diff mellan arbetskatalogen och indexet (ostagade ändringar). Returnerar en array med objekt av typen `DiffResult`. `$pathspec` filtrerar på en exakt filsökväg. `$algorithm` är `'myers'` (standard), `'patience'`, `'histogram'` eller `'minimal'`; alla andra värden utlöser `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
```

Visa diff mellan indexet och HEAD (stagade ändringar). Returnerar `DiffResult[]`, med identifiering av namnbyten mellan borttagna och tillagda filer.

Argumentet `$pathspec` ignoreras för närvarande, så alla stagade filer returneras. Metoden returnerar en tom array före den första incheckningen ([#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
```

Visa diff mellan två träd med hjälp av deras `ObjectId`. Returnerar `DiffResult[]`. Skicka träd-ID:n, inte inchecknings-ID:n: ett inchecknings-ID läses inte som ett träd och ger ett tomt resultat.

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

---

### Logg

#### `log`

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

Gå igenom incheckningshistoriken, nyaste först enligt incheckarens tidsstämpel. Returnerar `Commit[]`. Om `$from` är null börjar genomgången från HEAD. Returnerar en tom array om HEAD ännu inte har någon incheckning.

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

#### `logAll`

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

Gå igenom incheckningar som kan nås från varje referens och HEAD, nyaste först. Returnerar `Commit[]`.

#### `logOneline`

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

Returnera loggrader i formatet `git log --oneline` (`abc1234 Subject`), från HEAD, från alla referenser (`$all`) eller filtrerade efter sökväg.

#### `logPath`

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

Logg filtrerad efter en filsökväg. Returnerar endast incheckningar vars diff mot den första föräldern lägger till, ändrar, tar bort eller byter namn på just den filen. Katalogsökvägar matchar inte.

Endast de senaste `5 * $limit` incheckningarna undersöks, så äldre incheckningar som berör filen kan saknas i resultatet ([#7](https://github.com/inline0/pitmaster/issues/7)).

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

---

### Merge

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

Slå samman en gren (eller valfri revision) till HEAD. Identifierar automatiskt snabbspolningssammanfogningar. Vid andra sammanfogningar utförs konfliktdetektering på trädnivå och en merge-incheckning skapas om inga konflikter uppstår. Om en konflikt stoppar åtgärden skrivs ett mergeläge i formatet Git till indexet och worktreen; lös sökvägarna, stage:a dem och anropa sedan `mergeContinue()` eller `mergeAbort()`.

`$strategy` `'ours'` registrerar en merge-incheckning som behåller HEAD:s träd; alla andra värden använder den rekursiva standardmergen. `mergeOctopus()` slår samman två eller fler grenar till en incheckning. Om någon gren har konflikter returneras ett resultat med konflikter utan att mergeläget skrivs eller en incheckning skapas.

Om du sammanfogar en gren som redan ingår i HEAD skapas ytterligare en merge-commit i stället för att rapportera ”Already up to date” ([#6](https://github.com/inline0/pitmaster/issues/6)). Ocommittade ändringar i spårade filer skrivs över enligt beskrivningen under `checkout()`.

Returnerar en `MergeResult` med:
- `clean`: om sammanfogningen lyckades utan konflikter
- `commitId`: merge-commitens ID (om den gick rent)
- `conflictPaths`: array med sökvägar till filer med konflikter (om den inte gick rent)
- `mergedContents`: sökväg till fil med innehåll som markerar konflikter (om den inte gick rent)

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

Hitta merge-basen (den lägsta gemensamma förfadern) för två commits. Returnerar null om det inte finns någon gemensam förfader.

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

### Bisect

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

Gör en binärsökning efter den commit som introducerade en ändring. `bisectStart()` registrerar de dåliga och goda revisionerna, checkar ut den första kandidaten och returnerar den. `bisectGood()` och `bisectBad()` markerar aktuell HEAD (eller `$revision`), checkar ut nästa kandidat och returnerar den. När bara en misstänkt återstår returneras den commiten, som förblir kandidaten: det är den första dåliga commiten. `bisectReset()` avslutar sessionen och återgår till grenen eller commiten där den startade.

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

---

### Nätverk

#### `fetch`

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

Hämta från ett fjärrarkiv. Laddar ned nya objekt och uppdaterar fjärrspårningsreferenser. Ange `$depth` för att fördjupa eller begränsa en ytlig historik.

`fetch()` och metoderna `push*()` kastar `RuntimeException` för ett handtag som öppnats med `['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
```

Skicka den aktuella grenen (eller en angiven gren) till ett fjärrarkiv. Varianter med force-with-lease, atomisk uppdatering och spegling finns för striktare eller bredare uppdateringar av referenser.

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

---

### Arbetsgrenar

#### `addWorktree`

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

Lägg till ett länkat arbetskatalogträd. Skapar grenen om den inte finns, konfigurerar metadata för arbetskatalogträdet och skapar filerna i arbetskatalogen. Ange `$name` om du behöver en deterministisk metadataslugg som skiljer sig från basnamnet på utcheckningskatalogen.

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

Ta bort ett länkat arbetskatalogträd. Använd `$force = true` för att ta bort det även om det är låst.

#### `worktrees`

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

Visa alla arbetskatalogträd (huvudträd + länkade). Returnerar `Worktree[]`.

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

---

### Konfiguration

#### `config`

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

Kom åt arkivets konfiguration i git. Läs och skriv konfigurationsvärden.

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

---

### Intern åtkomst

Dessa metoder exponerar interna komponenter för avancerade användningsfall.

#### `objectDatabase`

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

Kom åt den råa objektdatabasen (lösa objekt och packade objekt).

#### `refDatabase`

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

Kom åt den råa referensdatabasen (lösa och packade referenser).

---

## Klasser på lägre nivå

Dessa klasser omsluts inte av `Repository` och konstrueras utifrån dess interna komponenter.

### `Pitmaster\Graph\Blame`

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

Returnerar en post per rad i `$path` vid `$headId`: `['line' => int, 'hash' => string, 'author' => string, 'content' => string]`. `author` är den fullständiga identitetssträngen (`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
```

Söker igenom blobbarna i ett träd. Returnerar `['path' => string, 'line' => int, 'content' => string]` per matchande rad. Alternativ: `regex` (tolka mönstret som ett PCRE-mönster) och `ignore_case`. Ett ogiltigt reguljärt uttryck kastar `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
```

Läser och skriver git-anteckningar som lagras under en anteckningsreferens. `listAll()` returnerar en mappning från commit-hash till anteckningsinnehåll.

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