
# Справочник CLI

Pitmaster включает CLI, реализующий часть команд git. Он работает с репозиторием в текущем рабочем каталоге.

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

При установке из Composer скрипт находится по пути `./vendor/bin/pitmaster`; поскольку 0.2.11, он находит там автозагрузчик проекта. В checkout самого репозитория Pitmaster выполните `./bin/pitmaster` после `composer install`. В примерах ниже для обоих путей используется `pitmaster`. Запуск без аргументов выводит список команд.

Ревизии разрешаются так же, как в `Repository::resolve()`: `HEAD`, имена веток и тегов, полные имена ссылок, полные хеши и выражения `~N` / `^N`. Сокращённые хеши не принимаются. Клонирование, получение данных и отправка доступны только через PHP API.

## Команды

### `log`

Показать историю коммитов, начиная с самых новых.

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

Варианты ограничения git (`-n N`, `-nN`, `--max-count N`, `--max-count=N`, `-N`) добавлены в 0.2.11. Простое число — это собственное сокращение Pitmaster для ограничения. Первый другой аргумент задаёт фильтр пути; всё после `--` считается путём. Любой другой аргумент, начинающийся с `-`, выводит `fatal: unrecognized argument: <arg>` и завершает работу с кодом 128.

Вывод содержит `commit <hash>` (жёлтый цвет), строку `Merge:` для коммитов слияния, `Author:` с исходными данными об авторе (имя, адрес электронной почты, временная метка и часовой пояс), а также текст сообщения коммита с отступом. `--oneline` выводит `abc1234 Subject`. Фильтр пути совпадает только с точным путём к файлу и проверяет коммиты в количестве, равном пятикратному значению ограничения ([#7](https://github.com/inline0/pitmaster/issues/7)).

### `show`

Показать сведения о коммите и его различия с первым родителем.

```bash
# Show HEAD
pitmaster show

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

Отображает метаданные коммита (со строкой `Date:`), а затем унифицированный diff. Для аннотированного тега сначала отображаются заголовок и сообщение тега. Цвета используются, только если stdout — терминал. Коммиты слияния отображаются без diff.

### `cat-file`

Вывести необработанное содержимое объекта git.

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

Принимает полный хеш. Выводит сохранённое содержимое объекта: blob-объекты, коммиты и теги — как текст, деревья — в двоичном формате. В отличие от `git cat-file -p`, деревья не выводятся в удобочитаемом формате.

### `status`

Показать состояние рабочего дерева.

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

Вывод:

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

Файлы в индексе отображаются зелёным, файлы с изменениями вне индекса, неслитые и неотслеживаемые — красным. Во время слияния с конфликтами появляется раздел `Unmerged paths:`. Для отсоединённого HEAD выводится `HEAD detached`, а для чистого дерева — `nothing to commit, working tree clean`. `--porcelain=v2` выводит результат `Repository::statusPorcelainV2()`.

### `diff`

Показать изменения между индексом и рабочим деревом (изменения, не добавленные в индекс).

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

Выводится раскрашенный унифицированный diff, даже если stdout не является терминалом. Для изменённых текстовых файлов формат соответствует `git diff`; новые, удалённые, двоичные файлы, переименования и изменения режима форматируются иначе (см. [Различия](https://pitmaster.inline0.dev/ru/docs/operations/diff)). `diff --cached` ничего не выводит до первого коммита ([#5](https://github.com/inline0/pitmaster/issues/5)).

### `add`

Добавить файлы в индекс для следующего коммита.

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

Каждый файл считывается из рабочего дерева, записывается как blob-объект, а индекс обновляется. Аргументы — пути к файлам; каталоги и `.` не раскрываются.

### `commit`

Создать коммит из файлов, добавленных в индекс.

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

Вывод:

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

Параметр `-m` обязателен, кроме завершения остановленного слияния, переноса коммита, отмены коммита или перемещения базы, когда используется подготовленное сообщение. Автор и коммиттер определяются по переменным окружения, константам и `.git/config`, как описано в разделе [Начало работы](https://pitmaster.inline0.dev/ru/docs/getting-started).

### `branch`

Показать ветки или создать новую.

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

Вывод списка:

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

При создании выводится `Created branch <name>`, при удалении — `Deleted branch <name>`. `-d` и `-D` работают одинаково: ни одна команда не проверяет, слита ли ветка, и обе отказываются удалять текущую ветку.

### `tag`

Показать теги или создать новый.

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

При создании выводится `Created tag <name>`.

### `checkout`

Переключить ветку или отсоединить HEAD.

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

Обновляет HEAD, индекс и рабочее дерево в соответствии с целью и выводит `Switched to '<target>'`. Отказывается выполнять операцию, если локальные изменения или неотслеживаемые файлы находятся по путям, различающимся в двух деревьях. Незакоммиченные изменения в других отслеживаемых файлах перезаписываются содержимым целевого дерева, тогда как git их сохранил бы ([#2](https://github.com/inline0/pitmaster/issues/2)); сначала создайте коммит или сохраните изменения во временное хранилище.

### `merge`

Слить одну или несколько веток в текущий HEAD либо продолжить/отменить начатое слияние с конфликтами.

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

Вывод при успехе:

```
Merge successful.
```

Вывод при конфликте (в stderr, код выхода 1):

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

`-s` принимает `ours`, `ort` и `recursive`; `ort` и `recursive` используют слияние по умолчанию. С `-s` CLI выводит `Merge successful.` и завершает работу с кодом 0, даже если слияние остановилось из-за конфликтов ([#21](https://github.com/inline0/pitmaster/issues/21)), поэтому после этого проверьте `status`. `merge --continue` без выполняющегося слияния завершает работу с кодом 128. Слияние уже слитой ветки создаёт ещё один коммит слияния ([#6](https://github.com/inline0/pitmaster/issues/6)), а незакоммиченные изменения в отслеживаемых файлах перезаписываются, как и при `checkout`.

### `cherry-pick`

Применить коммит поверх текущего HEAD либо продолжить/отменить начатую операцию с конфликтами.

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

При успехе ничего не выводится. `--continue` и `--abort` без выполняющегося переноса коммита завершаются с кодом 128.

### `revert`

Создать коммит отмены либо продолжить/отменить начатую операцию с конфликтами.

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

При успехе ничего не выводится. `--continue` и `--abort` без выполняющейся отмены коммита завершаются с кодом 128.

### `rebase`

Переместить текущую ветку на другую ссылку.

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

При успехе ничего не выводится. `--continue`, `--skip` и `--abort` без выполняющегося перемещения базы выводят `fatal: no rebase in progress` и завершаются с кодом 128.

### `bisect`

Найти коммит, в котором появилось изменение, с помощью бинарного поиска.

```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` и `bad` выводят полный хеш следующего кандидата и переключаются на него. Когда остаётся один подозреваемый, тот же хеш выводится повторно: этот коммит и есть первый плохой коммит. В отличие от git, сводка «это первый плохой коммит» не выводится.

### `stash`

Сохранять и восстанавливать изменения в рабочем каталоге.

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

Сообщение задаётся аргументом после `push` или `save`; `-m` не поддерживается и будет сохранено как сообщение. `pop`, `apply` и `drop` всегда используют `stash@{0}`. Они выводят `Saved working directory to stash abc1234`, `Applied and dropped stash`, `Applied stash` и `Dropped stash`.

Вывод списка stash:

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

Если записей больше одной, `drop` и `pop` сейчас оставляют запись в списке ([#10](https://github.com/inline0/pitmaster/issues/10)), а `apply` перезаписывает незакоммиченные изменения в файлах, которых не касается stash ([#11](https://github.com/inline0/pitmaster/issues/11)).

### `blame`

Показать авторство каждой строки файла в HEAD.

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

Вывод:

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

Каждая строка содержит первые 8 символов хеша коммита и первые 30 символов идентификатора автора (`Name <email> timestamp timezone`) без дополнения пробелами.

### `grep`

Ищет содержимое файлов в текущем дереве HEAD.

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

Вывод:

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

Параметры должны идти перед шаблоном:

- `-i`, `--ignore-case`: поиск без учета регистра
- `-E`, `--extended-regexp`, `--regex`: трактовать шаблон как регулярное выражение PCRE

Выводится обычный `path:line:content` без цветов.

### `reflog`

Показывает записи reflog, начиная с самых новых.

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

Формат по умолчанию — `%gd: %gs` (`HEAD@{0}: commit: Add feature`). Поддерживаются заполнители: `%gd` и `%gD` (селектор), `%gs` (сообщение), `%H` и `%h` (полный и краткий новый хеш). Для ограничения количества принимаются `-n N`, `-nN` и `--max-count N`; `-n 0` выводит все записи.

Репозитории, созданные с помощью `pitmaster init`, не записывают reflog, если в `.git/config` параметру `core.logallrefupdates` не задано значение `true` ([#8](https://github.com/inline0/pitmaster/issues/8)), поэтому там `reflog` ничего не выводит, пока это не будет настроено.

### `refs`

Выводит все ссылки с их хешами.

```bash
pitmaster refs
```

Вывод:

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

Хеши выводятся полностью.

### `reset`

Сбрасывает HEAD на указанный коммит.

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

Требуется ревизия. Вывод:

```
HEAD is now at abc1234
```

### `init`

Инициализирует новый репозиторий. Это единственная команда, для которой не нужен существующий репозиторий.

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

Вывод:

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

`--object-format` принимает `sha1` (по умолчанию) и `sha256`.

## Коды завершения

| Код | Значение |
|------|---------|
| 0 | Успешное выполнение |
| 1 | Ошибка команды: ошибка использования, неизвестная команда, неудачная операция (`error: <message>`) или слияние, остановленное из-за конфликтов |
| 128 | Не репозиторий git (`fatal: <message>`), неизвестный аргумент `log` или `--continue` / `--abort` / `--skip`, когда операция не выполняется |
