husky로 commit-msg 관리하기
git actions로 커밋 메시지를 관리하는 것에 이어서 husky의 commit-msg hooks를 활용하여 올바른 커밋 컨벤션을 지키지 않고 커밋을 했을 시 커밋을 막는 방법에 대해 알아보았습니다.
1.Git Hooks란?
Git Hooks는 Git과 관련한 어떤 이벤트가 발생할 시에 특정 스크립트를 실행하는 기능입니다. 훅은 크게 클라이언트 훅과 서버 훅으로 나뉘게 되는데 클라이언트 훅은 commit, merge 가 발생하거나 push가 발생하기 전 클라이언트에서 발생하는 훅입니다. 서버 훅은 Git repository로 push가 발생했을 때 서버에서 실행하는 훅입니다.
2. 레포지토리 생성 후 husky 모듈 설치하기
테스트용 레포지토리를 생성한 후 npm init으로 package.json파일을 활성화 한 뒤에 husky 모듈을 설치합니다.
https://typicode.github.io/husky/#/
Husky - Git hooks
typicode.github.io
공식 문서를 참고하여 모듈을 설치하겠습니다.
npx husky-init && npm install # npm
npm 방식으로 설치했을 때 .husky 디렉터리가 생성되는 것을 확인할 수 있습니다.
3. commit-msg hook 등록하기
.husky 디렉터리 내부에 pre-commit hook이 기본적으로 생성되어있습니다. pre-commit은 커밋 직전에 실행되는 hook입니다. pre-commit hook을 사용하지 않으신다면 삭제하시고 진행하시면 됩니다.
저는 커밋 메시지를 확인하는 스크립트를 활용해아 하므로 commit-msg 훅을 추가하도록 하겠습니다.
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
npx husky add .을 사용하여 hook을 추가할 수 있습니다.
hook을 추가 한 뒤 상위 경로에 check-commit.sh 파일을 root 경로에 생성하였습니다. 생성한 check-commit.sh 파일 내부에 커밋 메시지 처리에 대한 쉘 스크립트 코드를 작성합니다. 저는 커밋 메시지의 타이틀이 feat | fix | docs | style | test | refactor | chore로 시작하는지 확인하는 정규식으로 조건 처리를 하였습니다.
//check-commit.sh
// check-commit.sh
MSG_FILE=$1
COMMIT_MSG="$(cat $MSG_FILE)"
# Initialize constants here
export REGEX='^(feat|fix|docs|style|refactor|test|chore):*.+$'
export ERROR_MSG="커밋 메세지를 컨벤션에 맞게 작성해주세요."
if [[ $COMMIT_MSG =~ $REGEX ]]; then
exit 0
else
echo "Bad commit : $COMMIT_MSG" | head -n 1
echo $ERROR_MSG
exit 1
fi
다시 commit-msg hook 파일로 돌아와 커밋이 실행되면 check-commit.sh가 실행되도록 하는 내용으로 변경합니다.
//commit-msg
// commit-msg
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
./check-commit.sh $1
4. .git/hooks/ 디렉터리에서 commit-msg파일 생성
작업 중인 프로젝트를 확인해보면. git이라는 디렉터리를 확인할 수 있습니다.
. git 디렉터리 내부의 hooks 디렉터리로 이동 후 내용을 확인해보면. sample파일들을 확인할 수 있는데 commit-msg.sample hook을 복사하여 commit-msg라는 이름으로 생성합니다. hooks 디렉터리 내부의 hook들은. sample을 지우게 되면 각 상황에 hook이 바로 적용되게 됩니다.
이 상태에서 커밋을 진행하면 Permission denied라는 메시지가 출력됩니다.
chmod 755 check-commit.sh
터미널에 chmod를 활용하여 check-commit.sh파일에 대한 권한을 부여해주게 되면 정상적으로 hook이 동작하는것을 확인할 수 있습니다.