
# CLI Referenz

Pitmaster enthält ein CLI, das eine Teilmenge der Befehle von git nachbildet. Es arbeitet mit dem Repository im aktuellen Arbeitsverzeichnis.

```bash
./vendor/bin/pitmaster <command> [args...]
```

Bei einer Composer-Installation lautet der Skriptpfad `./vendor/bin/pitmaster`; seit Version 0.2.11 findet es dort den Autoloader des Projekts. In einem Checkout des Pitmaster-Repositorys selbst führe `./bin/pitmaster` nach `composer install` aus. Die folgenden Beispiele verwenden `pitmaster` für beide Pfade. Ohne Argumente werden die Befehle aufgelistet.

Revisionen werden wie bei `Repository::resolve()` aufgelöst: `HEAD`, Branch- und Tag-Namen, vollständige Ref-Namen, vollständige Hashes sowie `~N`- und `^N`-Ausdrücke. Abgekürzte Hashes werden nicht akzeptiert. Klonen, Abrufen und Pushen sind nur über die PHP API verfügbar.

## Befehle

### `log`

Commit-Verlauf anzeigen, neueste zuerst.

```bash
# Default: last 10 commits
pitmaster log

# Limit the number of commits
pitmaster log 25
pitmaster log -n 3
pitmaster log -n3
pitmaster log --max-count 3
pitmaster log --max-count=3
pitmaster log -3

# Commits that touch one file
pitmaster log src/Repository.php
pitmaster log -- src/Repository.php

# Commits reachable from all refs, and one line per commit
pitmaster log --all
pitmaster log --oneline
```

Die Schreibweisen für git-Limits (`-n N`, `-nN`, `--max-count N`, `--max-count=N`, `-N`) wurden in 0.2.11 hinzugefügt. Eine bloße Zahl ist die Kurzform für das Limit von Pitmaster. Das erste weitere Argument filtert nach Pfaden; alles nach `--` wird als Pfad behandelt. Jedes andere Argument, das mit `-` beginnt, gibt `fatal: unrecognized argument: <arg>` aus und beendet das Programm mit 128.

Die Ausgabe enthält `commit <hash>` (gelb), eine `Merge:`-Zeile für Merge-Commits, `Author:` mit der unformatierten Identität (Name, E-Mail, Zeitstempel und Zeitzone) sowie die eingerückte Commit-Nachricht. `--oneline` gibt `abc1234 Subject` aus. Der Pfadfilter erfasst genau einen Dateipfad und prüft nur die neuesten fünf mal so viele Commits wie das Limit ([#7](https://github.com/inline0/pitmaster/issues/7)).

### `show`

Commit-Details und Diff gegenüber dem ersten übergeordneten Commit anzeigen.

```bash
# Show HEAD
pitmaster show

# Show a specific commit
pitmaster show HEAD~3
pitmaster show v1.0.0
pitmaster show 3f2c1e0b9d6a4f8e7c5b2a1d0e9f8c7b6a5d4e3f
```

Zeigt die Commit-Metadaten (mit einer `Date:`-Zeile) und danach einen Unified Diff an. Bei einem annotierten Tag werden zuerst Tag-Header und Nachricht angezeigt. Farben werden nur verwendet, wenn stdout ein Terminal ist. Merge-Commits werden ohne Diff angezeigt.

### `cat-file`

Gibt den Rohinhalt eines git-Objekts aus.

```bash
pitmaster cat-file a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
```

Nimmt einen vollständigen Hash entgegen. Gibt den gespeicherten Inhalt des Objekts aus: Blobs, Commits und Tags als Text, Trees in ihrer Binärform. Anders als `git cat-file -p` werden Trees nicht formatiert ausgegeben.

### `status`

Arbeitsbaumstatus anzeigen.

```bash
pitmaster status
pitmaster status --porcelain=v2
```

Ausgabe:

```
On branch main

Changes to be committed:
	new file:   src/Feature.php

Changes not staged for commit:
	modified:   src/Existing.php

Untracked files:
	notes.txt
```

Bereitgestellte Dateien werden grün angezeigt, nicht bereitgestellte, nicht zusammengeführte und nicht nachverfolgte Dateien rot. Bei einem Merge-Konflikt wird ein Abschnitt `Unmerged paths:` angezeigt. Bei einem losgelösten HEAD wird `HEAD detached` ausgegeben, bei einem sauberen Arbeitsbaum `nothing to commit, working tree clean`. `--porcelain=v2` gibt die Ausgabe von `Repository::statusPorcelainV2()` aus.

### `diff`

Änderungen zwischen Index und Arbeitsbaum anzeigen (nicht bereitgestellte Änderungen).

```bash
# Unstaged changes
pitmaster diff

# Staged changes (index vs HEAD)
pitmaster diff --cached
pitmaster diff --staged

# Choose the algorithm
pitmaster diff --patience
pitmaster diff --histogram
pitmaster diff --minimal
```

Die Ausgabe ist ein farbiger Unified Diff, auch wenn stdout kein Terminal ist. Bei geänderten Textdateien entspricht sie `git diff`; neue, gelöschte, binäre, umbenannte und Dateien mit geändertem Modus werden anders formatiert (siehe [Diff](https://pitmaster.inline0.dev/de/docs/operations/diff)). `diff --cached` gibt vor dem ersten Commit nichts aus ([#5](https://github.com/inline0/pitmaster/issues/5)).

### `add`

Dateien für den nächsten Commit bereitstellen.

```bash
pitmaster add src/Feature.php
pitmaster add src/Feature.php tests/FeatureTest.php README.md
```

Jede Datei wird aus dem Arbeitsbaum gelesen, als Blob-Objekt geschrieben und der Index aktualisiert. Argumente sind Dateipfade; Verzeichnisse und `.` werden nicht erweitert.

### `commit`

Einen Commit aus den bereitgestellten Dateien erstellen.

```bash
pitmaster commit -m "Add new feature"
```

Ausgabe:

```
[main abc1234] Add new feature
```

`-m` ist erforderlich, außer wenn ein angehaltener Merge, Cherry-Pick, Revert oder Rebase abgeschlossen wird; dann wird die vorbereitete Nachricht verwendet. Autor und Committer werden anhand von Umgebungsvariablen, Konstanten und `.git/config` ermittelt, wie unter [Erste Schritte](https://pitmaster.inline0.dev/de/docs/getting-started) beschrieben.

### `branch`

Branches auflisten oder einen neuen erstellen.

```bash
# List all branches (current marked with *)
pitmaster branch

# Create a new branch from HEAD
pitmaster branch feature/new-thing

# Delete a branch
pitmaster branch -d feature/old
pitmaster branch -D feature/old
```

Ausgabe beim Auflisten:

```
  bugfix/typo
  feature/login
* main
```

Beim Erstellen wird `Created branch <name>` ausgegeben, beim Löschen `Deleted branch <name>`. `-d` und `-D` verhalten sich gleich: Keiner der Befehle prüft, ob der Branch bereits zusammengeführt wurde, und beide verweigern das Löschen des ausgecheckten Branches.

### `tag`

Tags auflisten oder einen neuen erstellen.

```bash
# List all tags
pitmaster tag

# Create a lightweight tag at HEAD
pitmaster tag v1.0.0

# Create an annotated tag at HEAD
pitmaster tag v2.0.0 -m "Release version 2.0.0"
```

Beim Erstellen wird `Created tag <name>` ausgegeben.

### `checkout`

Branches wechseln oder HEAD lösen.

```bash
# Switch to a branch
pitmaster checkout feature/login

# Detach HEAD at a tag or commit
pitmaster checkout v1.0.0
pitmaster checkout HEAD~2
```

Aktualisiert HEAD, den Index und den Arbeitsbaum entsprechend dem Ziel und gibt `Switched to '<target>'` aus. Der Befehl wird verweigert, wenn lokale Änderungen oder nicht nachverfolgte Dateien in Pfaden liegen, die sich zwischen den beiden Trees unterscheiden. Nicht committete Änderungen in anderen nachverfolgten Dateien werden mit dem Inhalt des Ziels überschrieben, wie es auch git tun würde ([#2](https://github.com/inline0/pitmaster/issues/2)); committe oder stash sie zuerst.

### `merge`

Einen oder mehrere Branches in den aktuellen HEAD mergen oder einen laufenden Merge-Konflikt fortsetzen/abbrechen.

```bash
# Start a merge
pitmaster merge feature/login

# Merge with a strategy
pitmaster merge -s ours feature/login

# Octopus merge of several branches
pitmaster merge feature/a feature/b

# Continue after resolving conflicts
pitmaster add a.txt
pitmaster merge --continue

# Abort and restore the pre-merge state
pitmaster merge --abort
```

Ausgabe bei Erfolg:

```
Merge successful.
```

Ausgabe bei Konflikt (auf stderr, Exit-Code 1):

```
CONFLICT in: src/File.php, src/Other.php
```

`-s` akzeptiert `ours`, `ort` und `recursive`; `ort` und `recursive` verwenden beide den Standard-Merge. Mit `-s` gibt CLI `Merge successful.` aus und beendet sich mit 0, auch wenn der Merge wegen Konflikten angehalten wurde ([#21](https://github.com/inline0/pitmaster/issues/21)); prüfe daher anschließend `status`. `merge --continue` beendet sich mit 128, wenn kein Merge läuft. Das Mergen eines bereits zusammengeführten Branches erstellt einen weiteren Merge-Commit ([#6](https://github.com/inline0/pitmaster/issues/6)), und nicht committete Änderungen in nachverfolgten Dateien werden wie bei `checkout` überschrieben.

### `cherry-pick`

Einen Commit auf den aktuellen HEAD anwenden oder einen laufenden Konflikt fortsetzen/abbrechen.

```bash
# Start a cherry-pick
pitmaster cherry-pick feature~1

# Continue after resolving conflicts
pitmaster add a.txt
pitmaster cherry-pick --continue

# Abort and restore HEAD
pitmaster cherry-pick --abort
```

Bei Erfolg wird nichts ausgegeben. `--continue` und `--abort` beenden sich mit 128, wenn kein Cherry-Pick läuft.

### `revert`

Einen Revert-Commit erstellen oder einen laufenden Konflikt fortsetzen/abbrechen.

```bash
# Start a revert
pitmaster revert HEAD~1

# Continue after resolving conflicts
pitmaster add a.txt
pitmaster revert --continue

# Abort and restore HEAD
pitmaster revert --abort
```

Bei Erfolg wird nichts ausgegeben. `--continue` und `--abort` beenden sich mit 128, wenn kein Revert läuft.

### `rebase`

Den aktuellen Branch auf eine andere Referenz rebasen.

```bash
# Start a rebase
pitmaster rebase main

# Continue after resolving conflicts
pitmaster rebase --continue

# Skip the current commit
pitmaster rebase --skip

# Abort and restore the original branch tip
pitmaster rebase --abort
```

Bei Erfolg wird nichts ausgegeben. `--continue`, `--skip` und `--abort` geben `fatal: no rebase in progress` aus und beenden sich mit 128, wenn kein Rebase läuft.

### `bisect`

Den Commit, der eine Änderung eingeführt hat, per binärer Suche finden.

```bash
# Start with a bad and a good revision; checks out and prints the first candidate
pitmaster bisect start HEAD v1.0.0

# Mark the checked-out candidate (or a given revision)
pitmaster bisect good
pitmaster bisect bad
pitmaster bisect bad HEAD~3

# End the session and return to the starting branch
pitmaster bisect reset
```

`start`, `good` und `bad` geben den vollständigen Hash des nächsten Kandidaten aus, der ausgecheckt wird. Bleibt nur noch ein möglicher Commit übrig, wird derselbe Hash erneut ausgegeben: Dieser Commit ist der erste fehlerhafte. Anders als git wird keine Zusammenfassung „is the first bad commit“ ausgegeben.

### `stash`

Änderungen im Arbeitsverzeichnis speichern und wiederherstellen.

```bash
# Save current changes (push)
pitmaster stash
pitmaster stash push
pitmaster stash push "Work in progress on login"
pitmaster stash save "Work in progress on login"

# Apply and remove the top stash entry
pitmaster stash pop

# Apply without removing
pitmaster stash apply

# List stash entries
pitmaster stash list

# Drop the top stash entry
pitmaster stash drop
```

Die Nachricht ist das Argument nach `push` oder `save`; `-m` wird nicht unterstützt und würde als Nachricht gespeichert. `pop`, `apply` und `drop` verwenden immer `stash@{0}`. Sie geben `Saved working directory to stash abc1234`, `Applied and dropped stash`, `Applied stash` und `Dropped stash` aus.

Ausgabe der Stash-Liste:

```
stash@{0}: On main: Work in progress on login
stash@{1}: WIP on main: abc1234 Add new feature
```

Bei mehr als einem Eintrag lassen `drop` und `pop` den Eintrag derzeit in der Liste ([#10](https://github.com/inline0/pitmaster/issues/10)), und `apply` überschreibt nicht committete Änderungen in Dateien, die der Stash nicht betrifft ([#11](https://github.com/inline0/pitmaster/issues/11)).

### `blame`

Urheberschaft für jede Zeile einer Datei bei HEAD anzeigen.

```bash
pitmaster blame src/Repository.php
```

Ausgabe:

```
a1b2c3d4 (Jane Smith <jane@example.com> ) <?php
a1b2c3d4 (Jane Smith <jane@example.com> )
f5e6d7c8 (Ann Lee <ann@example.com> 1700) declare(strict_types=1);
```

Jede Zeile zeigt die ersten 8 Zeichen des Commit-Hashs und die ersten 30 Zeichen der Autorenangabe (`Name <email> timestamp timezone`), ohne Auffüllung.

### `grep`

Dateiinhalte im aktuellen HEAD-Tree durchsuchen.

```bash
pitmaster grep "function merge"
pitmaster grep -i -E "h.llo"
```

Ausgabe:

```
src/Repository.php:2257:    public function merge(string $branch, string $strategy = 'recursive'): MergeResult
src/Merge/ThreeWayMerge.php:23:    public static function merge(
```

Optionen müssen vor dem Suchmuster stehen:

- `-i`, `--ignore-case`: Groß- und Kleinschreibung ignorieren
- `-E`, `--extended-regexp`, `--regex`: das Muster als PCRE-Regulären Ausdruck behandeln

Die Ausgabe ist reiner `path:line:content`-Text ohne Farben.

### `reflog`

Reflog-Einträge anzeigen, neueste zuerst.

```bash
# HEAD reflog (default: 10 entries)
pitmaster reflog

# Another ref, a custom limit, and a format
pitmaster reflog show refs/heads/main
pitmaster reflog -n 5
pitmaster reflog --format="%h %gs"
```

Das Standardformat ist `%gd: %gs` (`HEAD@{0}: commit: Add feature`). Unterstützte Platzhalter: `%gd` und `%gD` (Selektor), `%gs` (Nachricht), `%H` und `%h` (neuer Hash, vollständig und kurz). Für die Begrenzung sind `-n N`, `-nN` und `--max-count N` verfügbar; `-n 0` gibt alle Einträge aus.

Mit `pitmaster init` erstellte Repositories zeichnen keine Reflogs auf, sofern `core.logallrefupdates` nicht in `.git/config` auf `true` gesetzt ist ([#8](https://github.com/inline0/pitmaster/issues/8)). Daher gibt `reflog` dort bis dahin nichts aus.

### `refs`

Alle Referenzen mit ihren Hashes auflisten.

```bash
pitmaster refs
```

Ausgabe:

```
abc123def456... refs/heads/main
789012abc345... refs/heads/feature/login
def456789012... refs/tags/v1.0.0
```

Hashes werden vollständig ausgegeben.

### `reset`

HEAD auf einen bestimmten Commit zurücksetzen.

```bash
# Mixed reset (HEAD + index, default)
pitmaster reset HEAD~1
pitmaster reset --mixed HEAD~1

# Soft reset (HEAD only)
pitmaster reset --soft HEAD~1

# Hard reset (HEAD + index + worktree)
pitmaster reset --hard HEAD~3
```

Eine Revision ist erforderlich. Ausgabe:

```
HEAD is now at abc1234
```

### `init`

Ein neues Repository initialisieren. Dies ist der einzige Befehl, der kein vorhandenes Repository benötigt.

```bash
# Initialize in the current directory
pitmaster init

# Initialize at a specific path
pitmaster init /path/to/new-project

# Create a SHA-256 repository
pitmaster init --object-format=sha256
pitmaster init /path/to/new-project --object-format=sha256
```

Ausgabe:

```
Initialized empty Pitmaster repository in /path/to/new-project/.git/
```

`--object-format` akzeptiert `sha1` (Standard) und `sha256`.

## Exit-Codes

| Code | Bedeutung |
|------|---------|
| 0 | Erfolg |
| 1 | Befehlsfehler: Anwendungsfehler, unbekannter Befehl, fehlgeschlagene Operation (`error: <message>`) oder ein Merge, der wegen Konflikten abgebrochen wurde |
| 128 | Kein git-Repository (`fatal: <message>`), nicht erkanntes Argument `log` oder `--continue` / `--abort` / `--skip` ohne laufende Operation |
