Outsider's Dev Story

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

bash 프롬프트에 Git와 Mercurial의 branch를 표시하기

몇주전에 대안언어축제를 가서 저녁때 Github에 대한 LETS를 듣던 중 발표하시는 김기용님(이름이 정확히 기억이 안나는군요 ㅠㅠ)의 쉘프롬프트에 git의 브랜치가 표시되는 것을 보았습니다. 어떻게 하냐고 물었더니 쉘설정 수정해서 하는 방법이 있다고 인터넷에서 찾아서 하셨다고 하시길래 저도 돌아와서 인터넷에서 찾아보았습니다.




Bash Prompt에 Git Branch명 표시하기
인터넷을 검색해서 Current Git Branch in Bash Prompt라는 글을 찾아냈습니다. 댓글까지 다 보시면 좀더 괜찮은 방법들이 언급되고 있습니다. 사용자 홈디렉토리에 있는 .bashrc 파일에 아래 아래와 같이 추가했습니다.


c_cyan=`tput setaf 6`
c_red=`tput setaf 1`
c_green=`tput setaf 2`
c_sgr0=`tput sgr0`

parse_git_branch ()
{
   if git rev-parse --git-dir >/dev/null 2>&1
   then
      gitver=$(git branch 2>/dev/null| sed -n '/^\*/s/^\* //p')
   else
      return 0
   fi
   echo -e $gitver
}

branch_color ()
{
   if git rev-parse --git-dir >/dev/null 2>&1
   then
      color=""
      if git diff --quiet 2>/dev/null >&2
      then
         color="${c_green}"
      else
         color=${c_red}
      fi
   else
      return 0
   fi
   echo -ne $color
}

export PS1='\u@\h\[${c_sgr0}\]:\W\[${c_sgr0}\] (\[$(branch_color)\]$(parse_git_branch)\[${c_sgr0}\])\$ '

위처럼 .bashrc를 작성하고 source ~/.bashrc로 적용을 하면 prompt가 git저장소인 곳에서는 아래처럼 변경이 됩니다.

터미널에 git브랜치를 표시한 화면

처음 쉘스크립팅을 만져보긴 했는데 찬찬히 보다보니 대충은 이해할 수 있었습니다. PS1을 새로 작성해 주면 prompt에 표시되는 내용을 변경할 수 있고 \u는 사용자명 \h는 호스트명 \W는 현재 디랙토리 \w는 현재 경로를 나타내게 됩니다. 그외에는 자신의 입맛에 맛게 수정해주면 됩니다. git 저장소를 사용하는 폴더면 현재의 브랜치명을 표시하고 수정내용이 있으면 빨간색으로 이미 커밋한 상태명 빨간색으로 표시하도록 한 것입니다.




Bash Prompt에 Mercurial Branch명 표시하기
Git을 설정하고 나니까 좀 더 욕심이 생겼습니다. git보다는 덜 사용하지만 같이 사용하고 있는 Mercurial에 대해서도 동일하게 설정을 하고 싶었습니다. git은 검색하니까 아주 다양하게 많은 정보가 나왔지만 Mercurial은 사용자가 적어서인지 생각보다 많이 나오지 않아서 적용하는데 약간 고생을 했습니다. Mercurial Bash Prompts라는 글이 제일 잘 나와있었고 이글을 작성하고 그 결과물을 python으로 작성해서 hg-prompt 라는 hg 익스텐션을 만들어서 공개했습니다.

hg-prompt의 설치방법은 설치가이드에 잘 나와있는데 hg clone http://bitbucket.org/sjl/hg-prompt/ 로 소스를 받은 다음에 prompt.py를 원하는 위치에 복사한 뒤에 사용자 홈디렉토리의 .hgrc파일에 아래처럼 추가해 주면 됩니다.


[extensions]
prompt = (path to)/prompt.py

이제 hg prompt 'test'hg prompt {status}처럼 명령어를 입력하면 hg-prompt를 사용할 수 있습니다. 자세한 사용법은 hg-prompt 문서에 잘 나와있습니다.(사실 잘~까진 아니고요 ㅎ) 이제 Bash Prompt설정도 hg-prompt를 사용해서 합니다.(사실 제가 쉘스크립팅에 익숙하지 않아서 기본적인 hg명령어를 사용해서 하는 방법을 잘 몰라서 삽질하다가 결국 hg-prompt를 사용하기로 했습니다.)


c_cyan=`tput setaf 6`
c_red=`tput setaf 1`
c_green=`tput setaf 2`
c_pink=`tput setaf 5`
c_sgr0=`tput sgr0`

parse_branch ()
{
   if git rev-parse --git-dir >/dev/null 2>&1
   then
      branchname="(git:"$(branch_color)$(git branch 2>/dev/null| sed -n '/^\*/s/^\* //p')${c_sgr0}") "
   elif hg prompt >/dev/null 2>&1
   then
      branchname="(hg:"$(branch_color)$(hg prompt "{branch}" 2>/dev/null)${c_sgr0}") "
   else
      return 0
   fi
   echo -e $branchname
}

branch_color ()
{
   if git rev-parse --git-dir >/dev/null 2>&1
   then
      color=""
      if git diff --quiet 2>/dev/null >&2
      then
         gitstatus=$(git status 2>/dev/null| tail -n1)
         case "$gitstatus" in
            "nothing to commit (working directory clean)" ) color=${c_green};;
            * ) color=${c_pink};;
         esac
      else
         color=${c_red}
      fi
   elif hg prompt >/dev/null 2>&1
   then
      color=""
      hgstatus=$(hg prompt {status} 2>/dev/null)
      case "$hgstatus" in
         "!" ) color=${c_red};;
         "?" ) color=${c_pink};;
         *       ) color=${c_green};;
      esac
   else
      return 0
   fi
   echo -ne $color
}

export PS1='\u@\h\[${c_sgr0}\]:\W\[${c_sgr0}\] $(parse_branch)\$ '

그렇게 해서 완성된 코드가 위의 코드입니다. 앞에서 git 저장소가 아닌 위치에서는 ()만 나타나던 것도 표시되지 않도록 했고 git과 hg를 구분해서 볼수있도록 브랜치 앞에 어떤 DVCS인지를 표시하도록 했습니다. 동일하게 파일이 커밋된 상태에서는 녹색으로 나오고 수정파일이 있는 경우에는 빨간색으로 나오게 했습니다. 그리고 수정파일이 아닌 경우 추척되지 않는 파일이 있는 경우는 분홍색으로 표시되도록 했습니다.

터미널에 hg브랜치를 표시한 화면

이제 hg 저장소를 사용하면 위처럼 표시가 됩니다. hg를 설정하면서 비슷한 설정이 되도록 git에 대한 설정을 바꾸어서 아래처럼 나오도록 했습니다.

터미널에 hg브랜치를 표시한 화면

hg용과 git용의 차이점이라면 분홍색으로 표시될때 hg는 추적되지 않는 파일이 있을때만 분홍색으로 적용되는데 git은 스테이징까지 되었을때도 분홍색으로 표시된다는 점입니다. 더 설정을 만지기는 힘들어서 좀 써보다가 불편해지면 수정해 보려고 합니다.

DVCS를 쓰면서 가장 많이 사용하는 명령어중 하나가 git status나 hg status인데 기본적으로 프롬프트에 바로 표시해줘서 사용할 때 꽤 편할듯 합니다. 찾아보다보니 SVN도 설정하는 법이 있기도 하던데 요즘은 서브버전은 거의 사용하지 않는데다가 터미널에서 사용하는 경우는 극히 드물어서 굳이 설정하진 않았습니다. hg의 명령어들이 좀 느린지 git저장소를 사용하는 위치에서는 괜찮은데 hg 저장소를 사용하는 위치에서는 프롬프트가 약간 느려진 느낌이 있더군요.(누군가 더 좋은 소스를 제안해주면 좋겠는데요 ㅎㅎ)
2011/03/28 23:40 2011/03/28 23:40