티스토리 뷰
Conventional Commits?
커밋 메세지에 사용자와 기계 모두가 이해할 수 있는 의미를 부여하기 위한 스펙
명확한 커밋 히스토리를 생성하기 위한 간단한 규칙을 제공
커밋 히스토리를 이용하여 더 쉽게 자동화된 도구를 만듦
이 컨벤션은 커밋 메세지에 신규 기능 추가, 문제 수정, 커다란 변화가 있음을 기술함으로써 유의적 버전(Sementic Versioning)과 일맥상통
git 으로 commit 시에 일괄된 양식을 유지 → 그 양식을 바탕으로 버전 관리나 Change Log 를 자동으로 만들 수 있음
커밋 메시지 구조
<타입>[적용 범위(선택 사항)]: <설명>
[본문(선택 사항)]
[꼬리말(선택 사항)]Git hook에 Conventional Commit 적용하기
Commit 메시지를 아름답고 정갈하게 유지하기 위해 conventional commit을 git hook에 적용하는 과정을 소개하려고 한다.
1. 패키지에 husky 적용하기
husky 가 뭔가요?
husky는 git hook을 손쉽게 제어하도록 도와주는 npm 라이브러리이다.
git hook?
git을 쓰다가 특정 이벤트(커밋할 때, 푸시할 때 등등)가 벌어졌을 때, 그 순간에 ‘갈고리’를 걸어서 특정 스크립트가 실행되도록 도와주는 것!
물론 husky를 쓰지 않더라도 git hook을 설정할 수 있는 공식적인 방법은 따로 있다..git/hooks 폴더에 들어가서 스크립트를 작성하면 된다.
그러나 .git/hooks 폴더 안에 스크립트 파일을 넣게 되면 그 파일은 git에 기록되지 않아서 따로 관리해야 한다는 단점이 있다.
또 git hook으로 npm scripts를 제어하고 싶을 때, 예컨대 npm test 등의 명령어를 써야 한다면 스크립트를 작성하는 게 번거롭다.
husky는 굳이 .git/hooks 폴더를 건드리지 않고도 git hook 스크립트를 제어할 수 있게 도와준다.
husky 설치하기
npx husky-init && npm installpackage.json 파일에는 아래와 같은 script가 추가된 것을 확인할 수 있다.
"prepare": "husky install"그리고, .husky 디렉토리가 생성된 것도 확인할 수 있다.
.husky/pre-commit 파일이 생성되었는데, 기존에 test 명령어가 있었기 때문에 이를 감지하여 아래와 같이 추가되었다.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm test2. 패키지에 commitlint 적용하기
commitlint 는 뭔가요?
commit 에 대한 lint를 확인하여 성공/실패를 리턴해주는 도구이다.
commitlint 설치하기
npm install -D @commitlint/cli @commitlint/config-conventionalcommitlint config 추가하기
루트 디렉토리에 commitlint.config.js 파일을 추가해준다.
module.exports = { extends: ['@commitlint/config-conventional'] };commitlint의 기본 컨벤션
module.exports = {
    parserPreset: 'conventional-changelog-conventionalcommits',
    rules: {
        'body-leading-blank': [1, 'always'],
        'body-max-line-length': [2, 'always', 100],
        'footer-leading-blank': [1, 'always'],
        'footer-max-line-length': [2, 'always', 100],
        'header-max-length': [2, 'always', 100],
        'subject-case': [
            2,
            'never',
            ['sentence-case', 'start-case', 'pascal-case', 'upper-case'],
        ],
        'subject-empty': [2, 'never'],
        'subject-full-stop': [2, 'never', '.'],
        'type-case': [2, 'always', 'lower-case'],
        'type-empty': [2, 'never'],
        'type-enum': [
            2,
            'always',
            [
                'build',
                'chore',
                'ci',
                'docs',
                'feat',
                'fix',
                'perf',
                'refactor',
                'revert',
                'style',
                'test',
            ],
        ],
    },
};3. commit-msg hook 적용하기
commit-msg 훅은 최종적으로 커밋이 완료되기 전에, 프로젝트 상태나 커밋 메시지를 검증하기 위해 사용한다.
husky hook 에 commit-msg 추가하기
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'이렇게 하면, commitlint 의 컨벤션으로 husky가 commit-msg 훅을 실행한다.
commit-msg hook 동작 확인하기
그럼 어디한번 동작하는지 확인해볼까.
우선 잘못된 커밋 메시지를 넣어보자.
git commit -m 'hello-world'
두둥탁- 짠-.
subject 가 비어있으면 안되고, type 도 비어있으면 안된다고 지적해준다.
이번엔 제대로된 메시지를 넣어보자.
git commit -m 'test: hello world'
아주아주 잘되는 것을 확인할 수 있다.
git kraken 에서 동작 확인하기
야심차게 git kraken 에서도 잘못된 커밋메시지로 커밋을 시도해봤다.
그런데 웬걸 😱

커밋이 너무 잘된다... 젠장.
commit-msg 훅 로그를 들여다보니.
별 말도 없다. 어쩌란 건지..
그래서 issue tracking 을 해보니, 아래와 같은 문제점이 있다고 한다.
- 버전 7.5부터 Gitkraken은 - core.hookspath를 지원하지 않으며- .git/hooks을 사용할 것입니다.이 문제를 해결하는 방법은 매우 간단합니다.- .git/hooks에서 허스키의 디렉토리로의 심볼릭 링크를 만듭니다.
 최선의 방법은 아니지만 내가 찾은 유일한 방법입니다.- $ rm -rf .git/hooks && ln -s ../.husky .git/hooks- You may add this command to your package.json - postinstallscript, alongside- husky install:
- { "scripts": { "postinstall": "husky install && rm -rf .git/hooks && ln -s ../.husky .git/hooks" } }
- From you project root: 
- 참고로, git 공식 문서에 이런 글이 있다. 
 By default the hooks directory is- $GIT_DIR/hooks, but that can be changed via the- core.hooksPathconfiguration variable.
- husky v5부터는 기본 git의 경로 ( - .git/hooks)가 아닌 사용자 지정 후크 경로 (- .husky) 가 사용됩니다 . 이것은 로컬 git 구성- core.hookspath키 설정을 통해 수행됩니다.
하...
이렇게까지 해서 맥 Big Sur OS 에도 최적화되지 못한 채, 커밋 날릴때마다 7초 이상 기다리게 하더니, 이제는 깃훅 path 커스텀도 막아버리는 무례한 깃크라켄의 만행을, 돈을 내가면서 참아줘야 하는걸까.
결국 했다.
gitkraken 을 사용하지 않는 컨트리뷰터들을 위해 아래 postinstall script 는 추가하지 않고, 로컬에서만 .git/hooks 에 심볼링 링크를 걸어주는 것으로 끝냈다.
4. 컨벤션에 맞게 커밋하기
컨벤션에 맞게 커밋하는 것을 도와주는 commitizen cli 도구를 사용하려고 한다.
commitizen 설치하기
npm i -D commitizencommitizen 어댑터 구성하기
commitizen으로 커밋을 만들기 위한 방식은 어떤 어댑터를 사용하느냐에 따라 달라진다.
여기에서는 cz-conventional-changelog 어댑터 사용할 것이다.
npx commitizen init cz-conventional-changelog --save-dev --save-exact위 명령어는 아래 3가지를 수행한다.
- cz-conventional-changelog어댑터를 설치한다.
- 그리고 dev dependency에 추가한다.
- 아래처럼 config.commitizen을package.json에 추가한다.
"config": {
    "commitizen": {
      "path": "cz-conventional-changelog"
    }
  }이렇게 설정하면, 커밋하려고 할 때 사용할 어댑터를 commitizen에게 알려준다.
commitizen script 추가하기
package.json에 아래와 같은 script 를 추가한다.
husky와 함께 쓰는 경우는 commit 명령어로 쓰지 말라는 경고가 있으니 주의하자.
"scripts": {
...
    "cm": "cz"
  }npx cz
or
npm run cm위 명령어를 통해 commitizen으로 커밋을 정형화된 포맷으로 할 수 있다.
그러나, git commit 명령어를 실행시켰을 때, commitizen 을 먼저 실행시킬 수 있도록 설정한다면, 굳이 이 명령어를 쓰지 않아도 된다.
커밋 시 commitzen 실행하도록 husky에 훅 추가하기
npx husky add .husky/prepare-commit-msg 'exec < /dev/tty && node_modules/.bin/cz --hook || true'commitizen 으로 커밋하기
git commit- 원하는 type 선택하기 
- 필요한 설명 입력하기 
- 이슈에 연결하기(선택사항) 
- 결과 확인 
5. commitizen 어댑터 변경하기 (선택사항)
엇, 그런데 commitizen 에서 제공하는 어댑터 중에 commitlint 를 사용하는 것이 있다는 것을 뒤늦게 알아버렸다.
위에 commit-msg 훅에서 commitlint를 사용하고 있어서, 일관성 유지에는 commitlint를 사용하는 것이 좋을 것 같아서 commitlint 어댑터로 바꿔보겠다.
기존 어댑터 삭제하기
위에서 추가해준 cz-conventional-changelog 어댑터를 삭제해주자.
npm uninstall -D cz-conventional-changelog새로운 어댑터 추가하기
npm i -D @commitlint/promptcommitizen 어댑터 설정 변경하기
아래처럼 package.json 에서 config.commitizen 을 변경해주자.
"script": {
...
"cm": "git-cz"
},
"config": {
    "commitizen": {
       "path": "./node_modules/@commitlint/prompt"
    }
  }변경된 어댑터 동작 확인하기
git commit
전혀 다른 방식으로 커밋이 진행되는 것을 확인할 수 있다.
마치며.
마지막에 바꾼 어댑터.
써보니까 너무 별로여서 다시 기존 어댑터로 롤백했다.
ㅎㅎ..
그로부터 며칠 뒤.prepare-commit-msg 훅을 뻈다.
이제 대충 커밋 컨벤션이 머리에 있는데 저 과정으로 커밋하는게 영 불편했다.
그래서 필요한 경우에는 npm run cm 으로 실행시키는 것으로.
References
https://www.huskyhoochu.com/npm-husky-the-git-hook-manager/
https://git-scm.com/book/ko/v2/Git맞춤-Git-Hooks
https://blog.cookapps.io/guide/conventional-commits/
https://www.conventionalcommits.org/ko/v1.0.0/
https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines