어저께 Git 커밋메시지 작성화면에 최근 커밋목록 보여주기라는 포스팅을 올렸었는데 여기에 약간 오류가 있었다. 기존 포스팅을 수정해서 올릴까 하다가 수정사항 외에도 추가할 부분도 있고 기존 포스팅에 추가하면 이미 보신 분들은 이 내용을 놓칠까봐 별도의 포스팅으로 올린다.
기존 훅의 문제점
기존 훅은 정상적으로 동작하는 듯 하지만 git commit
대신에 편리한 git commmit -m 'MESSAGE'
와 같이 작성하는 경우 훅에서 추가한 커맨트가 커밋메시지로 들어가 버린다. 그래서 다음과 같이 커밋이 되어 버린다.
commit 523da0fbecb5d6740b3b278102c6972e5e9af32a
Author: Outsider <outsideris@gmail.com>
Date: Sat Aug 17 21:46:00 2013 +0900
removed wrapping div for iScroll
#
# Last 5 commit messages
# ----------------------
git commit -m
을 별로 사용하지 않아서 이 훅을 적용하고도 인식을 못하고 있었다. 원글을 다시 가보니 거기에도 누가 비슷한 오류를 문의해 놓은 상태이다.
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first comments out the
# "Conflicts:" part of a merge commit.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
case "$2,$3" in
# merge,) ;;
# /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
,|template,)
BRANCH_NAME=$(git branch | grep '*' | sed 's/* //')
if [[ $BRANCH_NAME != '(no branch)' ]]
then
HASLOG=$(git log 2>&1)
if [[ "$HASLOG" != *fatal* ]]; then
echo "#" >> $1
echo "# Last 5 commit messages" >> $1
echo "# ----------------------" >> $1
COMMITS=`git log --pretty=format:"# %h %s [%an]" -5`
echo "${COMMITS}" >> $1
fi
fi
;;
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$1" ;;
*) ;;
esac
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
여러 테스트를 거쳐서 새로 완성한 훅이다. 갑자기 라인이 많아졌지만 이건 원래 git에 들어있는 prepare-commit-msg.sample
파일에 그대로 수정을 해서 그렇다. 주석이 어런 정보가 들어있기 때문에 기존의 샘플에 들어있는 파일을 그대로 유지하는게 좋겠다고 생각했다.
달라진 점은 기존에는 prepare-commit-msg
전체에 해당 내용을 출력하도록 되어 있었지만 이번에는 샘플파일에 있던대로 명령어 조건에 따라 수행하도록 했다. git의 설명에서 prepare-commit-msg 부분을 보면 두번째 파라미터로 옵션에 따라서 merge, template, message, commit등으로 나누어짐을 알 수 있다. 테스트를 해본 결과 -m
옵션을 사용했을 때는 두번째 파라미터가 message라고 넘어오게 되고 -m
옵션없이 git commit
으로 에디터를 띄웠을 때는 template분기부분으로 빠지기 때문에 최근 5개의 커밋을 출력하는 부분을 이 template 조건 부분안으로 이동 시켰다. 그리고 BRANCH_NAME 부분을 검사할때 최초에 저장소를 생성할 때는 검사에 오류가 나와서 대괄호를 하나 더 감싸주었고 최초 첫 커밋시에는 HEAD가 없어서 최근 로그를 출력하는 부분에서 오류가 발생하기 때문에 로그가 있을 경우만 출력하도록 수정했다.
오류가 있다는걸 알고 놀라서 이런저런 테스트를 하긴 했지만 혹 빠진 부분이 있을지도 모르니 사용하시면서 잘못된 부분이 있으면 알려주시면 감사하겠습니다.
Git의 기본 템플릿 폴더
이전 글에서 사용자 홈디렉토리 아래 .git_template
이라는 폴더를 만들어서 Git의 템플릿 폴더로 지정했는데 원래는 Git의 기본 템플릿 폴더를 사용하고 있다. 이 템플릿 폴더는 최초 git-init
시에 .git
폴더 아래로 복사를 하는데 여기서는 새로 생성해서 다른 폴더로 지정했으므로 다른 파일은 생기지 않고 앞에서 만든 hooks/prepare-commit-msg
파일 하나만 생기게 된다. 이 원래 템플릿 폴더에 많은 내용이 있지는 않지만 hooks에 샘플 훅 파일들이 있으므로 편의 차원에서 이 파일들도 자동으로 생기게 하는게 좋아 보인다.
템플릿 폴더는 나같은 경우는(OS X 10.8.4 - Git 1.7.9.6) /usr/local/git/share/git-core/templates
위치에 템플릿 폴더가 존재하고 일반적으로는 /usr/local
이나 /usr
하위에 share/git-core/templates
같은 위치에 존재하는 것으로 보인다. 별도로 템플릿을 관리할 것이라면 사용자 디렉토리에 .git_template
를 만들어서 기존의 템플릿을 모두 복사한 뒤에 사용하거나 아니면 원래의 템플릿폴더 아래에 새로운 prepare-commit-msg
를 생성해서 추가해도 된다.물론 git config --global init.templatedir '~/.git_template'
같은 설정은 사용자의 템플릿 폴더를 사용할 때만 설정하면 된다.
좋은 정보 감사합니다.
우분투에서는 /bin/sh 쉘 이용 시 double brackets를 사용할 수 없다는 점에 유의해야 될 것 같네요.
해당 내용 참고 링크입니다.
http://stackoverflow.com/questions/9666102/bash-double-bracket-issue
아~ 그렇군요... 쉘이라서 상관없을 줄 알았는데 그런 문제가 있었군요. OSX에만 사용해봐서 몰랐었습니다.
안녕하세요, 평소에 써주시는 글들 감사히 읽고 있습니다!
git add -p 와 git commit -v 의 사용 를 보고 이 포스트로 넘어오게 되었습니다.
./.git/hooks/prepare-commit-msg 에 위에 있는 훅을 저장하고,
git config --global init.templatedir '~/.git_template'
git init 을 해도 아무런 변화가 없는 것은 왜 그럴까요 T_T
(그럴리 없지만) 혹시 zsh 을 쓰고 있어서 그런가 하고,
훅의 최상단 행을 #!/bin/sh 에서 #!/usr/local/bin/zsh 로 바꿔보아도
안 되는 것을 봤을 때는 그 문제는 아닌 것 같습니다..
위 기능이 정말 필요하다 느껴질 때가 많아서 꼭 적용하고 싶은데
제가 잘못한 부분이 있는지 알려주시면 정말 감사하겠습니다...!
sh로 설정되어 있어서 zsh로 바꾸진 않아도 될것 같은데 환경에 따라 스크립트에 문제가 있는게 아닐가 합니다.
설정이 제대로 되었으면 git init을 하셨을 때 현재 프로젝트에 .git/hooks/prepare-commit-msg 가 생겨야 합니다. 이 파일이 제대로 있다면 .git/hooks/prepare-commit-msg out.txt와 같이 실행을 해보시면 스크립트가 제대로 동작하는지 확인해 보실 수 있을것 같습니다.
저같은 경우는 out.txt가 다음과 같이 저장됩니다.
#
# Last 5 commit messages
# ----------------------
# 95f152a 222 [Outsider]
# 9a5c9ff 111 [Outsider]