Git hooks 이란? (+ Husky + lint-staged)

Maria Kim·2022년 6월 26일
5
post-thumbnail

1. Git hook

Github 공식문서 - Git Hooks 설명

1-1 Git hook 이란 ?

Git 에서 어떤 이벤트가 생겼을 때 자동으로 특정 스크립트를 실행할 수 있게 함.

1-2 종류

Git hook 의 종류는 많지만 주로 활용할 hook 을 위주로 아래 정리함.

1-2-1 클라이언트 훅

  • pre-commit
    • 실행 시점
      • commit 시 가장 먼저 호출됨
      • commit 메세지 작성하기 전에 호출됨
    • 용도
      • commit 하는 Snapshot 점검
      • 커밋 할 때 꼭 확인해야 하는 부분이 있는 경우
      • lint 로 코드 스타일을 검사
      • 라인 끝의 공백 문자를 검사
      • 새로 추가한 코드에 주석을 달았는지
      • 테스트 확실히 했는지
    • Exit 코드가 0 이 아니면 커밋 취소
      • git commit --no-verify 실행 시 일시적으로 생략 가능
  • prepare-commit-msg
    • 실행시점
      • Git이 commit 생성 - prepare-commit-msg - 편집기를 실행하기 전
      • 사람이 커밋 메세지를 수정 전 + 프로그램이 커밋 메시지를 손보고 싶을 때
    • Argumnet : 커밋 메세지가 들어 있는 파일의 경로, 커밋의 종류
    • 용도
      • commit 메세지를 자동으로 생성하는 commit 에 이용
      • commit 메세지에 Templete 적용 | Merge 커밋 | Squash 커밋 | Amend 커밋
  • commit-msg
    • 실행 시점
      • 최종적으로 commit 이 완료되기 전 → 프로젝트 상태 | 커밋 메세지 검증
    • Argument : 커밋 메시지가 들어 있는 임시 파일의 경로
    • 0 이 아닌 값을 반환하면 커밋 x
  • post-commit
    • 실행 시점
      • commit 완료 후
    • Argument : x
      • 커밋 해시 정보는 git log -1 HEAD 명령으로 가져올 수 있음
    • 용도
      • 커밋 된 것을 누군가 or 다른 프로그램에게 알릴 때 사용

기타 hook

  • pre-rebase
    • 실행 시점
      • Rebase 하기 전에 실행
    • 0 이 아닌 값을 반환하면 Rebase 취소
    • 이용 예시)
      • 이미 Push 한 커밋을 Rebase 하지 못하게 할 수 있음
  • post-rewrite
    • 시행시점
      • 커밋을 변경하는 명령 실행 시(ex)git commit --amend 이나 git rebase) 실행
    • git filter-branch 는 해당 x
    • Argument: 커밋을 변경하게 한 명령, stdin 으로 변경된 커밋 목록이 전달
    • 용도
      • post-checkout 이나 post-merge 훅과 비슷
      • 디렉토리에서 할 일이 있을 때 - 용량이 크기나 | Git이 관리하지 않는 파일을 옮기거나 | 문서를 자동으로 생성
  • post-merge
    • 실행되는 시점
      • Merge가 끝난 후 실행
    • 용도
      • 파일 권한같이 Git이 추적하지 않는 정보를 관리하는 데 사용
      • merge로 Working Tree가 변경될 때 → Git이 관리하지 않는 파일이 원하는 대로 잘 배치됐는지 검사
  • pre-push
    • 실행 시점 :
      • git push 명령을 실행하면 동작
      • Remote 정보를 업데이트하고 난 후 → pre-push → Remote 데이터를 전송
    • Parameter : Remote 이름과 주소
      • stdin 을 통해 업데이트할 해시 리스트를 전달받는다
    • 용도 :
      • Push 하기 전에 커밋이 유효한지 확인하는 용도
    • 0 이 아닌 값을 반환 시 Push 중지

1-2-2 서버 훅

  • Push 전후에 실행된다
  • Push 전에 실행되는 훅이 0이 아닌 값을 반환 →해당 Push는 거절 → 클라이언트는 에러 메시지를 출력
  • 아주 복잡한 Push 정책도 가능
  • pre-receive
    • 실행 시점 :
      • Push 하면 가장 처음 실행되는 hook
    • 표준 입력(STDIN)으로 Push 하는 Refs의 목록을 입력받음
    • 0이 아닌 값을 반환하면 해당 Refs가 전부 거절
    • 용도 :
      • Fast-forward Push가 아니면 거절
      • 브랜치 Push 권한을 제어
      • 관리자만 브랜치를 새로 Push 하고 삭제할 수 있고 일반 개발자는 수정사항만 Push 할 수 있게
  • update
    • 각 브랜치마다 한 번씩 실행된다는 것을 제외하면 pre-receive 스크립트와 거의 같음
      • ex) 1 번에 n개 브런치 push → pre-receive = 1번 실행 + update = 브랜치마다 실행
    • Argument:
      • 표준 입력(STDIN) x
      • 브랜치 이름, 원래 가리키던 SHA-1 값, 사용자가 Push 하는 SHA-1 값
    • 0이 아닌 값을 반환 → 해당 Refs만 거절되고 나머지 다른 Refs는 상관없음
  • post-receive
    • 실행 시점 :
      • Push 한 후에 실행
    • 용도
      • 사용자나 서비스에 알림 메세지를 보낼 수 있다.
      • 메일링리스트에 메일을 보내기
      • CI(Continuous Integration) 서버 | Ticket-tracking 시스템의 정보를 수정
      • Ticket을 만들고, 수정하고, 닫을 수 있다
      • 표준 입력(STDIN)으로 Refs 목록이 넘어감
        • 커밋 메시지도 파싱 가능
    • 이 스크립트가 완전히 종료할 때까지 클라이언트와의 연결은 유지되고 Push를 중단시킬 수 없다 → 이 스크립트로 시간이 오래 걸릴만한 일을 할 때는 조심해야 한다.

1-3 Git Hook 의 Argument & 자주 사용되는 명령어

commit-msg-file (커밋 메시지 파일)

commit-source (커밋되는 파일)

sha-1 (커밋 번호 - 수정하는 커밋일 때)
  • git rev-parse --abbrev-ref HEAD : HEAD가 가리키는 커밋의 해시 넘버를 가져오고, 그 넘버가 가리키는 브랜치 이름을 가져오라는 뜻

2. Husky

2-1 Husky 란?

git-hook 제어를 간편하게 하기 위해 사용

2-2 이용 방법

Husky 공식 문서

2-2-1 권장하는 자동 설치 방법

npx husky-init && npm install       # npm
npx husky-init && yarn              # Yarn 1
yarn dlx husky-init --yarn2 && yarn # Yarn 2+
pnpm dlx husky-init && pnpm install # pnpm
  • 설치되는 내용 : husky 설치 + package.json 수정 + pre-commit 훅 샘플 생성

  • package.json 설정

  "scripts": {
    ...
    "prepare": "husky install"
  },

2-2-2 hook 추가 방법

  1. husky add .

예시
npx husky add .husky/pre-commit "yarn yarn lint-staged"

  1. 직접 파일 추가

2-3 적용한 코드

2-3-1 pre-commit 파일 - lint-stage 실행 코드

위치 : .husky/pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

yarn lint-staged

2-3-2 prepare-commit-msg 파일 - [프로젝트 이름 및 브랜치 이름] 자동 적용 코드

위치 : .husky/prepare-commit-msg

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3

BRANCH_NAME=`git rev-parse --abbrev-ref HEAD`
PROJECT_NAME=''
PREFIX=''

if [[ "${BRANCH_NAME}" == *"/"* ]];then
    PROJECT_NAME=`echo ${BRANCH_NAME} | cut -d '/' -f1`
    PREFIX=`echo PREFIX ${BRANCH_NAME} | cut -d '/' -f2`
fi

FIRST_LINE=`head -n1 ${COMMIT_MSG_FILE}`

if [[ ${PROJECT_NAME} == '' ]]; then
    exit
fi

if [ -z "$FIRST_LINE" ]; then
    sed -i ".bak" "1s/^/[$PROJECT_NAME] $PREFIX : /" ${COMMIT_MSG_FILE}
fi

[참고 사이트]

Git hook 으로 Commit message 설정

git argument & shell 용어 정리

3. lint-staged

3-1 lint-staged 란?

stage 상태(변경 사항만)의 git 파일에 대해 lint와 우리가 설정해둔 명령어를 실행하기 위해 사용

https://github.com/okonet/lint-staged#readme

3-2 이용 방법

  1. lint-staged 설치
# npm
npm install --save-dev lint-staged
# yarn
yarn add -D lint-staged
  1. package.json 설정

ts/tsx 의 경우 prettier 및 eslint 적용 시 아래 코드 설정

  "lint-staged": {
    "*.{ts,tsx}": [
      "prettier --write",
      "eslint --fix"
    ]
  },
profile
Frontend Developer, who has business in mind.

0개의 댓글