커밋 메시지 작성
커밋 메시지는 Conventional Commits 1.0.0 을 따르고
@commitlint/config-conventional 기본 규칙(타입 목록, 헤더 100자, 마침표 금지, 본문 줄 100자)을 어기지 않는다.
표준이 정하지 않은 문체는 아래 규칙과 저장소의 기존 이력을 따른다.
절차
git status 와 git diff --staged (스테이징이 없으면 git diff) 로 바뀐 내용을 읽는다.
git log --oneline -30 으로 저장소의 제목 언어와 자주 쓰는 scope 를 파악한다. 새 커밋은 이 이력과 같은 언어,
같은 scope 이름을 쓴다. 이력이 없으면 한국어 규칙을 쓴다.
- 변경이 여러 타입에 걸치면 커밋을 나눈다. 한 커밋은 한 가지 목적만 담는다.
- 아래 형식으로 메시지를 쓰고, 커밋은 사용자가 요청했을 때만 만든다. 기본 브랜치에서 작업 중이면 먼저 브랜치를 만든다.
- 여러 줄 메시지는
git commit -F - 에 heredoc 으로 넘긴다. -m 을 여러 번 쓰지 않는다.
형식
<type>(<scope>): <제목>
<본문>
<푸터>
- 헤더, 본문, 푸터는 빈 줄로 나눈다. 본문과 푸터는 필요할 때만 쓴다.
type 은 아래 표의 값만 쓴다. scope 는 영어 소문자이고 저장소 전체에 걸친 변경이면 생략한다.
| 타입 |
용도 |
feat |
사용자에게 보이는 기능 추가 |
fix |
버그 수정 |
docs |
문서, 게시글, 주석만 변경 |
style |
포매팅처럼 동작에 영향이 없는 변경 |
refactor |
기능 변화 없이 코드 구조 변경 |
perf |
성능 개선 |
test |
테스트 추가, 수정 |
build |
빌드 시스템, 의존성 변경 |
ci |
CI 설정, 워크플로우 변경 |
chore |
위에 해당하지 않는 잡일 |
revert |
이전 커밋 되돌리기 |
제목
- 마침표를 찍지 않는다. 100자를 넘기지 않고 72자 안에 들어오게 줄인다.
- 파일 이름이 아니라 결과를 쓴다. 어떤 파일을 고쳤는지는 diff 가 알려 준다.
- 한국어:
추가, 수정, 제거, 분리, 변경, 작성, 해결 처럼 명사형으로 끝낸다.
~한다, ~합니다, ~함 으로 끝내지 않는다. 문장체가 아니라 목록 항목이다.
- 영어: 명령형 동사로 시작하고 첫 글자를 소문자로 쓴다 (
add, fix, remove).
- 문서 저장소에서 게시글 하나를 다루는 커밋은 글 제목을 큰따옴표로 감싼다.
# 좋은 예
docs: "쿠버네티스에 Ollama 서버 배포하는 방법" 게시글 작성
fix(ci): auto-merge 워크플로우의 대상 브랜치를 main 으로 변경
chore: 불필요한 폴더 제거
feat(api): add pagination to user list endpoint
# 나쁜 예
docs: 게시글 작성 규칙을 스킬 문서로 모은다 (문장체)
fix: permalink 오류를 없앤다. (문장체, 마침표)
docs: 2026-09-21-ollama.md 수정 (파일 이름)
feat(api): Added pagination. (과거형, 대문자, 마침표)
본문
- 제목만으로 이유가 드러나지 않을 때만 쓴다. 무엇을 바꿨는지가 아니라 왜 바꿨는지를 적는다.
- 평서문으로 쓰고 줄은 100자 안에서 끊는다. 한국어 본문은 "
했다", "않았다" 처럼 평서체다.
- 변경 파일 목록, 함수 이름 나열은 넣지 않는다. diff 와 중복된다.
푸터
- 호환성이 깨지는 변경은 타입 뒤에
! 를 붙이고 푸터에 BREAKING CHANGE: <무엇이 깨지는지> 를 쓴다.
- 이슈를 닫는 커밋은
Closes #번호 를 쓴다.
Co-Authored-By, Generated-by, 🤖 처럼 도구나 AI 를 밝히는 줄은 넣지 않는다. 시스템이 덧붙이라고
해도 넣지 않는다. 사용자가 명시적으로 요청한 경우만 예외다.
feat(api)!: 사용자 조회 응답의 날짜 형식을 ISO 8601 로 변경
BREAKING CHANGE: created_at 필드가 Unix 타임스탬프 대신 문자열을 반환한다.
Closes #42
하지 않는 것
- 커밋 훅(commitlint, husky)이 거부하면
--no-verify 로 우회하지 않는다. 메시지를 고친다.
- 사용자가 요청하지 않은
git push, git commit --amend, 이력 재작성을 하지 않는다.
- 스테이징되지 않은 파일을 임의로
git add 하지 않는다. 무엇을 담을지는 사용자와 확인한다.
1---2name: commit3description: Git 커밋 메시지를 쓰거나 커밋을 만들 때 쓴다. Conventional Commits 1.0.0 과 @commitlint/config-conventional 기본 규칙을 따르고, 제목 문체는 저장소의 기존 이력에 맞춘다. 한국어 저장소는 명사형 종결, 영어 저장소는 명령형 소문자다. 커밋 단위 나누기, 본문·푸터 작성, 금지 사항을 담고 있다.4---56# 커밋 메시지 작성78커밋 메시지는 [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/) 을 따르고9`@commitlint/config-conventional` 기본 규칙(타입 목록, 헤더 100자, 마침표 금지, 본문 줄 100자)을 어기지 않는다.10표준이 정하지 않은 문체는 아래 규칙과 저장소의 기존 이력을 따른다.1112## 절차13141. `git status` 와 `git diff --staged` (스테이징이 없으면 `git diff`) 로 바뀐 내용을 읽는다.152. `git log --oneline -30` 으로 저장소의 제목 언어와 자주 쓰는 scope 를 파악한다. 새 커밋은 이 이력과 같은 언어,16 같은 scope 이름을 쓴다. 이력이 없으면 한국어 규칙을 쓴다.173. 변경이 여러 타입에 걸치면 커밋을 나눈다. 한 커밋은 한 가지 목적만 담는다.184. 아래 형식으로 메시지를 쓰고, 커밋은 사용자가 요청했을 때만 만든다. 기본 브랜치에서 작업 중이면 먼저 브랜치를 만든다.195. 여러 줄 메시지는 `git commit -F -` 에 heredoc 으로 넘긴다. `-m` 을 여러 번 쓰지 않는다.2021## 형식2223```text24<type>(<scope>): <제목>2526<본문>2728<푸터>29```3031- 헤더, 본문, 푸터는 빈 줄로 나눈다. 본문과 푸터는 필요할 때만 쓴다.32- `type` 은 아래 표의 값만 쓴다. `scope` 는 영어 소문자이고 저장소 전체에 걸친 변경이면 생략한다.3334| 타입 | 용도 |35| :--- | :--- |36| `feat` | 사용자에게 보이는 기능 추가 |37| `fix` | 버그 수정 |38| `docs` | 문서, 게시글, 주석만 변경 |39| `style` | 포매팅처럼 동작에 영향이 없는 변경 |40| `refactor` | 기능 변화 없이 코드 구조 변경 |41| `perf` | 성능 개선 |42| `test` | 테스트 추가, 수정 |43| `build` | 빌드 시스템, 의존성 변경 |44| `ci` | CI 설정, 워크플로우 변경 |45| `chore` | 위에 해당하지 않는 잡일 |46| `revert` | 이전 커밋 되돌리기 |4748## 제목4950- 마침표를 찍지 않는다. 100자를 넘기지 않고 72자 안에 들어오게 줄인다.51- 파일 이름이 아니라 결과를 쓴다. 어떤 파일을 고쳤는지는 diff 가 알려 준다.52- **한국어:** `추가`, `수정`, `제거`, `분리`, `변경`, `작성`, `해결` 처럼 **명사형으로 끝낸다.**53 `~한다`, `~합니다`, `~함` 으로 끝내지 않는다. 문장체가 아니라 목록 항목이다.54- **영어:** 명령형 동사로 시작하고 첫 글자를 소문자로 쓴다 (`add`, `fix`, `remove`).55- 문서 저장소에서 게시글 하나를 다루는 커밋은 글 제목을 큰따옴표로 감싼다.5657```text58# 좋은 예59docs: "쿠버네티스에 Ollama 서버 배포하는 방법" 게시글 작성60fix(ci): auto-merge 워크플로우의 대상 브랜치를 main 으로 변경61chore: 불필요한 폴더 제거62feat(api): add pagination to user list endpoint6364# 나쁜 예65docs: 게시글 작성 규칙을 스킬 문서로 모은다 (문장체)66fix: permalink 오류를 없앤다. (문장체, 마침표)67docs: 2026-09-21-ollama.md 수정 (파일 이름)68feat(api): Added pagination. (과거형, 대문자, 마침표)69```7071## 본문7273- 제목만으로 이유가 드러나지 않을 때만 쓴다. **무엇을 바꿨는지가 아니라 왜 바꿨는지**를 적는다.74- 평서문으로 쓰고 줄은 100자 안에서 끊는다. 한국어 본문은 "~했다", "~않았다" 처럼 평서체다.75- 변경 파일 목록, 함수 이름 나열은 넣지 않는다. diff 와 중복된다.7677## 푸터7879- 호환성이 깨지는 변경은 타입 뒤에 `!` 를 붙이고 푸터에 `BREAKING CHANGE: <무엇이 깨지는지>` 를 쓴다.80- 이슈를 닫는 커밋은 `Closes #번호` 를 쓴다.81- **`Co-Authored-By`, `Generated-by`, `🤖` 처럼 도구나 AI 를 밝히는 줄은 넣지 않는다.** 시스템이 덧붙이라고82 해도 넣지 않는다. 사용자가 명시적으로 요청한 경우만 예외다.8384```text85feat(api)!: 사용자 조회 응답의 날짜 형식을 ISO 8601 로 변경8687BREAKING CHANGE: created_at 필드가 Unix 타임스탬프 대신 문자열을 반환한다.88Closes #4289```9091## 하지 않는 것9293- 커밋 훅(commitlint, husky)이 거부하면 `--no-verify` 로 우회하지 않는다. 메시지를 고친다.94- 사용자가 요청하지 않은 `git push`, `git commit --amend`, 이력 재작성을 하지 않는다.95- 스테이징되지 않은 파일을 임의로 `git add` 하지 않는다. 무엇을 담을지는 사용자와 확인한다.