[도서 정리] 8. Git 맞춤 - ProGit |
8.1. GIt 설정하기
-
git 은 내장된 기본 규칙을 따르지만 설정된 것이 있으면 그에 따른다.
git 은 먼저 /etc/gitconfig 파일을 찾는다.
이 파일은 시스템에 있는 모든 사용자와 모든 저장소에 적용되는 설정 파일이다.
git config —system 을 이용하면 이 파일을 사용한다.
다음으로 ~/.gitconfig 파일을 찾는다.
이 파일은 해당 사용자에게만 적용되는 설정파일이다.
—global 옵션을 주면 git 은 이 파일을 사용한다.
마지막으로 현재 작업중인 저장소의 git 디렉터리에 있는 .git/config 파일을 찾는다.
이 파일은 해당 저장소에만 적용된다.
-
각 설정 파일에 중복된 설정이 있으면 순서대로 덮어쓴다.
즉 .git/config 의 설정값이 우선순위가 가장 높다.
* 클라이언트 설정
-
설정이 영향을 미치는 대상에 따라 클라 설정과 서버 설정으로 나눠볼 수 있다.
대부분은 클라 설정이다.
man git-config 로 설정 가능한 내용들을 볼 수 있다.
-
core.editor 는 git 의 편집기를 설정한다.
$VISUAL, $EDITOR 로 설정된 것이 없으면 vi 를 실행한다.
커밋할 때나 tag 메시지를 편집할 때 설정한 편집기를 실행한다.
-
commit.template 은 커밋 메시지의 템플릿을 설정하는 것이다.
$ git config —global commit.template file_name
$ git commit
-
core.pager 는 log, diff 같은 명령의 메시지를 출력할 때 paging 하는 규칙을 설정한다.
기본적으로 less 를 사용하는데, more 를 좋아하면 more 라고 설정한다.
페이지를 나누고 싶지 않으면 빈 문자열로 설정한다.
-
user.signkey 는 내 작업에 서명할 때 사용하다.
gpg 키를 설정하는 것이다.
$ git config —global user.signkey gpg_key_id
$ git tag -s tag_name
-
core.excludesfile 은 global level 로 gitignore 를 설정할 수 있다.
$ git config —global core.excludesfile <ignore_file_name>
-
help.autocorrect 는 명령어를 잘못 입력했을 때 git 이 자동으로 해당 명령어로 대체하여 명령을 수행한다.
$ git config —global help.autocorrect 1
* 컬러 터미널
-
git 은 기본적으로 터미널에 출력하는 결과물을 알아서 색칠한다.
하지만 이 기능을 끄고싶다면 color.ui 를 false 로 두면 된다.
-
좀 더 꼼꼼하게 컬러를 설정하려면 color.branch, diff, interactive, status 등에 true, false, always 를 설정할 수 있다.
$ git config —global color.diff.meta “blue black bold”
* 다른 merge, diff 도구 사용하기
-
P4Merge 가 추천되는 무료 툴 중 하나이다.
$ 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
* Formatting and Whitespace
-
윈도우에서 개발하는 동료와 함께 일하면 new line 에 문제가 생길 수 있다.
윈도우는 CR, LF 문자를 둘 다 사용하지만, 맥과 리눅스는 LN 만 사용하기 때문이다.
git 은 커밋할 때 자동으로 crlf 를 lf 로 변환해주고 반대로 checkout 할 때 lf 를 crlf 로 변환해주는 기능이 있다.
core.autocrlf 를 이용하면 된다. true 로 하면 윈도우에서 checkout 할 때 lf 가 crlf 로 변환된다.
core.autocrlf 를 input 으로 설정하면 커밋할 때만 crlf 를 lf 로 변환한다.
-
git 에는 공백 문자를 다루는 방법으로 네 가지가 정의돼 있다.
blank-at-eol 은 각 라인 끝에 공백이 있는지 찾고, blank-at-eof 는 파일 끝에 추가한 빈 라인이 있는지 찾는다.
space-before-tab 은 모든 라인에서 처음에 tab 보다 공백이 먼저 나오는지 찾는다.
이들은 기본으로 켜져 있다.
indent-with-non-tab 는 tab 이 아니라 공백으로 시작하는 라인이 있는지 찾고,
cr-at-eol 은 라인 끝에 cr 문자가 있어도 괜찮다고 git 에 알리는 것이다.
이들은 기본적으로 꺼져있다.
core.whitespace 옵션으로 이 네가지 방법을 켜고 끌 수 있다.
ex)
$ git config —global core.whitespace trailing-space, space-before-tab, indent-with-non-tab
* 서버 설정
-
git 은 push 할 때마다 각 객체가 sha-1 체크섬에 맞는지 잘못된 개체가 가리키고 있는지 검사하게 할 수 있다.
기본적으로 이 기능이 동작하지 않게 설정되어 있는데 개체를 점검하는데 시간이 걸리기 때문에 push 시간이 늘어나기 때문이다.
얼마나 늘어나는지는 저장소 크기와 push 양에 따라 다르다.
receive.fsckObjects 를 true 로 하면 push 할 때마다 검증한다.
-
이미 push 한 커밋을 rebase 해서 다시 push 하지 못하게 할 수 있다.
브랜치를 push 할 때 해당 리모트 브랜치가 가리키는 커밋이 push 하려는 브랜치를 없을때 push 하지 못하게 할 수 있다.
보통 이런 정책이 좋고 git push 명령에 -f 옵션을 주면 강제로 push 할 수 있다.
receive.denyNonFastForwards 옵션을 켜면 fast-forward 로 push 할 수 없는 브랜치는 아예 push 하지 않는다.
-
receive.denyDeletes 는 브랜치를 삭제하는 push 가 거절된다.
브랜치나 tag 를 삭제하는 push 는 거절된다.
아무도 삭제할 수 없다.
리모트 브랜치를 삭제하려면 직접 손으로 server 의 ref 파일을 삭제해야 한다.
8.2. Git Attributes
-
디렉터리와 파일 단위로 다른 설정을 할 수 있다.
경로별로 설정하는 것을 git attribute 라고 부른다.
이 설정은 .gitattributes 라는 파일에 저장하고 아무 디렉터리에나 둘 수 있지만, 보통은 프로젝트 최상위 디렉터리에 둔다.
이 파일을 커밋하고 싶지 않으면 .gitattributes 가 아니라 .git/info/attributes 로 파일을 만든다.
-
attribute 로 머지는 어떻게 할지, 텍스트가 아닌 파일은 어떻게 diff 할지, checkin/cehckout 할 때 어떻게 필터링할지 정해줄 수 있다.
* 바이너리 파일
-
이 attribute 로 어떤 파일이 바이너리 파일인지 git 에 알려줄 수 있다.
기본적으로 git 은 어떤 파일이 바이너리인지 알지 못한다.
attribute 파일에 패턴으로 명시해주면 된다.
ex)
*.pbxproj binary
이렇게 하면 CRLF 변환이 적용되지 않고, git show 나 git diff 같은 명령을 실행할 때에도 diff 를 출력하지 않는다.
-
git은 바이너리 파일도 diff 할 수 있다.
git attribute 를 통해 바이너리 파일을 텍스트 포맷으로 변환하고 그 결과를 diff 명령으로 비교하도록 하는 것이다.
예를 들어 word 문서를 비교할 때 사용할 수 있다.
ex)
*.docx diff=word
이렇게 하면 docs 파일의 diff 시 word 필터를 사용하라고 설정하는 것이다.
word 필터도 정의해줘야 한다.
word 문서에서 사람이 읽을 수 있는 텍스트를 추출해주는 docx2txt 를 사용하여 diff 에 이용하면 된다.
ex)
$ git config diff.word.textconv docx2txt
* 키워드 치환
-
git 은 체크섬을 계산하고 커밋하기 때문에 그 커밋에 대한 정보를 가지고 파일을 수정할 수 없다.
하지만 checkout 할 때 그 정보가 자동으로 파일에 삽입되도록 했다가 다시 커밋할 때 삭제되도록 할 수 있다.
파일 안에 $ID$ 필드를 넣으면 blob 의 sha-1 체크섬을 자동으로 삽입한다.
이 필드를 파일에 넣으면 git 은 앞으로 checkout 할 때 해당 blob 의 sha-1 값으로 교체한다.
교체되는 체크섬은 커밋의 것이 아니라 blob 그 자체의 sha-1 체크섬이다.
-
commit/checkout 할 때 사용하는 필터를 직접 만들어 쓸 수 있다.
방향에 따라 clean 필터와 smudge 필터라 부른다.
checkout 할 때 파일을 처리하는 것을 smudge 필터이고, 커밋할 때 처리하는 필터가 clean 필터이다.
.gitattributes 파일에 설정하고 파일 경로마다 다른 필터를 설정할 수 있다.
-
이하 생략....
* 저장소 익스포트하기
-
프로젝트를 익스포트해서 아카이브를 만들 때도 git attribute 가 유용하다.
아카이브를 만들 때 제외할 파일이나 디렉터리를 설정할 수 있다.
특정 디렉터리나 파일을 프로젝트에는 포함하고 아카이브에는 포함하고 싶지 않을 때 export-ignore attribute 를 사용한다.
-
아카이브를 만들어서 배포할 때에도 git log 같은 포맷 규칙을 적용할 수 있다.
export-subst attribute 로 설정한 파일들의 키워드가 치환된다.
git archive 명령을 실행할 때 자동으로 마지막 커밋의 메타데이터가 자동으로 삽입되게 할 수 있다.
* Merge 전략
-
파일마다 다른 머지 전략을 사용하도록 할 수 있다.
머지할 때 충돌이 날 것 같은 파일이 있다고 하자.
Git attribute 로 이 파일만 항상 타인의 코드 말고 내 코드를 사용하도록 설정할 수 있다.
ex)
database.xml merge=ours
8.3. Git Hooks
-
이벤트가 생겼을 때 자동으로 특정 스크립트를 실행하도록 할 수 있다.
이 훅은 클라이언트 훅과 서버 훅으로 나눌 수 있다.
클라 훅은 커밋이나 머지할 때 실행되고, 서버 훅은 push 할 떄 서버에서 실행된다.
* 훅 설치하기
-
훅은 git 디렉터리 밑에 hooks 라는 디렉터리에 저장한다.
기본 훅 디렉터리는 .git/hooks 이다.
이 디렉터리에 가보면 git 이 자동으로 넣어준 매우 유용한 스크립트 예제가 몇 개 있다.
셸과 perl, ruby, python 등 다 가능하다.
실행할 수 있는 스크립트 파일을 확장자 없이 저장소의 hooks 디렉터리에 넣으면 훅 스크립트가 켜진다.
이 스크립트는 앞으로 계속 호출된다.
* 클라 훅
-
저장소를 clone 해도 클라 훅이 복사되지 않는다.
만든 정책이 반드시 적용되도록 하려면 서버 훅을 이용해야만 한다.
-
커밋과 관련된 훅은 모두 네 가지다.
-
pre-commit 은 커밋할 때 가장 먼저 호출되며, 커밋 메시지를 작성하기 전에 호출된다. 이 훅에서 커밋하는 snapshot 을 점검한다.
이 훅의 exit 코드가 0이 아니면 커밋은 취소된다.
git commit —no-verify 로 생략할 수 도 있다.
$ git commit --no-verify
-
prepare-commit-msg 훅은 git 이 커밋 매세지를 생성하고 나서 편집기를 실행하기 전에 실행된다.
이 훅은 사람이 커밋 메시지를 수정하기 전에 먼저 프로그램으로 손보고 싶을 때 사용한다.
이 훅은 커밋 메시지가 들어 있는 파일의 경로, 커밋의 종류를 아규먼트로 받는다.
그리고 amending 할 때는 SHA-1 값을 추가 아규먼트로 더 받는다.
-
commit-msg 훅은 커밋 메시지가 들어 있는 임시 파일의 경로를 아규먼트로 받는다.
그리고 이 스크립트가 0이 아닌 값을 반환하면 커밋되지 않는다.
이 훅에서 최종적으로 커밋이 완료되기 전에 프로젝트 상태나 커밋 메시지를 검증한다.
-
커밋이 완료되면 post-commit 훅이 실행된다.
-
이메일 워크플로에 해당하는 클라 훅은 세 가지다.
이 훅은 모두 git am 명령으로 실행된다.
자세한 내용은 생략....
-
pre-rebase 훅은 rebase 하기 전에 실행된다.
post-rewrite 훅은 커밋을 변경하는 명령을 실행했을 때 실행된다. 예를 들어 --amend 나 rebase 등에 해당한다. filter-branch 는 해당하지 않는다.
-
post-merge 훅은 머지가 끝나고 나서 실행된다.
pre-push 훅은 push 명령을 실행하면 동작하는데 리모트 정보를 업데이트 하고 난 후 리모트로 데이터를 전송하기 전에 동작한다.
훅에서 0이 아닌 값을 반환하면 push 를 중지시킨다.
-
git 은 정상적으로 동작하는 중에도 이따금 git gc --auto 명령으로 gc 를 한다.
pre-auto-gc 훅은 gc 가 실행되기 직전에 호출되는 훅이다.
* 서버 훅
-
서버 훅은 모두 push 전후에 실행된다.
push 전에 실행되는 훅이 0이 아닌 값을 반환하면 해당 push 는 거절되고 클라는 에러 메시지를 출력한다.
-
push 하면 가장 처음 실행되는 훅은 pre-receive 훅이다.
이 스크립트는 표준 입력(stdin)으로 push 하는 refs 목록을 입력받는다.
fast-forward push 가 아니면 거절하거나, 브랜치 push 권한을 제어하려면 이 훅에서 하는 것이 좋다.
관리자만 브랜치를 새로 push 하고 삭제할 수 있고 일반 개발자는 수정사항만 push 할 수 있게 할 수 있다.
-
update 스크립트는 각 브랜치마다 한번씩 실행된다는 것을 제외하면 pre-receive 스크립트와 거의 같다.
한 번에 브랜치를 여러 개 push 하면 pre-receive 는 한번 실행되지만, update 는 브랜치마다 실행된다.
-
post-receive 훅은 push 한 후에 실행된다.
이 훅으로 사용자나 서비스에 알림 메시지를 보낼 수 있다.
8.4. 정책 구현하기
-
커밋 메시지 규칙으로 검사하고 fast-forward push 만 허용하고 디렉터리마다 사용자의 수정 권한을 제어하는 워크플로를 만들 수 있다.
실질적으로 정책을 강제하려면 서버 훅으로 만들어야 한다.
개발자들이 push 할 수 없는 커밋은 아예 만들지 않도록 클라 훅도 만드는 것이 좋다.
* 서버 훅
-
자세한 내용 생략!
* 클라 훅
-
서버 훅의 단점은 push 할 때까지 push 할 수 있는지 없는지 알 수 없다는 데 있다.
기껏 정성껏 구현했는데 막상 push 할 수 없으면 곤혹스럽다.
clone 할 때 이 훅은 전송되지 않기 때문에 다른 방법으로 동료에게 배포해야 한다.
그 훅을 가져다 .git/hooks 디렉터리에 복사하고 실행할 수 있게 만든다.
이 훅 파일을 프로젝트에 넣어서 배포해도 되고, git 훅 프로젝트를 만들어 배포해도 된다.
-
자세한 내용은 생략...
8.5. 요약
'프로그래밍 놀이터 > Tips' 카테고리의 다른 글
[도서 정리] 10. Git 의 내부 - ProGit (0) | 2020.01.15 |
---|---|
[도서 정리] 9. Git 과 여타 버전 관리 시스템 - ProGit (0) | 2020.01.14 |
[도서 정리] 7. Git 도구 #2 - ProGit (0) | 2020.01.12 |
[도서 정리] 7. Git 도구 #1 - ProGit (0) | 2020.01.11 |
[도서 정리] 6. GitHub - ProGit (0) | 2020.01.10 |
댓글