
# CLI 참조

Pitmaster에는 git 명령어 일부를 미러링하는 CLI이 포함되어 있습니다. 현재 작업 디렉터리의 저장소에서 작동합니다.

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

Composer 설치본에서는 스크립트가 `./vendor/bin/pitmaster`에 있으며, 0.2.11부터 그 위치에서 프로젝트의 자동 로더를 찾습니다. Pitmaster 저장소 자체를 체크아웃한 경우 `composer install` 후 `./bin/pitmaster`를 실행하세요. 아래 예제에서는 두 경로 중 어느 쪽이든 `pitmaster`을 사용합니다. 인수 없이 실행하면 명령어 목록을 출력합니다.

리비전은 `Repository::resolve()`와 같은 방식으로 해석됩니다. `HEAD`, 브랜치 및 태그 이름, 전체 ref 이름, 전체 해시, `~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`를 출력합니다. 경로 필터는 정확히 일치하는 파일 경로 하나를 대상으로 하며 제한 수의 5배에 해당하는 최신 커밋만 확인합니다([#7](https://github.com/inline0/pitmaster/issues/7)).

### `show`

커밋 세부 정보와 첫 번째 부모 커밋 기준 diff를 표시합니다.

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

stdout이 터미널이 아니어도 색상이 적용된 통합 diff를 출력합니다. 수정된 텍스트 파일은 `git diff`에 맞춰 표시됩니다. 새 파일, 삭제된 파일, 바이너리 파일, 이름이 변경된 파일 및 모드가 변경된 파일은 형식이 다릅니다([Diff](https://pitmaster.inline0.dev/ko/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
```

중단된 병합, cherry-pick, 되돌리기 또는 rebase를 완료할 때는 준비된 메시지가 사용되므로 `-m`이 필요하지 않습니다. 작성자와 커미터는 환경 변수, 상수 및 `.git/config`에서 확인하며, [시작하기](https://pitmaster.inline0.dev/ko/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)), 먼저 커밋하거나 stash하세요.

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

성공 시 아무것도 출력하지 않습니다. 진행 중인 cherry-pick이 없을 때 `--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`

현재 브랜치를 다른 ref 위로 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
```

성공 시 아무것도 출력하지 않습니다. 진행 중인 rebase가 없으면 `--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과 달리 "is the first bad commit" 요약은 출력하지 않습니다.

### `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자와 작성자 식별 정보(`Name <email> timestamp timezone`)의 앞 30자가 공백으로 채우지 않은 채 표시됩니다.

### `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`로 생성한 저장소는 `.git/config`에서 `core.logallrefupdates`을 `true`로 설정하지 않으면 reflog를 기록하지 않습니다([#8](https://github.com/inline0/pitmaster/issues/8)). 따라서 설정하기 전까지 그곳에서 `reflog`은 아무것도 출력하지 않습니다.

### `refs`

모든 ref와 해당 해시를 나열합니다.

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