Pro git - 8.1
Updated:
Pro git - Git 설정하기
1. Git 설정하기
- Git은 먼저
/etc/gitconfig
파일을 찾는다. - 이 파일은 해당 시스템에 있는 모든 사용자와 모든 저장소에 적용되는 설정 파일이다.
git config
명령에--system
옵션을 주면 이 파일을 사용한다.- 다음으로
~/.gitconfig
파일을 찾는다. - 이 파일은 해당 사용자에게만 적용되는 설정 파일이다.
--global
옵션을 주면 Git은 이 파일을 사용한다.- 마지막으로 현재 작업 중인 저장소의 Git 디렉토리에 있는
.git/config
파일을 찾는다. - 이 파일은 해당 저장소에만 적용된다.
git config
명령에--local
옵션을 적용한 것과 같다. (아무런 범위 옵션을 지정하지 않으면 Git은 기본적으로--local
옵션을 적용한다)- 각 설정 파일에 중복된 설정이 있으면 설명한 “순서대로” 덮어쓴다.
- 예를 들어
.git/config
와/etc/gitconfig
에 같은 설정이 들어 있다면.git/config
에 있는 설정을 사용한다.
2. 클라이언트 설정
- 설정이 영향을 미치는 대상에 따라 클라이언트 설정과 서버 설정으로 나눠볼 수 있다.
- 대부분은 개인작업 환경과 관련된 클라이언트 설정이다.
- Git에는 설정거리가 매우 많은데, 여기서는 워크플로를 관리하는 데 필요한 것과 주로 많이 사용하는 것만 설명한다.
- Git 버전마다 옵션이 조금씩 다른데, 아래와 같이 실행하면 설치한 버전에서 사용할 수 있는 옵션을 모두 보여준다.
$ man git-config
2.1 core.editor
- Git은 편집기를 설정(
$VISUAL
,$EDITOR
변수로 설정)하지 않았거나 설정한 편집기를 찾을 수 없으면vi
를 실행한다. - 커밋할 때나 태그 메시지를 편집할 때 설정한 편집기를 실행한다.
code.editor
설정으로 편집기를 설정한다.
$ git config --global core.editor emacs
- 이렇게 설정하면 메시지를 편집할 때 환경변수에 설정한 편집기가 아니라 Emacs를 실행한다.
2.2 commit.template
- 커밋할 때 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이 그 파일을 사용하도록 설정하면 규칙을 따르기가 쉬워진다.
2.3 core.pager
- Git은
log
나diff
같은 명령의 메시지를 출력할 때 페이지로 나누어 보여준다. - 기본으로 사용하는 명령은
less
다.more
를 더 좋아하면more
라고 설정한다. 페이지를 나누고 싶지 않으면 빈 문자열로 설정한다.
$ git config --global core.pager ''
- 이 명령을 실행하면 Git은 길든지 짧든지 결과를 한 번에 다 보여 준다.
2.4 user.signingkey
- 이 설정은 내 작업에 서명하기 에서 설명했던 Annotated Tag를 만들 때 유용하다.
- 사용할 GPG 키를 설정해 둘 수 있다.
- 아래처럼 GPG 키를 설정하면 서명할 때 편리하다.
$ git config --global user.signingkey <gpg-key-id>
git tag
명령을 실행할 때 키를 생략하고 서명할 수 있다.
$ git tag -s <tag-name>
2.5 core.excludesfile
- 한 저장소 안에서뿐 아니라 어디에서라도 Git에 포함하지 않을 파일을 설정할 수 있다.
- 예를 들어 Mac을 쓰는 사람이라면
.DS_Store
파일을 자주 보았을 것이다. -
Emacs나 Vim를 쓰다 보면 이름 끝에
~
,.swp
붙여둔 임시 파일도 있다. .gitignore
파일처럼 무시할 파일을 설정할 수 있는데~/.gitignore_global
파일 안에 아래 내용으로 입력해두고
*~
.*.swp
.DS_Store
git config --global core.excludesfile ~/.gitignore_global
명령으로 설정을 추가하면 더는 위와 같은 파일이 포함되지 않을 것이다.
2.6 help.autocorrect
- 명령어를 잘못 입력하면 Git은 메시지를 아래와 같이 보여 준다.
$ git chekcout master
git: 'chekcout' is not a git command. See 'git --help'.
Did you mean this?
checkout
- Git은 어떤 명령을 입력하려고 했을지 추측해서 보여주긴 하지만 직접 실행하진 않는다.
- 그러나
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초간 명령을 실행하지 않고 기다려줄 수 있다.
3. 컬러 터미널
- 사람이 쉽게 인식할 수 있도록 터미널에 결과를 컬러로 출력할 수 있다.
- 터미널 컬러와 관련된 옵션은 매우 다양하기 때문에 꼼꼼하게 설정할 수 있다.
3.1 color.ui
- Git은 기본적으로 터미널에 출력하는 결과물을 알아서 색칠하지만, 이 색칠하는 기능을 끄고 싶다면 한 가지 설정만 해 두면 된다.
- 아래와 같은 명령을 실행하면 더는 색칠된 결과물을 내지 않는다.
$ git config --global color.ui false
-
컬러 설정의 기본 값은
auto
로 터미널에 출력할 때는 색칠하지만, 결과가 리다이렉션되거나 파일로 출력되면 색칠하지 않는다. always
로 설정하면 터미널이든 다른 출력이든 상관없이 색칠하여 내보낸다.- 대개 이 값을 설정해서 사용하지 않는다.
--color
옵션을 사용하면 강제로 결과를 색칠해서 내도록 할 수 있기 때문이다.- 대부분은 기본 값이 낫다.
3.2 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
중에서 고를 수 있다.
4. 다른 Merge, Diff 도구 사용하기
- 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/extDiff
- Git 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^ 32d1776b1
- diff 결과가 터미널에 출력되는 대신 P4Merge가 실행되어 아래처럼 Diff 결과를 보여준다.
https://git-scm.com/book/en/v2/images/p4merge.png
- 브랜치를 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 kdiff3
extMerge
와extDiff
파일을 만들지 않고 이렇게 Merge 도구만kdiff3
로 설정하고 Diff 도구는 Git에 원래 들어 있는 것을 사용할 수 있다.
5. Formatting and Whitespace
- 협업할 때 겪는 소스 포맷(Formatting)과 공백 문제는 미묘하고 난해하다.
- 동료 사이에 사용하는 플랫폼이 다를 때는 특히 더 심하다.
- 다른 사람이 보내온 Patch는 공백 문자 패턴이 미묘하게 다를 확률이 높다.
- 편집기가 몰래 공백문자를 추가해 버릴 수도 있고 크로스-플랫폼 프로젝트에서 Windows 개발자가 라인 끝에 CR(Carriage-Return) 문자를 추가해 버렸을 수도 있다.
- Git에는 이 이슈를 돕는 몇 가지 설정이 있다.
5.1 core.autocrlf
- 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 false
5.2 core.whitespace
- Git에는 공백 문자를 다루는 방법으로 네 가지가 미리 정의돼 있다.
-
두 가지는 기본적으로 켜져 있지만 끌 수 있고 나머지 두 가지는 꺼져 있지만 켤 수 있다.
- 먼저 기본적으로 켜져 있는 것을 살펴보자.
-
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-eol
git 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를 적용하면서 공백을 설정한 대로 고친다.
6. 서버 설정
- 서버 설정은 많지 않지만, 꼭 짚고 넘어가야 하는 것이 몇 개 있다.
6.1 receive.fsckObjects
- Git은 Push 할 때마다 각 개체가 SHA-1 체크섬에 맞는지 잘못된 개체가 가리키고 있는지 검사하게 할 수 있다.
- 기본적으로 이 기능이 동작하지 않게 설정이 되어 있는데 개체를 점검하데 상당히 시간이 걸리기 때문에 Push 하는 시간이 늘어난다.
- 얼마나 늘어나는지는 저장소 크기와 Push 하는 양에 달렸다.
receive.fsckOBjects
값을 true로 설정하면 Git이 Push 할 때마다 검증한다.
$ git config --system receive.fsckObjects true
- 이렇게 설정하면 Push 할 때마다 검증하기 때문에 클라이언트는 잘못된 데이터를 Push 하지 못한다.
6.2 receive.denyNonFastForwards
- 이미 Push 한 커밋을 Rebase 해서 다시 Push 하지 못하게 할 수 있다.
- 브랜치를 Push 할 때 해당 리모트 브랜치가 가리키는 커밋이 Push 하려는 브랜치에 없을 때 Push 하지 못하게 할 수 있다.
-
보통은 이런 정책이 좋고
git push
명령에-f
옵션을 주면 강제로 Push 할 수 있다. receive.denyNonFastForwards
옵션을 켜면 Fast-forward로 Push 할 수 없는 브랜치는 아예 Push 하지 못한다.
$ git config --system receive.denyNonFastForwards true
- 사용자마다 다른 정책을 적용하고 싶으면 서버 훅을 사용해야 한다.
- 서버의 receive 훅으로 할 수 있고 이 훅도 이 장에서 설명한다.
6.2 receive.denyDeletes
receive.denyNonFastForwards
와 비슷한 정책으로receive.denyDeletes
라는 것이 있다.- 이 설정을 켜면 브랜치를 삭제하는 Push가 거절된다.
$ git config --system receive.denyDeletes true
- 이제 브랜치나 Tag를 삭제하는 Push는 거절된다.
- 아무도 삭제할 수 없다.
- 리모트 브랜치를 삭제하려면 직접 손으로 server의 ref 파일을 삭제해야 한다.
- 그리고 사용자마다 다른 정책을 적용시키는 ACL을 만드는 방법도 있다.