git에서도 hook을 추가 할 수 있습니다.
프로그래밍에서 hook이란 특정 이벤트 또는 함수가 호출 되기 전,후에 호출이 되는 코드를 말합니다.
git에서의 이벤츠는 커밋, 풀, 머지 등과 같은 작업으로부터 특정 스크립트를 실행을 시킬 수 있습니다.
(해당 스크립트는 perl, python등과 같은 스크립트 언어로 작성이 가능 합니다.)
git은 크게 local과 remote두가지로 나눌 수 있늗데 hooks또란 이 두가지경우 모든 설정을 각각 해 줄 수 있습니다.
git과 연동된 프로젝트에서 .git이라는 디렉토리를 확인 할 수 있습니다.
$ ls -ahl . .. .git
해당 디렉토리는 숨긴상태로 뜨기 때문에 -ahl이라는 옵션을 추가 해 줍니다. 윈도우의 경우 디렉토리 옵션에 들어가서 숨긴 폴더표시를 눌러주시면 됩니다.
$ cd .git $ ls applypatch-msg.sample pre-push.sample commit-msg.sample pre-rebase.sample post-update.sample pre-receive.sample pre-applypatch.sample prepare-commit-msg.sample pre-commit.sample update.sample
.git/hooks 아래에 .sample로 이미 만들어진 hooks파일이 존재합니다.
해당 훅을 사용하기 위해서는 .sample을 지워주기만 하면 됩니다.
클라이언트 훅
1. 커밋 훅
commit훅은 pre-commit, prepare-commit-msg, commit-msg, post-commit 4가지가 존재합니다.
pre-commit : 커밋할 때 가장먼저 호출되는 훅입니다. 커밋 메시지를 작성하기 전에 호출이 됩니다. 이 훅에서 커밋하는 스냅샷을 검사를 합니다. 빠트린 것이 없는지, 테스트 유무를 점검을 하게 됩니다. 커밋할 때 꼭 확인할 게 있으면 pre-commit훅을 사용하여 확인을 하면 됩니다. 이 훅은 exit가 0이 아니면 커밋이 취소가 됩니다. git commit --no-verify를 해주면 해당 pre-commit훅을 일시적으로 생략이 가능합니다.
추가적으로 lint같은 프로그램으로 코드 스타일을 검사하거나, 라인 끝 공백 문자를 검사하거나(.sample로 작성된 코드가 하는 행위입니다), 새로 추가한 코드에 주석이 달려있는지 검사를 할 땐 pre-commit훅을 이용하시면 됩니다.
prepare-commit-msg : 이 훅은 깃이 커밋 메시지를 생성하고 나서 편집기를 실행하기 전에 실행됩니다. 이 훅은 사람이 커밋 메시지를 수정하기 전에 먼저 프로그램으로 손보고 싶을 때 사용한다. prepare-commit-msg는 인자를 받는데 커밋 메시지가 들어있는 파일 경로, 커밋의 종류 두개의 인자를 받게되는데, 최근 커밋을 수정할 때는(Amending 커밋) SHA-1 값을 추가적으로 더 받게 됩니다. prepare-commit-msg은 Merge 커밋, Squash 커밋, Amend커밋일 때 유용하다.
commit-msg : 이 훅은 커밋 메시지가 들어 있는 임시 파일의 경로를 인자로 받게됩니다. pre-commit과 마찬가지로 exit 0이 반환되지 않으면 커밋이 취소됩니다. 이 훅에서는 최종적으로 커밋이 완료되기 전에 프로젝트 상태나 커밋 메시지를 검증합니다. 커밋 메시지가 해당 프로젝트 정책에 맞는지 검사등을 수행을 하면 됩니다.
post-commit : 이 훅은 커밋이 완료되면 실행이 됩니다. 이 훅은 넘겨받는 인자가 하나도 없지만 커밋 해시정보는 git log -l HEAD 명령으로 쉽게 가져올 수 있습니다. 일반적으로 이 스크립트는 커밋된 것을 누군가 혹은 다른 프로그램에게 알릴 때 사용합니다.
2. 이메일 워크플로 훅
applypatch-msg, pre-applypatch-msg, post-applypatch 3가지가 있다. 해당 문서에서는 해당 명령(git format-patch)을 사용 할 일이 없으면 읽지 말라고 한다 ㅋㅋㅋㅋㅋ
그래도 최소한 무엇을 하는지만 알아가보도록 하겠습니다
applypatch-msg : 가장먼저 실행 되는 훅입니다. exit 0을 하지 않으면 patch를 하지 않습니다. 이 훅은 Author가 보내온 커밋 메시지 파일의 이름을 인자로 받게 됩니다. 커밋 메시지가 규칙에 맞는지 확인하거나 자동으로 메시지를 수정할 때 이 훅을 사용합니다.
pre-applypatch : git am으로 patch할 때 두번째로 실행되는 훅입니다. 이 훅은 인자를 받지 않고, 단순하게 Patch를 적용하고 나서 실행됩니다. 커밋이 스냅샷을 점검할 때 사용합니다. 0이 아닌 값을 반환시켜서 git am명령을 취소 할 수 있습니다.
post-applypatch: git am명령에서 마지막으로 실행 되는 훅입니다. patch를 보낸 사람이나 그룹에게 알림 메시지를 보낼 수 있습니다. 이 훅은 patch를 중단 시킬 수 없습니다.
3.기타 훅
pre-rebase: rebase하기 전에 실행 됩니다. 0아 아닌 값을 반환하면 rebase가 취소 됩니다. 이 훅으로 이미 push한 커밋을 rebase 하지 못하게 할수 있습니다. git이 자동으로 넣어주는 pre-rebase예제가 바로 이 예제입니다. 이 예제는 기준 브랜치가 next라고 되있습니다. 참고하여 실제로 적용할 브랜치 이름으로 사용하면 됩니다.
post-rewrite : 커밋을 변경하는 명령을 실행했을 때 실행하는 훅입니다. git commit --amend나 git rebase같은 명령이 post-rewrite 훅을 실행시키는 명령어에 해당됩니다. git filter-branch명령은 해당되지 않습니다. 훅의 용도는 post-checkout이나 post-merge훅과 비슷합니다.
디렉토리에서 뭔가 할 일이 있을 때 사용합니다. 예를들면 용량이 크거나 깃이 관리하지 않는 파일을 옮기거나 문서를 자동으로 생성하는데 사용하시면 됩니다.
post-merge : 머지가 끝이나면 실행이 됩니다. 이 훅은 파일 권한 길이가 깃이 추적하지 않는 정보를관리하는 데 사용합니다.
post-push : git push 명령을 실행하면 동작하는데 리모트 정보를 업데이트 하고 난 후 리모트로 데이터를 전송하기 전에 동작합니다. 리모트의 이름과 주소를 인자로 받습니다. 0이 아닌 값을 반환하면 push를 중단시킬 수 있습니다.
서버 훅
클라이언트 훅으로도 어떠한 정책을 강요할 수 있지만 시스템을 관리하는 입장에서는 서버 훅이 더 중요합니다. 서버 훅은 모두 push 전후에 실행됩니다. push전에 실행되는 훅이 0이 아닌 값을 반환하면 해당 push는 거절이 됩니다.
pre-receive : push를 하면 가장 처음 실행되는 훅입니다. 해당 스크립트는 표준 입력(STDIN)으로 push하는 레퍼런스를 목록으로 입력받습니다. 0이 아닌 값을 반환하게 되면 해달 레퍼런스를 모두 거절합니다. Fast-forward Push가 아니면 거절하거나, 프랜치 권한 Push 권한을 제어하려면 이 훅에서 하는 것이 좋습니다.
update : update는 스크립트는 각 브랜치마다 한 번씩 실행된다는 것을 제외하면 pre-receive와 거의 같습니다. 한 번에 브랜치를 여러 개 push하면 pre-receive를 딱 한번만실행되니만, update는 브랜치마다 실행이됩니다. 이 스크립트는 인자를 표준 입력으로 데이터를 받지 않습니다.
post-receive : push한 후에 실행됩니다. 이 스크립트가 종료할 때까지 클라이언트와의 연결은 유지되고 push를 중단시킬 수 없다. 그래서 이 스크립트로 시간이 오래 걸릴만한 일을 할 때는 조심해야 합니다.
그럼 해당 훅을 수정하여 정상동작을 하는지 확인을 해보도록 하겠습니다.
pre-commit.sample을 pre-commit으로 이름을 변경을 합니다. 해당 파일을 열어서 아래와 같이 수정을 해줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
echo 'hello world'
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --
| cs |
중간에 echo 'hello world'를 추가를 해보았습니다.
$ git commit -m 'test' hello world [master j1j2h3] test ...중략... 1 file changed, 2 insertions(+), 1 deletion(-)
와 같이 정상적으로 훅이 실행됨을 확인 할 수 있습니다.
댓글
댓글 쓰기