기고자:박서정
‘A Commit Message 잘못 입력했습니다.
그러나 누구인지, 누구나 종종 전략과 다른 커밋 메시지를 잘못 입력하는 등의 실수를 할 수도 있다.
Git에는 이러한 문제를 사전에 방지하고 보다 편리한 협업을 지원하는 기능이 있다.
이번 세션을 통해 그 기능인 Git Hooks를 조사하려고 한다.
1. Git Hooks 배우기
1-1. Git Hooks 개념
Git Hooks는 Git에서 이벤트 발생때, 원하는 작업을 특정 스크립트에서 실행할 수 있도록 하는 기능이다.
Git Hooks 공식 문서
1-2. Git 후크의 종류
Git Hooks는 주로 클라이언트 후크, 서버 후크로 나뉩니다.
클라이언트 후크는 commit, merge 이벤트와 관련하여 발생하기 전에 클라이언트에서 실행되는 후크이며, 서버 후크는 git의 repository에서 push가 발생했을 때 서버에서 실행하는 후크입니다.
Client Git Hooks
분류 | 후크 | 발생 시점 |
커밋 워크플로 후크 | 사전 커밋 | commit 실행 전 |
prepare-commit-msg | 커밋 메시지를 만든 후 편집기를 실행하기 전에 | |
commit-msg | commit message 완료 후 commit 최종 완료 전 | |
post-commit | 커밋 완료 후 | |
이메일 워크플로 후크 | applypatch-msg | git am 명령을 실행 한 후 첫 번째 |
pre-applypatch | 패치 적용 후 실행 (중단 가능) | |
post-applypatch | git am 명령 실행 후 끝 (중단 불가) | |
기타 클라이언트 후크 | pre-rebase | rebase 전에 |
post-rewrite | git commit -amend, git rebase 등의 커밋 변경 명령을 실행 한 후 | |
post-merge | merge 완료 후 | |
pre-push | git push 실행 후 원격으로 데이터 전송 전 (중단 가능) |
Server Git Hooks
분류 | 후크 | 발생 시점 |
서버 후크 | pre-receive | 푸시 실행 후 첫 번째 |
update | 푸시 실행 후 각 브랜치에 대해 한 번 실행 | |
post-receive | 푸시 완료 후 실행 |
2. Git Hooks 사용
2-1. Git Hooks 사용법
원하는 Git Hooks를 사용하려면 프로젝트 .git/hooks 디렉토리 내에 설정하고 싶은 후크명으로 스크립트를 보존하면 된다.
만약 커밋을 하기 전에 특정 메시지를 띄우고 싶다면 다음과 같이 진행한다.
// 경로로 이동
$ cd .git/hooks/
// 훅이름 file 생성
$ touch pre-commit
// 훅 실행 시점에서 실행시킬 코드 작성
$ vi pre-commit
# pre-commit 파일
# 'Commit message: (MJU-이슈번호) 메시지' 를 출력시키기
echo 'Commit message: (MJU-이슈번호) 메시지'
# Exit 코드가 0이 아니면 커밋 취소
exit 0
2-2. Git Hooks를 공유하는 방법
위와 같이 만든 Git Hooks를 팀 구성원과 공유하려는 경우 스크립트는 모두 .git 파일에 있으므로 git에 파일이 나타나지 않습니다.
그 문제를 해결하고 Git Hooks의 제어를 단순화하기 위해 Husky를 사용하면 된다.
# Husky ver 6 기준
# husky 설치
npx husky-init && npm install
# package.json 설정
{
"scripts": {
...
"prepare": "husky install"
},
}
# 훅 추가
npx husky add .husky/(hook) '(code)'
3. Git Hooks 활용
3-1. 커밋 메시지 형식 검증
커밋 메시지 규칙을 “(MJU-Issue Number) message” 형식으로 지정하면 입력한 커밋 메시지가 필요합니다.
정규식과 일치하는지 확인에서 푸시가 이루어지는 것을 관리하면 좋을 것이다.
그러므로 이러한 경우 commit-msg 후크를 이용하면 된다.
$ cd .git/hooks/
$ touch commit-msg
$ vi commit-msg
# commit-msg 파일
# 원하는 정규식
$regex = /^\(MJU-(0-9)+\)(\d\D)*refs(\s)?-(\s)?.*/
def check_message_format
# ARGV는 commit message가 들어 있는 임시 파일 경로
message_file = ARGV(0)
# 위의 경로에서 commit message를 받아온다
message = File.read(message_file)
if !
$regex.match(message)
puts "(POLICY) 잘못된 커밋 메시지 형식입니다.
"
puts "(RULE) (MJU-{issueTicketNumber}) \n\n /* message */ \n\n refs - {issueLink}"
exit 1
end
end
check_message_format
3-2. Branch에서 Issue 번호를 얻어 커밋 메시지 생성
Jira를 사용하는 경우 주로 branch 및 commit message 이슈 번호 관리를 통해 오류가 발생한 경우 신속하게 해결할 수 있도록 다음 규칙을 사용합니다.
Branch: feature/특정 이름 – 문제 번호 – 어떻게
예: feature/MJU-231-post
커밋 메시지: 특정 이름 – 문제 번호 커밋 내용
예: MJU-231 게시물 업로드 API 추가
이와 같이 commit 할 때마다 작성해야 하는 message 는 실수를 유발하기 쉽고, 무엇보다도 귀찮은 것의 하나이다.
따라서 이것을 Git Hooks prepare-commit-msg 후크을 사용하여 분기에서 문제 번호를 검색하고 커밋 메시지에 자동으로 적용할 수 있습니다.
$ cd .git/hooks/
$ touch prepare-commit-msg
$ vi prepare-commit-msg
#!
/bin/bash
# 만약, branch가 master, develop, release, hotfix인 경우 스킵
if ( -z "$BRANCHES_TO_SKIP" ); then
BRANCHES_TO_SKIP=(master develop release hotfix)
fi
# 브랜치 이름에서 이슈 번호 가져오기
BRANCH_NAME=$(git symbolic-ref --short HEAD)
BRANCH_NAME="${BRANCH_NAME##*/}"
JIRA_ID=`echo $BRANCH_NAME | egrep -o 'HD.-(0-9)+'`
BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP(@)}" | grep -c "^$BRANCH_NAME$")
BRANCH_IN_COMMIT=$(grep -c "$JIRA_ID" $1)
# 커밋 메시지에 이슈 번호가 적혀있는지 확인 후, 있다면 skip, 없다면 맨 앞에 이슈번호 추가
if ( -n $JIRA_ID ) && !
(( $BRANCH_EXCLUDED -eq 1 )) && !
(( $BRANCH_IN_COMMIT -ge 1 )); then
sed -i.bak -e "1s/^/$JIRA_ID /" $1
fi
여러 사람이 함께 하는 프로젝트일수록 체계적인 개발 룰은 서로의 코드를 보다 간단하게 파악하고 에러 발생시 신속하게 대처할 수 있도록 중요한 부분 중 하나라고 생각한다.
그러나 솔직히, 이것은 꽤 귀찮은 작업이며, 실수도 발생하기 쉽다는 문제가있다.
그러나 이것을 앞의 예처럼 프로젝트 내에서 Git Hooks를 활용하면 보다 체계적인 개발에 도움이 될 것 같다.
(References)