
# PHP API

## `Pitmaster\Pitmaster`

`Pitmaster\Pitmaster` sınıfı statik giriş noktasıdır. Depoları açmak, oluşturmak ve klonlamak için fabrika yöntemlerinin yanı sıra algılama yardımcıları sunar.

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

### `open`

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

Mevcut bir depoyu `$path` konumunda açın. Yol, çalışma ağacının kökü olmalıdır (`.git/` içeren). Bağlı çalışma ağaçlarını (`.git`, `gitdir: <path>` içeren bir dosyadır) ve yalın depoları (`$path`, `.git` dizininin kendisidir) da destekler.

`$options`, her ikisi de varsayılan olarak `true` olan iki boole değeri kabul eder:

- `hooks`: `.git/hooks` betiklerini çalıştırır. Bu tanıtıcı için bunları atlamak üzere `false` değerini geçin.
- `processes`: süreç başlatan veya ağ aktarımı açan her şeye izin verir. Hook'ları, fsmonitor hook'unu, clone, fetch, push ve SSH süreç aktarımını devre dışı bırakmak için `false` değerini geçin. Yerel okuma ve yazma işlemleri çalışmaya devam eder.

Yol bir git deposu değilse `InvalidArgumentException` fırlatır.

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

`$path` konumunda yeni bir depo başlatın. `.git` dizin yapısını `objects/`, `refs/heads/`, `refs/tags/`, `hooks/`, `info/`, `HEAD` (`refs/heads/main` konumunu gösteren) ve varsayılan bir `config` ile oluşturur.

`$objectFormat`, `'sha1'` veya `'sha256'` olabilir. SHA-256 deposu, yapılandırmasında `repositoryformatversion = 1` ve `extensions.objectformat = sha256` değerlerini alır. Başka herhangi bir değer `InvalidArgumentException` fırlatır. `$options`, `open()` ile aynı anahtarları alır.

Belirtilen yolda zaten bir depo varsa `RuntimeException` fırlatır.

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

Uzak bir depoyu klonlayın. Yeni bir depo başlatır, uzak ref'leri keşfeder, pack dosyasını getirir, uzak izleme dallarını ayarlar ve çalışma ağacını oluşturur. SSH URL'leri (`ssh://...` veya `user@host:path`) SSH aktarımını kullanır; diğer URL'ler smart HTTP kullanır ve smart alışveriş başarısız olduğunda dumb HTTP yöntemine geri döner. Sığ klon için `$depth` geçin.

`$options['processes']`, `false` ise `RuntimeException` fırlatır. Klonlama başarısız olursa ve `$path` önceden mevcut değilse, kısmen oluşturulan dizin kaldırılır.

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

Ana makine süreçlerini başlatmaması gereken çalışma ortamları için `['processes' => false, 'hooks' => false]` döndürür. Bunu `open()` veya `init()`'ye geçin.

### `isRepository`

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

Bir yolun git deposu olup olmadığını denetler. Normal depolar (`.git/` dizini), bağlı çalışma ağaçları (`.git` dosyası) ve yalın depolar (`HEAD` dosyası mevcut) için `true` döndürür.

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

### `isWorktree`

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

Bir yolun bağlı çalışma ağacı (ana depo değil) olup olmadığını denetler. Yalnızca `.git`, `gitdir:` referansı içeren bir dosyaysa `true` döndürür.

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

### `commonGitDir`

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

Ortak git dizinini herhangi bir checkout yolundan çözümler. Normal depolarda bu, `.git` dizinidir. Bağlı çalışma ağaçlarında ise nesneleri, yapılandırmayı ve packed-refs'i içeren paylaşılan git dizinidir. Yol bir depo değilse `null` döndürür.

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

---

## `Pitmaster\Repository`

`Pitmaster\Repository` sınıfı, tüm git işlemleri için ana tanıtıcıdır. `Pitmaster::open()`, `Pitmaster::init()` veya `Pitmaster::clone()` aracılığıyla edinin.

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

### Yol erişimcileri

#### `gitDir`

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

Çalışma ağacına özel git dizinini döndürür. Normal depolarda bu, `.git/` konumudur. Bağlı çalışma ağaçlarında ise `.git/worktrees/<name>/` konumudur.

#### `commonGitDir`

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

Paylaşılan git dizinini döndürür. Normal depolarda `gitDir()` ile aynıdır. Bağlı çalışma ağaçlarında, ana deponun nesneleri, yapılandırmayı ve packed-refs'i içeren `.git/` dizinidir.

#### `workDir`

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

Çalışma ağacının kök yolunu döndürür.

#### `isLinkedWorktree`

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

Bu depo tanıtıcısı bağlı bir çalışma ağacıysa `true` döndürür.

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

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

Deponun çalışma ağacı olmadığını ve bu tanıtıcı için `hooks` / `processes` seçeneklerinden hangilerinin etkin olduğunu bildirir. Süreçler devre dışı olduğunda `hooksEnabled()` daima `false` olur.

---

### Nesneler

#### `readObject`

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

Herhangi bir nesneyi tam onaltılık karmasıyla (40 karakter veya SHA-256 deposunda 64 karakter) okuyun. Kısaltılmış karmalar kabul edilmez. Bir `Blob`, `Tree`, `Commit` veya `Tag` örneği döndürür. Önce gevşek nesneleri, ardından pack dosyalarını arar.

Karma bulunamazsa `ObjectNotFoundException` fırlatır.

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

#### `writeObject`

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

Gevşek nesne deposuna bir nesne yazın. Hesaplanan `ObjectId` değerini döndürür.

```php
use Pitmaster\Object\Blob;

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

#### `catFile`

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

Bir nesnenin ham içeriğini döndürür; `git cat-file -p` ile eşdeğerdir.

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

#### `objectExists`

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

Depoda (gevşek veya paketlenmiş) bir nesnenin bulunup bulunmadığını denetler.

#### `listObjects`

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

Depodaki tüm nesne karmalarını listeleyin. Onaltılık dizelerden oluşan bir dizi döndürür.

---

### Ref'ler

#### `head`

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

Geçerli HEAD commit'ini döndürür. Sembolik ref'leri izler (HEAD -> refs/heads/main -> commit karması).

HEAD geçerli bir commit'i göstermiyorsa `RuntimeException` fırlatır (e.g., boş depo).

#### `branch`

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

Bağımsız değişken olmadan geçerli dal adını (e.g., `'main'`) veya HEAD ayrılmışsa `null` döndürür.

Dal adı verildiğinde, onu commit karmasına (onaltılık dize) çözümler veya dal mevcut değilse `null` döndürür.

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

#### `branches`

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

Tüm dal adlarının sıralanmış bir dizisini (`refs/heads/` öneki olmadan) döndürür.

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

#### `tags`

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

Tüm etiket adlarının sıralanmış bir dizisini (`refs/tags/` öneki olmadan) döndürür.

#### `resolve`

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

Bir revizyon ifadesini `ObjectId` olarak çözümler. Şunları destekler:
- Tam onaltılık karmalar (40 karakter veya SHA-256 için 64 karakter). `abc1234` gibi kısaltılmış karmalar çözümlenmez.
- `HEAD`
- Dal adları (`main`, `feature/login`)
- Etiket adları (`v1.0.0`)
- Tam ref yolları (`refs/heads/main`)
- Revizyon ifadeleri (`HEAD~3`, `main^2`)

Revizyon çözümlenemiyorsa `RuntimeException` fırlatır.

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

#### `allRefs`

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

Tüm ref'leri, ref adlarından onaltılık karmalara eşleyen ilişkisel dizi olarak döndürür.

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

#### `updateRef`

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

Bir ref'i yeni bir hedefi gösterecek şekilde günceller.

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

#### `createBranch`

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

Yeni bir dal oluşturur. `$from` null ise geçerli HEAD'den dallanır.

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

#### `deleteBranch`

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

Bir dalı adıyla siler. Dal checkout edilmişse veya mevcut değilse `RuntimeException` fırlatır. `git branch -d`'den farklı olarak dalın birleştirilip birleştirilmediğini denetlemez.

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

#### `createLightweightTag`

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

Hafif bir etiket oluşturur. `$target` null ise geçerli HEAD'i doğrudan etiketler.

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

Açıklamalı bir etiket oluşturur. `$target` null ise geçerli HEAD'i etiketler. Etiket nesnesinin `ObjectId` değerini döndürür.

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

#### `deleteTag`

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

Bir etiketi adına göre siler.

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

#### `packRefs`

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

Paylaşılan `packed-refs` dosyasını geçerli gevşek ref kümesinden yeniden yazar ve karşılık gelen paylaşılan gevşek ref'leri budar. Bağlı çalışma ağaçlarında ortak git dizinine yazar.

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

#### `defaultBranch`

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

Deponun varsayılan dalını çözümler. Önce uzak HEAD symref'ini, ardından yerel HEAD'i denetler ve son olarak `main` veya `master` değerine geri döner.

#### `isBranchMerged`

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

Bir dalın başka bir dala (varsayılan olarak varsayılan dala) tamamen birleştirilip birleştirilmediğini denetler.

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

#### `checkout`

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

Dalları değiştirir veya HEAD'i ayırır. HEAD'i, indeksi ve çalışma ağacını günceller. `$target` bir dal adı, etiket, tam karma veya revizyon ifadesidir; dal olmayan her şey HEAD'i ayırır.

Geçerli ağaç ile hedef ağaç arasında farklılık gösteren bir yolda yerel değişiklik (hazırlanmış olsun ya da olmasın) veya izlenmeyen dosya varsa `RuntimeException` fırlatır.

İzlenen diğer dosyalardaki commit edilmemiş değişiklikler taşınmaz: indeks ve çalışma ağacı hedef ağaçtan yeniden oluşturulur; bu nedenle her iki tarafta da aynı olan dosyalardaki düzenlemeler kaybolur; git ise bunları korurdu ([#2](https://github.com/inline0/pitmaster/issues/2)). Önce commit edin veya stash'e alın. `merge()`, `cherryPick()`, `revert()`, `rebase()` ve bisect yöntemleri çalışma ağacını aynı şekilde yeniden oluşturur.

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

---

### İndeks

#### `index`

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

Geçerli indeksi (hazırlama alanı) `.git/index` konumundan okur ve döndürür.

#### `add`

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

Dosyaları hazırlayın. Her dosyayı çalışma ağacından okur, bir blob nesnesi oluşturur ve indeksi günceller. Her bağımsız değişken, çalışma ağacının köküne göreli bir dosya (veya sembolik bağlantı) yolu olmalıdır; dizinler ve glob kalıpları genişletilmez ve dosya yoksa `RuntimeException` fırlatır.

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

#### `remove`

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

İzlenen yolları hem indeksten hem de çalışma ağacından kaldırır. `--cached` ve Git davranışını taklit eden bağımsız değişken listesindeki `-r` / `--recursive` öğelerini destekler.

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

Bir dosyayı hem çalışma ağacında hem de indekste taşır/yeniden adlandırır.

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

---

### Commit'ler

#### `commit`

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

Geçerli indeksten bir commit oluşturur. İndeks girdilerinden bir ağaç hiyerarşisi kurar, varsa üst öğe olarak HEAD'i kullanarak commit nesnesini oluşturur ve HEAD'i günceller. Yeni commit'in `ObjectId` değerini döndürür.

`$message` yalnızca birleştirme, cherry-pick, revert veya rebase bir çakışmada durduğunda `null` olabilir; bu durumda hazırlanan mesaj kullanılır. Aksi durumda `null` mesajı `RuntimeException('Commit message required')` fırlatır. İndekste birleştirilmemiş yollar varsa, commit içermeyen bir depoda indeks boşsa veya ağaç HEAD'den değişmemişse de commit işlemi hata verir.

`$author` parametresi tam bir git yazar dizesidir (`Name <email> timestamp timezone`). null ise ortam değişkenlerinden, sabitlerden ve `.git/config`'ten, [Başlarken](https://pitmaster.inline0.dev/tr/docs/getting-started) bölümünde açıklanan sırayla çözümlenir.

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

#### `show`

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

Bir commit benzeri nesneyi ve ilk üst öğesine göre farkını gösterir. Revizyon açıklamalı bir etikete çözümlendiğinde, döndürülen değer ayrıca `['tag' => Tag]` içerir ve `commit` soyulmuş hedef commit olur.

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

HEAD'i bir commit'e sıfırlar. Modlar:
- `'soft'`: yalnızca HEAD'i taşır
- `'mixed'`: HEAD'i taşır + indeksi sıfırlar (varsayılan)
- `'hard'`: HEAD'i taşır + indeksi sıfırlar + çalışma ağacını sıfırlar

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

Bir yolu indeksten veya belirli bir kaynak revizyondan geri yükler. Her iki bayrak da ayarlanmamışsa Pitmaster çalışma ağacını indeksten (verilmişse `$source` konumundan) geri yükler. `staged: true`, indeksi HEAD'den (veya `$source` konumundan) geri yükler ve çalışma ağacına dokunmaz; ikisini birden geri yüklemek için `staged: true, worktree: true` geçin.

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

Bir commit'i özgün yazarını koruyarak geçerli dalda yeni bir commit olarak uygular. Çakışmalar işlemi durdurursa bunları çözün, yolları hazırlayın, ardından `cherryPickContinue()` veya `cherryPickAbort()` çağırın.

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

Başka bir commit'i geri alan bir commit oluşturur. Çakışmalar revert işlemini durdurursa bunları çözün, yolları hazırlayın, ardından `revertContinue()` veya `revertAbort()` çağırın.

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

Geçerli dalı başka bir revizyonun üzerine rebase eder. Pitmaster şu anda çakışmalarda Git biçiminde durma durumuyla doğrusal rebase işlemlerini ve devam etme, iptal etme ve atlama işlemlerini kapsar. HEAD bir dala işaret etmelidir.

`rebase()`, `rebaseContinue()` ve `rebaseSkip()`, rebase'in tamamlanıp tamamlanmadığını, kaç commit'in uygulandığını ve durduğunda çakışan yolları bildiren `['success' => bool, 'commits' => int, 'conflicts' => list<string>]` değerini döndürür.

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

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

---

### Durum

#### `status`

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

Çalışma ağacının durumunu hesaplar. Her biri şunları içeren `StatusEntry` nesnelerinden oluşan bir dizi döndürür:
- `path`: dosya yolu
- `index`: HEAD'den indekse değişiklikler için `FileStatus` enum değeri
- `worktree`: indeksten çalışma ağacına değişiklikler için `FileStatus` enum değeri
- `origPath`, `renameScore`: yeniden adlandırılan girdilerde ayarlanır, aksi hâlde `null` olur

İzlenmeyen dosyaların her iki sütununda da `FileStatus::Untracked` bulunur. Yoksayılan dosyalar bildirilmez.

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

#### `statusPorcelainV2`

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

git'ın porcelain v2 biçiminde makine tarafından okunabilir durum çıktısı.

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

---

### Fark

#### `diff`

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

Çalışma ağacını indekse göre karşılaştırır (hazırlanmamış değişiklikler). `DiffResult` nesnelerinden oluşan bir dizi döndürür. `$pathspec` tek bir tam dosya yoluna göre filtreler. `$algorithm`, `'myers'` (varsayılan), `'patience'`, `'histogram'` veya `'minimal'` değeridir; başka herhangi bir değer `InvalidArgumentException` fırlatır.

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

İndeksi HEAD ile karşılaştırır (hazırlanmış değişiklikler). Silinen ve eklenen dosyalar arasında yeniden adlandırma algılamasıyla `DiffResult[]` döndürür.

`$pathspec` bağımsız değişkeni şu anda yok sayılır; bu nedenle hazırlanan her dosya döndürülür ve ilk commit'ten önce yöntem boş bir dizi döndürür ([#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
```

İki ağacı `ObjectId` değerlerine göre karşılaştırır. `DiffResult[]` döndürür. Commit kimlikleri değil, ağaç kimlikleri geçin: commit kimliği ağaç olarak okunmaz ve boş sonuç üretir.

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

---

### Günlük

#### `log`

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

Commit geçmişini, commit eden kişinin zaman damgasına göre en yeniden başlayarak tarar. `Commit[]` döndürür. `$from` null ise HEAD'den başlar. HEAD'de henüz commit yoksa boş dizi döndürür.

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

#### `logAll`

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

Her ref'ten ve HEAD'den erişilebilen commit'leri en yeniden başlayarak tarar. `Commit[]` döndürür.

#### `logOneline`

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

Günlük satırlarını HEAD'den, tüm ref'lerden (`$all`) veya bir yola göre filtrelenmiş olarak `git log --oneline` biçiminde (`abc1234 Subject`) döndürür.

#### `logPath`

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

Dosya yoluna göre filtrelenmiş günlük. Yalnızca ilk üst öğesine göre farkında tam olarak bu dosyayı ekleyen, değiştiren, silen veya yeniden adlandıran commit'leri döndürür. Dizin yolları eşleşmez.

Yalnızca en yeni `5 * $limit` commit incelenir; bu nedenle dosyaya dokunan daha eski commit'ler sonuçta bulunmayabilir ([#7](https://github.com/inline0/pitmaster/issues/7)).

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

---

### Birleştirme

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

Bir dalı (veya herhangi bir revizyonu) HEAD ile birleştirir. İleri sarma birleştirmelerini otomatik olarak algılar. İleri sarma olmayan birleştirmelerde ağaç düzeyinde çakışma algılaması yapar ve temizse bir birleştirme commit'i oluşturur. Çakışma durumunda yazma işlemi Git biçimindeki birleştirme durumunu indekse ve çalışma ağacına kaydeder; yolları çözün, hazırlayın, ardından `mergeContinue()` veya `mergeAbort()` çağırın.

`$strategy` `'ours'`, HEAD'in ağacını koruyan bir birleştirme commit'i kaydeder; başka herhangi bir değer varsayılan özyinelemeli birleştirmeyi kullanır. `mergeOctopus()`, iki veya daha fazla dalı tek bir commit'te birleştirir. Herhangi bir dalda çakışma varsa, temiz olmayan bir sonuç döndürür ve birleştirme durumunu kaydetmez veya commit oluşturmaz.

Zaten HEAD içinde bulunan bir dalı birleştirmek, "Zaten güncel" bildirmek yerine yeni bir birleştirme commit'i oluşturur ([#6](https://github.com/inline0/pitmaster/issues/6)). İzlenen dosyalardaki commit edilmemiş değişikliklerin üzerine, `checkout()` bölümünde açıklandığı gibi yazılır.

Şunları içeren bir `MergeResult` döndürür:
- `clean`: birleştirmenin çakışma olmadan başarılı olup olmadığı
- `commitId`: birleştirme commit'inin kimliği (temizse)
- `conflictPaths`: çakışan dosya yollarının dizisi (temiz değilse)
- `mergedContents`: çakışma işaretçileri içeren dosya içeriğine giden çakışan yol (temiz değilse)

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

İki commit'in birleştirme tabanını (en düşük ortak atayı) bulur. Ortak ata yoksa null döndürür.

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

### İkiye bölme

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

Bir değişikliği başlatan commit'i ikili aramayla bulur. `bisectStart()` kötü ve iyi revizyonları kaydeder, ilk adayı kullanıma alır ve döndürür. `bisectGood()` ve `bisectBad()` geçerli HEAD'i (veya `$revision`) işaretler, sonraki adayı kullanıma alıp döndürür. Tek bir şüpheli kaldığında, o commit döndürülür ve aday olarak kalır: bu ilk hatalı commit'tir. `bisectReset()` oturumu bitirir ve başlandığı dala veya commit'e döner.

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

---

### Ağ

#### `fetch`

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

Bir uzak depodan getirir. Yeni nesneleri indirir ve uzak izleme referanslarını günceller. Sığ geçmişi derinleştirmek veya sınırlamak için `$depth` kullanın.

`fetch()` ve `push*()` yöntemleri, `['processes' => false]` ile açılmış bir tanıtıcıda `RuntimeException` hatası verir.

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

Geçerli dalı (veya belirtilen bir dalı) uzak depoya gönderir. Daha sıkı veya kapsamlı referans güncellemeleri için force-with-lease, atomic ve mirror varyantları kullanılabilir.

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

---

### Çalışma ağaçları

#### `addWorktree`

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

Bağlantılı bir çalışma ağacı ekler. Dal yoksa oluşturur, çalışma ağacı meta verilerini ayarlar ve çalışma ağacı dosyalarını oluşturur. Ödeme dizininin temel adından farklı, belirleyici bir meta veri slug'ına ihtiyacınız varsa `$name` kullanın.

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

Bağlantılı bir çalışma ağacını kaldırır. Kilitliyken de kaldırmak için `$force = true` kullanın.

#### `worktrees`

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

Tüm çalışma ağaçlarını (ana + bağlantılı) listeler. `Worktree[]` döndürür.

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

---

### Yapılandırma

#### `config`

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

Depo git yapılandırmasına erişir. Yapılandırma değerlerini okur ve yazar.

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

---

### Dahili erişim

Bu yöntemler, ileri düzey kullanım senaryoları için dahili bileşenleri sunar.

#### `objectDatabase`

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

Ham nesne veritabanına erişir (gevşek + paket depoları).

#### `refDatabase`

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

Ham ref veritabanına erişir (gevşek + paketlenmiş ref'ler).

---

## Daha düşük düzeyli sınıflar

Bu sınıflar `Repository` tarafından sarmalanmaz ve onun dahili bileşenlerinden oluşturulur.

### `Pitmaster\Graph\Blame`

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

`$headId` konumundaki `$path` girdilerinden satır başına bir tane döndürür: `['line' => int, 'hash' => string, 'author' => string, 'content' => string]`. `author` tam kimlik dizesidir (`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
```

Bir ağacın blob'larında arama yapar. Eşleşen satır başına `['path' => string, 'line' => int, 'content' => string]` döndürür. Seçenekler: `regex` (deseni PCRE deseni olarak ele alır) ve `ignore_case`. Geçersiz bir regex, `InvalidArgumentException` hatasına yol açar.

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

Notlar ref'i altında saklanan git notlarını okur ve yazar. `listAll()`, commit karmasını not içeriğine döndürür.

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