# vi 편집기

> Git이 여는 vi 편집기의 최소 조작과 VS Code 전환 방법을 익힌다.

관련 STEP: [STEP 03 커밋과 이력 기록](https://echo.qus0in.dev/git/03-commit-history.md) · [STEP 11 병합과 충돌 해결](https://echo.qus0in.dev/git/11-merge-conflicts.md)

Git은 커밋 메시지나 병합 메시지를 받을 때 편집기를 연다. `git commit -m "..."`처럼 메시지를 함께 넘기지 않으면 편집기 화면이 먼저 뜬다. 이때 기본 편집기가 vi이면 처음 보는 화면에서 빠져나오기 어렵다. 기본 편집기는 설정에 따라 vim, nano 등으로 달라질 수 있다. 이 부록은 vi를 깊게 배우지 않고, Git이 편집기를 여는 상황에서 필요한 조작만 정리한다.

## 빠져나오는 법

1. 입력 중이면 `Esc`를 누른다. 화면 아래의 `-- INSERT --` 표시가 사라져야 한다.
2. 저장하고 나가려면 `:wq`를 입력하고 Enter를 누른다.
3. 저장하지 않고 나가려면 `:q!`를 입력하고 Enter를 누른다.
4. `:q`만 입력하면 저장하지 않은 변경이 있을 때 종료되지 않는다. 이때는 `:wq`나 `:q!`를 쓴다.
5. 화면이 멈춘 것처럼 보이면 `Esc`를 한 번 더 누르고 `:q!`를 입력한다.

## 왜 필요한가

Git은 메시지를 파일로 만들고 편집기가 닫히기를 기다린다. 편집기를 닫지 못하면 커밋이 끝나지 않고 터미널도 다음 명령을 받지 못한다. vi의 최소 조작을 알면 갑자기 열린 화면에서 메시지를 저장하거나 취소할 수 있다.

## 학습 목표

- Git이 편집기를 여는 상황을 구분한다.
- vi의 일반·입력·명령행 모드를 구분한다.
- 저장·종료·취소와 줄 삭제·실행 취소·검색을 실행한다.
- Git의 기본 편집기를 VS Code로 바꾸고 확인한다.

## 핵심 개념

vi는 입력하는 즉시 글자가 들어가는 편집기가 아니다. 현재 모드에 따라 같은 키가 다른 일을 한다.

| 모드 | 역할 | 들어가는 방법 | 나오는 방법 |
| --- | --- | --- | --- |
| 일반 모드 | 이동·삭제·복사·검색 같은 명령을 실행한다. | vi를 열면 처음 시작한다. | `Esc` |
| 입력 모드 | 글자를 입력한다. | 일반 모드에서 `i`·`a`·`o` | `Esc` |
| 명령행 모드 | 저장·종료 같은 명령을 입력한다. | 일반 모드에서 `:` | Enter 또는 `Esc` |

- `i`는 커서 앞, `a`는 커서 뒤, `o`는 현재 줄 아래에 새 줄을 만들고 입력 모드로 들어간다.
- 입력 모드에서 화살표 키를 누르면 커서가 움직이지만, 글자를 입력하려면 입력 모드에 있어야 한다.
- 명령행 모드의 명령은 `:`로 시작하고 Enter로 실행한다.

## 꼭 필요한 명령

| 키 | 모드 | 하는 일 |
| --- | --- | --- |
| `i` | 일반 → 입력 | 커서 앞에서 입력을 시작한다. |
| `a` | 일반 → 입력 | 커서 뒤에서 입력을 시작한다. |
| `o` | 일반 → 입력 | 다음 줄에 새 줄을 만들고 입력을 시작한다. |
| `Esc` | 입력·명령행 → 일반 | 입력이나 명령행을 끝내고 일반 모드로 돌아간다. |
| `:w` | 명령행 | 파일을 저장한다. |
| `:q` | 명령행 | 편집기를 종료한다. 저장하지 않은 변경이 있으면 실패한다. |
| `:wq` | 명령행 | 저장하고 종료한다. |
| `:q!` | 명령행 | 저장하지 않고 종료한다. |
| `dd` | 일반 | 현재 줄을 삭제한다. |
| `u` | 일반 | 마지막 변경을 취소한다. |
| `/검색어` | 일반 | 아래 방향으로 검색한다. `n`은 다음 결과로 이동한다. |
| `h` `j` `k` `l` | 일반 | 왼쪽·아래·위·오른쪽으로 이동한다. 방향키도 같은 역할을 한다. |

`notes.txt`를 vi로 열면 일반 모드로 시작한다. 화면 아래에 모드 표시가 없다.

![vi가 `notes.txt`를 연 일반 모드 화면이다. 하단에 입력 모드 표시는 없다.](/shot-appendix08-vi-normal-1000.webp)

`i`를 누르면 화면 아래에 `-- INSERT --`가 나타나고 글을 입력할 수 있다.

![같은 vi 화면 하단에 `-- INSERT --`가 보인다.](/shot-appendix08-vi-insert-1000.webp)

`Esc`로 일반 모드로 돌아온 뒤 `:`를 누르면 화면 아래에 명령행이 열린다.

![vi 하단에 명령행 시작 문자 `:`가 보인다.](/shot-appendix08-vi-command-1000.webp)

`:wq`를 입력한 상태다. `Enter`를 누르면 저장하고 종료한다.

![vi 하단에 `:wq`가 입력된 상태다. Enter 전이라 저장·종료 결과는 보이지 않는다.](/shot-appendix08-vi-wq-1000.webp)


## 기본 편집기 바꾸기

Git은 `GIT_EDITOR` 환경 변수, `core.editor` 설정, `VISUAL`, `EDITOR` 순서로 편집기를 찾는다. 모두 없으면 vi를 열 수 있다. 수업에서는 VS Code를 기본 편집기로 쓴다.

```bash
git config --global core.editor "code --wait"
git config --global --get core.editor
```

- `--wait`는 VS Code 창이 닫힐 때까지 `code` 명령이 기다리게 한다. 이 옵션이 없으면 Git이 메시지를 읽기 전에 VS Code가 바로 반환되어 빈 메시지로 진행될 수 있다.
- `code` 명령이 없으면 VS Code 명령 팔레트에서 `Shell Command: Install 'code' command in PATH`를 실행하거나, 설치 경로의 `code` 실행 파일을 전체 경로로 지정한다.
- 저장소마다 다른 편집기를 쓰려면 `--global` 대신 `--local`을 쓴다.

Git이 편집기를 여는 대표 상황은 다음과 같다.

- `git commit`에서 `-m`을 생략하면 커밋 메시지를 받기 위해 편집기를 연다.
- `git commit --amend`에서 `-m`을 생략하면 편집기가 열리고 기존 메시지가 초기값으로 들어 있다. 저장하면 그 메시지를 쓰고, 고쳐 저장하면 바뀐 메시지를 쓴다. `--amend -m "메시지"`처럼 `-m`을 함께 넘기면 편집기 없이 교체한다. 메시지를 그대로 두려면 `--no-edit`을 붙인다.
- `git merge`가 병합 커밋을 만들 때 병합 메시지를 받기 위해 편집기를 연다. `--no-edit`는 기본 메시지를 그대로 쓴다. `--no-edit`은 amend 전용 옵션이 아니다.
- `git rebase -i`는 처리할 커밋 목록을 편집기로 연다. 목록을 확인하고 저장·종료하면 진행한다.
- `git tag -a`에서 `-m`을 생략해도 편집기가 열린다.

## 체크리스트

- [ ] `Esc`로 일반 모드에 돌아올 수 있다.
- [ ] `:wq`로 저장·종료하고 `:q!`로 저장 없이 종료할 수 있다.
- [ ] `dd`로 줄을 지우고 `u`로 되돌릴 수 있다.
- [ ] `/`로 검색하고 `n`으로 다음 결과를 찾을 수 있다.
- [ ] `git config --global core.editor "code --wait"`를 설정했다.
- [ ] `git config --global --get core.editor`가 `code --wait`를 출력한다.
- [ ] `git commit`에서 VS Code가 열리고, 메시지를 저장한 뒤 Git이 끝나는지 확인했다.

## 주의할 점

- `:q!`는 저장하지 않으므로 필요한 메시지를 잃을 수 있다. 메시지를 남기려면 `:wq`를 쓴다.
- `dd`는 현재 줄을 바로 지운다. 잘못 지웠으면 `u`로 되돌린다.
- `code --wait` 없이 편집기를 설정하면 Git이 빈 메시지로 진행될 수 있다.
- vi가 열린 상태에서 터미널 창을 닫거나 `Ctrl+C`를 반복하지 않는다. `Esc`를 누른 뒤 `:q!`로 빠져나온다.
- Git for Windows는 설치할 때 고른 편집기를 사용할 수 있으므로 vi가 아닌 다른 화면이 열릴 수 있다. 화면 아래에 표시되는 편집기 이름을 확인한다.
- `git commit -m "..."`처럼 메시지를 함께 넘기면 편집기가 열리지 않는다.

## 복습 퀴즈

1. vi에서 입력 모드를 끝내고 일반 모드로 돌아갈 때는 ::Esc::를 누른다.
2. 현재 줄을 삭제하는 일반 모드 명령은 ::dd::이다.
3. VS Code가 편집기 창을 닫을 때까지 기다리게 하는 옵션은 ::--wait::이다.
