Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

"Git 커밋메시지 작성화면에 최근 커밋목록 보여주기"의 오류부분 수정

어저께 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'같은 설정은 사용자의 템플릿 폴더를 사용할 때만 설정하면 된다.

2013/08/18 16:42 2013/08/18 16:42