Git Hooks 기초

59INU·2022년 12월 7일
0

깃 훅 사용하기

목록 보기
1/1
post-thumbnail

vscode 설정이 잘못된 줄 몰랐다. 린트를 설치했는데도 적용 안된 코드들이 리모트에 올라갔다. 테스트 코드를 쓰자! 고 했지만 커밋, 푸시 할 때 테스트 실행하는 건 늘 깜박한다. 실패하는 테스트는 나날이 쌓여가고 커버리지는 이상과는 멀다.

그러면 자동화를 할 때입니다.

무지성으로 커밋을 하려 해도 스테이징 파일들을 자동으로 린트로 검사해 고쳐주고, 커밋 메세지의 컨벤션을 상기시켜주며, 무지성으로 푸시를 하려 해도 자동으로 테스트를 실행하여 테스트 통과 전까지 푸시를 허락해주지 않는 혹독하고 편리한 세계로 가야된다.

githooks

Git에서 지원하는 기능. Git 이벤트 실행 전후에 자동으로 실행할 동작들을 미리 정의할 수 있다.

어디에 있고 어떻게 생겼나

내 git은 그런 거 없지 않고, git을 사용하고 있는 프로젝트의 루트 폴더마다 존재하는 .git 폴더 내부에는 git init 시점에 자동으로 hooks 폴더가 생성되며 그 내부에는 심지어 샘플 파일들이 만들어진다.

정의된 모든 훅을 생성하지는 않으나 보편적으로 사용되는 훅들은 거진 포함하고 있으므로, 샘플 파일을 통해 어떤 종류의 훅들이 있는지 살펴볼 만 하다.

언제 실행되나

Git book에 명시된 훅의 종류는 대략 30종에 이르지만 자주 쓰이는 혹은 친숙한 이벤트와 관련된 일부 훅들을 소개하면 아래와 같다.

  • git-commit

    • pre-commit
      커밋 작성 전 린트를 실행하여 소스 코드를 검사하는 경우에 흔히 쓰인다. (ex. lint-staged)
    • prepare-commit-msg
      커밋 메시지를 작성하는 과정에 관여할 때 주로 쓰인다. (ex. commitizen, gitmoji-cli)
    • commit-msg
      메시지 작성 완료 후 실제로 커밋이 저장되기 직전 단계에 실행된다. 만약 실행한 훅을 통과하지 못한다면 커밋은 최종적으로 저장되지 않는다.
      - post-commit
      커밋 저장이 완료된 후에 실행된다. api 호출을 통해 공유 채널 등에 노티를 줄 수도 있겠다.
  • git-push

    • pre-push
      push 이벤트가 발생하는 경우 리모트에 실제 push 가 완료되기 전에 실행된다. 이 훅을 사용해 테스트, 린트 등 프로젝트 상태에 따라 리모트 푸시를 제한할 수 있다.
  • Etc.

    • git-merge : post-merge
      브랜치 머지가 완료된 후 실행된다.
    • post-rewite
      git commit --amend, git rebase와 같이 기존 커밋을 변경하는 작업 완료 후 호출된다.

어떻게 쓰이나

gitmoji cli 는 컨벤션에 맞는 prefix에 따라 gitmoji를 추가해 커밋 메시지를 작성을 돕는 툴로, githooks의 prepare-commit-msg 훅을 사용해 구현되었다.
프로젝트에서 gitmoji -i 명령어를 통해 툴을 설치하면 .git/hooks 경로 내부에는 prepare-commit-msg 파일이 생성되는데 해당 파일을 열어보면 아래와 같은 스크립트를 확인할 수 있다

직접 만들어보자

실제로 실행이 되는지 커밋 이벤트로 실행되는 바보 같은 테스트 훅을 만들어보자

1. 파일 생성

훅 샘플들이 있는 .git/hooks 경로에 pre-commit 파일을 생성한다. 원한다면 샘플 파일명의 .sample을 제거하여 사용해도 된다.

2. 스트립트 작성

텍스트 에디터로, 위와 같이 단순히 문장을 출력하고 0을 반환하여 다음 작업을 이어나가게 하는 스크립트를 작성했다.

이제 실행하면 아마 전혀 안 된다.

3. 권한 설정

hooks 폴더를 다시 들여다 보자. ls -l 롱포맷으로 이름 외에 다른 정보들을 함께 출력해서 맨 앞에 보이는 권한 정보를 보자.

-[rwx][rwx][rwx] 패턴이며 대괄호 단위로 각각 사용자, 그룹, 다른 사용자의 권한을 나타낸다. r는 읽기 권한, w는 쓰기 권한, x는 실행 권한을 의미한다.

방금 만든 pre-commit 파일만 권한이 다르다. 방금 새로 만든 파일에는 사용자에게 읽기/쓰기 권한만 있고 실행 권한이 없다. 기왕 샘플 파일이 있으니 따라하기로 했다. 권한 숫자 표기법을 사용하면 샘플파일들의 권한은 755 이므로 pre-commit 파일도 동일한 권한으로 변경한다.

4. 실행

잘 된다.
다만 작업을 중단하지 않으므로, commit 명령어의 -m 옵션 사용 여부와 관계 없이 커밋 메시지를 작성하고 제출한 후에야 터미널을 확인할 수 있기 때문에 진짜로 커밋 전에 실행되었는지 모르겠다.

5. 작업 중단시키기

스크립트 실행 종료 시 1을 반환하여 다음 작업을 중단시키자.

커밋이 완료되지 않고 중단되었다.

깃훅의 공유

hooks 폴더가 자리한 디렉토리 .git/는 로컬 git 정보를 관리하는 장소이자 버전 컨트롤의 대상에서 제외된, 리모트에 공유하지 않는 정보다.

말인 즉슨 기본적으로 githooks는 공유되지 않는, 작업자의 로컬 설정이다.

어떻게 공유를 할까

보편적으로 사용하는 방법은 크게 분류해 아래 세가지 정도인 것 같다.

  • symlink
    버전 컨트롤 가능한 위치에 별도 디렉토리를 생성해 훅들을 관리하고 .git/hooks 폴더가 해당 경로를 바라보도록 symlink(소프트링크) 연결한다.
    ln -s ../hooks .git/hooks // 프로젝트 루트에 hooks 폴더를 만드는 경우
    !!) 링크로 연결되는 목적지 파일은 사라져도 심링크는 살아있지만, 이 경우 훅 관리 폴더를 바라볼 심링크가 리모트에 공유되지 않는 .git/경로 이므로 클론을 할 때마다 심링크 연결을 실행해줘야 한다.
  • git template
    .git 폴더 안의 내용을 미리 만들어두고 복사하여 재사용하는 기능.
    clone, init 등--template 옵션을 사용하면 명시된 폴더 안의 내용을 프로젝트의 .git 폴더 하위에 복사해준다.
    그러나 템플릿 폴더가 공유되어야 한다는 전제조건이 다시 반복되므로 두 방법 중에서는 심링크를 사용하는 경우가 더 많은 것 같다.
    !!) clone을 하든 init을 하든 결국 로컬 작업자가 팀에 공유되는 템플릿 소스가 있음을 인지하고, 이를 공유 받은 상태에서 잊지 않고 --template 옵션을 사용해야만 한다.
  • custom script
    첫 번째 방법처럼 별도의 폴더에서 훅들을 관리하고, 깃템플릿 처럼 이 폴더 내용을 .git 폴더로 복사하는 스크립트를 작성한다.
    !!) 로컬 작업자가 클론 받은 이후 잊지 않고 스크립트를 실행해야 한다

대세인 듯한 husky를 적용하느라 native git hooks 부터 정리해봤다. git hooks를 사용할 때 많이 쓰이는 husky 사용법과 실제로 hooks로 자주 하는 작업들, 네이티브 깃훅이 아닌 hooks 라이브러리들을 사용하는 이유에 대해 이어 정리할 것이다.

profile
개랑 사는 개발자

0개의 댓글