ch01-getting-started.asc에서 git config 명령을 간단히 사용했었다.
git config 명령으로 제일 먼저 하게 되는 작업은 이름과 이메일 주소를 설정하는 것이다.
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com여기서는 이렇게 설정하는 것 중에서 중요한 것만 몇 가지 배운다.
우선 Git은 내장된 기본 규칙 따르지만, 설정된 것이 있으면 그에 따른다는 점을 생각해두자.
Git은 먼저 /etc/gitconfig 파일을 찾는다. 이 파일은 해당 시스템에 있는 모든 사용자와 모든 저장소에 적용되는 설정 파일이다.
git config 명령에 --system 옵션을 주면 이 파일을 사용한다.
다음으로 ~/.gitconfig 파일을 찾는다. 이 파일은 해당 사용자에게만 적용되는 설정 파일이다.
--global 옵션을 주면 Git은 이 파일을 사용한다.
마지막으로 현재 작업 중인 저장소의 Git 디렉토리에 있는 .git/config 파일을 찾는다.
이 파일은 해당 저장소에만 적용된다. git config 명령에 --local 옵션을 적용한 것과 같다.
(아무런 범위 옵션을 지정하지 않으면 Git은 기본적으로 --local 옵션을 적용한다)
각 설정 파일에 중복된 설정이 있으면 설명한 “순서대로” 덮어쓴다. 예를 들어 .git/config 와 /etc/gitconfig 에 같은 설정이 들어 있다면 .git/config 에 있는 설정을 사용한다.
|
Note
|
설정 파일 일반적인 텍스트파일로 쉽게 고쳐 쓸 수 있다.
보통 |
설정이 영향을 미치는 대상에 따라 클라이언트 설정과 서버 설정으로 나눠볼 수 있다. 대부분은 개인작업 환경과 관련된 클라이언트 설정이다. Git에는 설정거리가 매우 많은데, 여기서는 워크플로를 관리하는 데 필요한 것과 주로 많이 사용하는 것만 설명한다. 한 번도 겪지 못할 상황에서나 유용한 옵션까지 다 포함하면 설정할 게 너무 많다. Git 버전마다 옵션이 조금씩 다른데, 아래와 같이 실행하면 설치한 버전에서 사용할 수 있는 옵션을 모두 보여준다.
$ man git-config어떤 옵션을 사용할 수 있는지 매우 자세히 설명하고 있다. http://git-scm.com/docs/git-config.html 페이지에서도 같은 내용을 볼 수 있다.
Git은 편집기를 설정($VISUAL, $EDITOR 변수로 설정)하지 않았거나 설정한 편집기를 찾을 수 없으면 vi 를 실행한다. 커밋할 때나 태그 메시지를 편집할 때 설정한 편집기를 실행한다.
code.editor 설정으로 편집기를 설정한다.
$ git config --global core.editor emacs이렇게 설정하면 메시지를 편집할 때 환경변수에 설정한 편집기가 아니라 Emacs를 실행한다.
커밋할 때 Git이 보여주는 커밋 메시지는 이 옵션에 설정한 템플릿 파일이다. 사용자 지정 커밋 템플릿 메시지가 주는 장점은 커밋 메시지를 작성할 때 일정한 스타일을 유지할 수 있다는 점이다.
예를 들어 ~/.gitmessage.txt 파일을 아래와 같이 만든다.
Subject line (try to keep under 50 characters)
Multi-line description of commit,
feel free to be detailed.
[Ticket: X]커밋 메시지 템플릿을 보면 커밋 메시지를 작성할 때 제목은 일정 길이 이하로 짧게 하고(git log --oneline 으로 보기 좋게) 자세한 수정 내용은 한칸 공백 이후 서술하도록 하고 버그 트래킹 시스템이나 이슈 관리 시스템을 쓸 경우 이슈의 번호를 적도록 유도하고 있는 것을 볼 수 있다.
이 파일을 commit.template 에 설정하면 Git은 git commit 명령이 실행하는 편집기에 이 메시지를 기본으로 넣어준다.
$ git config --global commit.template ~/.gitmessage.txt
$ git commit그러면 커밋할 때 아래와 같은 메시지를 편집기에 자동으로 채워준다.
Subject line (try to keep under 60 characters)
Multi-line description of commit,
feel free to be detailed.
[Ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C소속 팀에 커밋 메시지 규칙이 있으면 그 규칙에 맞는 템플릿 파일을 만들고 시스템 설정에 설정해둔다. Git이 그 파일을 사용하도록 설정하면 규칙을 따르기가 쉬워진다.
Git은 log 나 diff 같은 명령의 메시지를 출력할 때 페이지로 나누어 보여준다.
기본으로 사용하는 명령은 less 다. more 를 더 좋아하면 more 라고 설정한다. 페이지를 나누고 싶지 않으면 빈 문자열로 설정한다.
$ git config --global core.pager ''이 명령을 실행하면 Git은 길든지 짧든지 결과를 한 번에 다 보여 준다.
이 설정은 ch07-git-tools.asc 에서 설명했던 Annotated Tag를 만들 때 유용하다. 사용할 GPG 키를 설정해 둘 수 있다. 아래처럼 GPG 키를 설정하면 서명할 때 편리하다.
$ git config --global user.signingkey <gpg-key-id>git tag 명령을 실행할 때 키를 생략하고 서명할 수 있다.
$ git tag -s <tag-name>Git에서 git add 명령으로 추적할 파일에 포함하지 않을 파일은 .gitignore 에 해당 패턴을 적으면 된다고 ch02-git-basics-chapter.asc에서 설명했다.
한 저장소 안에서뿐 아니라 어디에서라도 Git에 포함하지 않을 파일을 설정할 수 있다.
예를 들어 Mac을 쓰는 사람이라면 .DS_Store 파일을 자주 보았을 것이다.
Emacs나 Vim를 쓰다 보면 이름 끝에 ~, .swp 붙여둔 임시 파일도 있다.
.gitignore 파일처럼 무시할 파일을 설정할 수 있는데 ~/.gitignore_global 파일 안에 아래 내용으로 입력해두고
*~
.*.swp
.DS_Storegit config --global core.excludesfile ~/.gitignore_global 명령으로 설정을 추가하면 더는 위와 같은 파일이 포함되지 않을 것이다.
명령어를 잘못 입력하면 Git은 메시지를 아래와 같이 보여 준다.
$ git chekcout master
git: 'chekcout' is not a git command. See 'git --help'.
Did you mean this?
checkoutGit은 어떤 명령을 입력하려고 했을지 추측해서 보여주긴 하지만 직접 실행하진 않는다.
그러나 help.autocorrect 를 1로 설정하면 명령어를 잘못 입력해도 Git이 자동으로 해당 명령어를 찾아서 실행해준다.
$ git chekcout master
WARNING: You called a Git command named 'chekcout', which does not exist.
Continuing under the assumption that you meant 'checkout'
in 0.1 seconds automatically...여기서 재밌는 것은 “0.1 seconds” 이다. 사실 help.autocorrect 설정에 사용하는 값은 1/10 초 단위의 숫자를 나타낸다.
만약 50이라는 값으로 설정한다면 자동으로 고친 명령을 실행할 때 Git은 5초간 명령을 실행하지 않고 기다려줄 수 있다.
사람이 쉽게 인식할 수 있도록 터미널에 결과를 컬러로 출력할 수 있다. 터미널 컬러와 관련된 옵션은 매우 다양하기 때문에 꼼꼼하게 설정할 수 있다.
Git은 기본적으로 터미널에 출력하는 결과물을 알아서 색칠하지만, 이 색칠하는 기능을 끄고 싶다면 한 가지 설정만 해 두면 된다. 아래와 같은 명령을 실행하면 더는 색칠된 결과물을 내지 않는다.
$ git config --global color.ui false컬러 설정의 기본 값은 auto 로 터미널에 출력할 때는 색칠하지만, 결과가 리다이렉션되거나 파일로 출력되면 색칠하지 않는다.
always 로 설정하면 터미널이든 다른 출력이든 상관없이 색칠하여 내보낸다.
대개 이 값을 설정해서 사용하지 않는다. --color 옵션을 사용하면 강제로 결과를 색칠해서 내도록 할 수 있기 때문이다.
대부분은 기본 값이 낫다.
Git은 좀 더 꼼꼼하게 컬러를 설정하는 방법을 제공한다.
아래와 같은 설정들이 있다. 모두 true, false, always 중 하나를 고를 수 있다.
color.branch color.diff color.interactive color.status
또한, 각 옵션의 컬러를 직접 지정할 수도 있다. 아래처럼 설정하면 diff 명령에서 meta 정보의 포그라운드는 blue, 백그라운드는 black, 테스트는 bold로 바뀐다.
$ git config --global color.diff.meta "blue black bold"컬러는 normal, black, red, green, yellow, blue, magenta, cyan, white 중에서 고를 수 있다.
텍스트 속성은 bold, dim, ul (underline), blink, reverse 중에서 고를 수 있다.
Git에 들어 있는 diff 도구 말고 다른 도구로 바꿀 수 있다. 화려한 GUI 도구로 바꿔서 좀 더 편리하게 충돌을 해결할 수 있다. 여기서는 Perforce의 Merge 도구인 P4Merge로 설정하는 것을 보여준다. P4Merge는 무료인데다 꽤 괜찮다.
P4Merge는 중요 플랫폼을 모두 지원하기 때문에 웬만한 환경이면 사용할 수 있다.
여기서는 Mac과 Linux 시스템에 설치하는 것을 보여준다. Windows에서 사용하려면 /usr/local/bin 경로만 Windows 경로로 바꿔준다.
먼저 https://www.perforce.com/product/components/perforce-visual-merge-and-diff-tools 에서 P4Merge를 내려받는다.
그 후에 P4Merge 에 쓸 Wrapper 스크립트를 만든다.
필자는 Mac 사용자라서 Mac 경로를 사용한다. 어떤 시스템이든 p4merge 가 설치된 경로를 사용하면 된다.
예제에서는 extMerge 라는 Merge 용 Wrapper 스크립트를 만들고 이 스크립트로 넘어오는 모든 아규먼트를 p4merge 프로그램으로 넘긴다.
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*그리고 diff용 Wrapper도 만든다. 이 스크립트로 넘어오는 아규먼트는 총 7개지만 그 중 2개만 Merge Wrapper로 넘긴다. Git이 diff 프로그램에 넘겨주는 아규먼트는 아래와 같다.
path old-file old-hex old-mode new-file new-hex new-mode이 중에서 old-file 과 new-file 만 사용하는 wrapper 스크립트를 만든다.
$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"이 두 스크립트에 실행 권한을 부여한다.
$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiffGit config 파일에 이 스크립트를 모두 추가한다. 설정해야 하는 옵션이 좀 많다.
merge.tool 로 무슨 Merge 도구를 사용할지, mergetool.*.cmd 로 실제로 어떻게 명령어를 실행할지, mergetool.trustExitCode 로 Merge 도구가 반환하는 exit 코드가 Merge의 성공 여부를 나타내는지, diff.external 은 diff 할 때 실행할 명령어가 무엇인지를 설정할 때 사용한다.
모두 git config 명령으로 설정한다.
$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.extMerge.trustExitCode false
$ git config --global diff.external extDiff~/.gitconfig/ 파일을 직접 편집해도 된다.
[merge]
tool = extMerge
[mergetool "extMerge"]
cmd = extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
trustExitCode = false
[diff]
external = extDiff설정을 완료하고 나서 아래와 같이 diff 명령어를 실행한다.
$ git diff 32d1776b1^ 32d1776b1diff 결과가 터미널에 출력되는 대신 P4Merge가 실행되어 아래처럼 Diff 결과를 보여준다.
브랜치를 Merge 할 때 충돌이 나면 git mergetool 명령을 실행한다. 이 명령을 실행하면 GUI 도구로 충돌을 해결할 수 있도록 P4Merge를 실행해준다.
Wrapper를 만들어 설정해두면 다른 Diff, Merge 도구로 바꾸기도 쉽다.
예를 들어, KDiff3를 사용하도록 extDiff 와 extMerge 스크립트를 수정한다.
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*이제부터 Git은 Diff 결과를 보여주거나 충돌을 해결할 때 KDiff3 도구를 사용한다.
어떤 Merge 도구는 Git에 미리 설정이 들어 있다. 그래서 추가로 스크립트를 작성하거나 하는 설정 없이 사용할 수 있는 것도 있다. 아래와 같은 명령으로 확인해볼 수 있다.
$ git mergetool --tool-help
'git mergetool --tool=<tool>' may be set to one of the following:
emerge
gvimdiff
gvimdiff2
opendiff
p4merge
vimdiff
vimdiff2
The following tools are valid, but not currently available:
araxis
bc3
codecompare
deltawalker
diffmerge
diffuse
ecmerge
kdiff3
meld
tkdiff
tortoisemerge
xxdiff
Some of the tools listed above only work in a windowed
environment. If run in a terminal-only session, they will fail.Diff 도구로는 다른 것을 사용하지만, Merge 도구로는 KDiff3를 사용하고 싶은 경우에는 kdiff3 명령을 실행경로로 넣고 아래와 같이 설정하기만 하면 된다.
$ git config --global merge.tool kdiff3extMerge 와 extDiff 파일을 만들지 않고 이렇게 Merge 도구만 kdiff3 로 설정하고 Diff 도구는 Git에 원래 들어 있는 것을 사용할 수 있다.
협업할 때 겪는 소스 포맷(Formatting)과 공백 문제는 미묘하고 난해하다. 동료 사이에 사용하는 플랫폼이 다를 때는 특히 더 심하다. 다른 사람이 보내온 Patch는 공백 문자 패턴이 미묘하게 다를 확률이 높다. 편집기가 몰래 공백문자를 추가해 버릴 수도 있고 크로스-플랫폼 프로젝트에서 Windows 개발자가 라인 끝에 CR(Carriage-Return) 문자를 추가해 버렸을 수도 있다. Git에는 이 이슈를 돕는 몇 가지 설정이 있다.
Windows에서 개발하는 동료와 함께 일하면 라인 바꿈(New Line) 문자에 문제가 생긴다. Windows는 라인 바꿈 문자로 CR(Carriage-Return)과 LF(Line Feed) 문자를 둘 다 사용하지만, Mac과 Linux는 LF 문자만 사용한다. 아무것도 아닌 것 같지만, 크로스 플랫폼 프로젝트에서는 꽤 성가신 문제다. Windows에서 사용하는 많은 편집기가 자동으로 LF 스타일의 라인 바꿈 스타일을 CRLF로 바꾸거나 Enter 키를 입력하면 CRLF 스타일을 사용하기 때문이다.
Git은 커밋할 때 자동으로 CRLF를 LF로 변환해주고 반대로 Checkout 할 때 LF를 CRLF로 변환해 주는 기능이 있다.
core.autocrlf 설정으로 이 기능을 켤 수 있다.
Windows에서 이 값을 true로 설정하면 Checkout 할 때 LF 문자가 CRLF 문자로 변환된다.
$ git config --global core.autocrlf true라인 바꿈 문자로 LF를 사용하는 Linux와 Mac에서는 Checkout 할 때 Git이 LF를 CRLF로 변환할 필요가 없다. 게다가 우연히 CRLF가 들어간 파일이 저장소에 들어 있어도 Git이 알아서 고쳐주면 좋을 것이다.
core.autocrlf 값을 input으로 설정하면 커밋할 때만 CRLF를 LF로 변환한다.
$ git config --global core.autocrlf input이 설정을 이용하면 Windows에서는 CRLF를 사용하고 Mac, Linux, 저장소에서는 LF를 사용할 수 있다.
Windows 플랫폼에서만 개발하면 이 기능이 필요 없다.
이 옵션을 false 라고 설정하면 이 기능이 꺼지고 CR 문자도 저장소에도 저장된다.
$ git config --global core.autocrlf falseGit에는 공백 문자를 다루는 방법으로 네 가지가 미리 정의돼 있다. 두 가지는 기본적으로 켜져 있지만 끌 수 있고 나머지 두 가지는 꺼져 있지만 켤 수 있다.
먼저 기본적으로 켜져 있는 것을 살펴보자. blank-at-eol 는 각 라인 끝에 공백이 있는지 찾고, blank-at-eof 는 파일 끝에 추가한 빈 라인이 있는지 찾고, space-before-tab 은 모든 라인에서 처음에 tab보다 공백이 먼저 나오는지 찾는다.
기본적으로 꺼져 있는 나머지 세 개는 indent-with-non-tab 과 tab-in-indent 과 cr-at-eol 이다. intent-with-non-tab 은 tab이 아니라 공백으로(tabwidth 설정에 영향받음) 시작하는 라인이 있는지 찾고 cr-at-eol 은 라인 끝에 CR 문자가 있어도 괜찮다고 Git에 알리는 것이다.
core.whitespace 옵션으로 이 네 가지 방법을 켜고 끌 수 있다.
설정에서 해당 옵션을 빼버리거나 이름이 - 로 시작하면 기능이 꺼진다.
예를 들어, 다른 건 다 켜고 space-before-tab 옵션만 끄려면 아래와 같이 설정한다. trailing-space 옵션은 blank-at-eol 옵션과 blank-at-eof 옵션을 의미한다.
$ git config --global core.whitespace \
trailing-space,-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol또는 각 부분에 대해서 설정을 할 수도 있다.
$ git config --global core.whitespace \
-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eolgit diff 명령을 실행하면 Git은 이 설정에 따라 검사해서 컬러로 표시해준다.
그래서 좀 더 쉽게 검토해서 커밋할 수 있다.
git apply 명령으로 Patch를 적용할 때도 이 설정을 이용할 수 있다. 아래처럼 명령어를 실행하면 해당 Patch가 공백문자 정책에 들어맞는지 확인할 수 있다.
$ git apply --whitespace=warn <patch>아니면 Git이 자동으로 고치도록 할 수 있다.
$ git apply --whitespace=fix <patch>이 옵션은 git rebase 명령에서도 사용할 수 있다.
공백 문제가 있는 커밋을 Upstream에 Push 하기 전에 --whitespace=fix 옵션을 주고 Rebase 하면 Git은 다시 Patch를 적용하면서 공백을 설정한 대로 고친다.
서버 설정은 많지 않지만, 꼭 짚고 넘어가야 하는 것이 몇 개 있다.
Git은 Push 할 때마다 각 개체가 SHA-1 체크섬에 맞는지 잘못된 개체가 가리키고 있는지 검사하게 할 수 있다.
기본적으로 이 기능이 동작하지 않게 설정이 되어 있는데 개체를 점검하데 상당히 시간이 걸리기 때문에 Push 하는 시간이 늘어난다. 얼마나 늘어나는지는 저장소 크기와 Push 하는 양에 달렸다.
receive.fsckOBjects 값을 true로 설정하면 Git이 Push 할 때마다 검증한다.
$ git config --system receive.fsckObjects true이렇게 설정하면 Push 할 때마다 검증하기 때문에 클라이언트는 잘못된 데이터를 Push 하지 못한다.
이미 Push 한 커밋을 Rebase 해서 다시 Push 하지 못하게 할 수 있다. 브랜치를 Push 할 때 해당 리모트 브랜치가 가리키는 커밋이 Push 하려는 브랜치에 없을 때 Push 하지 못하게 할 수 있다.
보통은 이런 정책이 좋고 git push 명령에 -f 옵션을 주면 강제로 Push 할 수 있다.
receive.denyNonFastForwards 옵션을 켜면 Fast-forward로 Push 할 수 없는 브랜치는 아예 Push 하지 못한다.
$ git config --system receive.denyNonFastForwards true사용자마다 다른 정책을 적용하고 싶으면 서버 훅을 사용해야 한다. 서버의 receive 훅으로 할 수 있고 이 훅도 이 장에서 설명한다.
receive.denyNonFastForwards 와 비슷한 정책으로 receive.denyDeletes 라는 것이 있다.
이 설정을 켜면 브랜치를 삭제하는 Push가 거절된다.
$ git config --system receive.denyDeletes true이제 브랜치나 Tag를 삭제하는 Push는 거절된다. 아무도 삭제할 수 없다. 리모트 브랜치를 삭제하려면 직접 손으로 server의 ref 파일을 삭제해야 한다. 그리고 사용자마다 다른 정책을 적용시키는 ACL을 만드는 방법도 있다. 이 방법은 ch08-customizing-git.asc 에서 다룬다.
