Git 서버
프로토콜
- Local, SSH, Http, Git 의 4가지 프로토콜을 제공한다.
- Http 를 제외하고는 모두 해당 프로토콜이 Git 서버에 설치되어 있어야 한다.
로컬 프로토콜
- 저장소가 디스크의 다른 디렉토리에 존재.
$ git clone /localPath/project.git
$ git clone file:///localPath/project.git
- network 처럼 프로세스를 따로 생성하여 처리한다.
- 이미 존재하는 git 프로젝트에는 다음과 같이 저장소를 추가한다.
$ git remote add local_proj /localPath/project.git
- 장점 : 간단하다.
- 단점 : 디렉토리를 공유하는 것 자체가 어렵다. 저장소를 mount 해야 하기 때문에 물리적으로 remote 한 곳에서 연결하는 것은 더욱 어려우며, 파일시스템을 마운트하여 사용하기 때문에 빠르지도 않다.
SSH 프로토콜
- SSH는 읽기/쓰기를 쉽게 할 수 있는 유일한 네트워크 프로토콜 ( HTTP 와 git 은 보통 읽기만 가능 )
- SSH는 인증도 지원한다.
$ git clone ssh://user@server:project.git
$ git clone user@server:project.git
- 장점 : 설정하기 쉬우며, 보안에 안전하다. 전송시 데이터를 압축하기 때문에 효율적이다.
- 단점 : 익명으로 접근할 수 없다. ( 읽기 전용인 경우에도.. ) 오픈소스와 같은 경우는 익명의 사용자들이 pull 할 수 있도록 SSH 를 설정해야 한다.
Git 프로토콜
- Git에 포함된 데몬 사용. 포트는 9418.
- SSH 와 비슷하지만, 인증 메커니즘이 없다.
- 저장소에 git-export-daemon-ok 파일이 있는 저장소만 서비스된다.
- 이 프로토콜로는 push 할 수 없다. ( 엄밀히 말하면 push는 가능하지만 인증할 수 없다. )
- 장점 : 전송속도가 가장 빠르다.
- 단점 : 인증 메커니즘이 없다. 그래서 대부분 SSH 로 push 하고 git 을 사용해서 pull 하는 방식을 섞어쓴다. 하지만 설정이 어려워진다.
HTTP/S 프로토콜
- HTTP 도큐먼트 루트에 bare 저장소를 놓고, post-update 훅을 설정하는 것이 전부.
$ git clone http://example.com/gitproject.git
- push 도 가능하지만, 환경 세팅하기가 어렵다.
- 장점 : 설정하기가 쉽다. HTTPS 를 이용하여 암호화도 할 수 있다. 서명된 SSL 인증서를 사용할 수 있게도 할 수 있다.
- 단점 : 클라이언트 측면에서 비효율적이다. HTTP 오버해드가 크다.
서버에 git 설정하기
- 어떤 서버를 설치하더라도 우선 저장소를 bare 로 만들어야 한다. working directory가 없는 저장소가 bare 저장소이다.
초간단 뚝딱
- 사용자를 관리하는 것이 가장 어렵다. (권한설정)
- 사용자를 추가할 때 사용자마다 adduser 를 실행하고 임시비번을 만들어줘야 한다. 직관적이지만 귀찮은 방법이다.
- 서버마다 git 계정을 만든다. 쓰기 권한이 필요한 사용자들의 SSH 공개키를 모아서 ~/.ssh/authorized_keys 파일에 키를 입력한다.
- LDAP 서버를 사용하면 더욱 쉽다.
SSH 공개키 만들기
- 사용자의 SSH 키들은 기본적으로 ~/.ssh 디렉토리에 저장된다.
- ~/.ssh 폴더에 id_rsa나 id_dsa 와 확장자 pub 이 붙은 녀석들이 있다면 공개키가 있는 것이다.
- ssh-keygen 을 수행하여 공개키를 만들 수 있다.
- 서버쪽에 공개키를 보내야 SSH 로 접근할 수 있다.
Gitosis
- authroized_keys 파일을 관리하고, 접근제어를 하는 스크립트 패키지
Hosted git
- GitHub 는 가장 큰 오픈소스 Git 호스팅 사이트
분산환경에서의 Git
분산환경에서의 workflow
중앙집중식 workflow
- push 하려면 다른 사람이 작업한 내용을 무조건 merge 한 다음에 해야 한다.
Integration-Manager workflow
- Integration manager 만 중앙서버에 push 할 수 있다.
- 프로젝트 참여자들은 중앙서버를 clone & pull 하여 사용한다.
- 프로젝트 참여자들은 수정내용을 자신의 public server에 push 해 놓는다.
- integration manager가 public server를 remote 저장소로 등록하고 내용들을 pull 하여 머지하고, 중앙서버에 push 한다.
Dictator and Lieutenants Workflow
- integration-manager workflow 의 변형판으로 중간머지를 하는 lieutenants들이 있고, 그것들을 머지하는 dictator가 있다.
- 매우 큰 오픈소스 프로젝트류에서 사용된다.
프로젝트에 기여하기
- 첫번째로 살펴볼 변수는 프로젝트 참여자수. 참여자 수가 늘어나면 머지가 어려워진다. ( conflict 가 많이 발생 )
- 두번째는 저장소의 운영방식. workflow는 어떤 것을 따르는가? 모든 수정사항을 review 하는가 등.
- 세번째는 접근 권한
커밋 가이드라인
$ git diff --check
- 최대한 하나의 issue 에 대한 수정사항을 하나로 커밋해야한다.
- 여러가지 이슈를 한번에 수정했어도 스테이지에 한번에 다 넣지 않아야 한다. 나누어 넣으면서 커밋해야 한다.
- 같은 파일의 다른 부분을 수정하는 경우에는
$ git add -patch
- 커밋메세지를 잘 작성해야 한다.
비공개 소규모 팀
- subversion 에서는 서버(공용저장소)로 push할때 자동 merge를 지원한다. 즉 서버가 머지작업을 한다.
- git 은 로컬에서 먼저 merge 해야만 서버로 push 할 수 있다.
$ git fetch origin
$ git merge origin/master
$ git push origin master
$ git log --no-merges origin/master^<otherBranchName>
- merge를 위해서는 우선 master branch 로 체크아웃 한 후에, branch 내용을 머지하거나 rebase 를 먼저 수행한다.
$ git checkout master
$ git merge <subBranchName> || $ git rebase <subBranchName>
$ git merge origin/master
$ git push origin master
비공개 대규모 팀
- integration-manager를 두었을 경우에는 master 가 아닌 다른 branch 에 푸시해야 한다.
$ git push origin <otherBranchName>
- featureB 라는 또 다른 branch를 만들어 수정하는 와중에 팀원이 featureBee라는 이름으로 먼저 push 한 경우에는 다음과 같은 순서를 따른다.
$ git fetch origin
$ git merge origin/featureBee
$ git push origin featureB:featureBee
- 해당 브랜치에 어떤 내용이 수정되었는지는 다음을 통해서 확인 가능하다.
$ git log origin/featureA^featureA
공개 소규모 팀
$ rebase -i
- Fork 기능을 제공하는 git 호스팅 사이트를 이용하여, fork를 만들어 쓰기권한이 있는 생성된 fork 에 push 를 하고, dictator가 나중에 merge 한다. 머지할 수 있도록 메세지를 보낼 수 있다.
$ git remote add <forkName> <URL >
$ git push <forkName> <branchName>
$ git request-pull origin/master <forkName>
프로젝트 운영하기
토픽 브랜치 작업
- 머지하기 전에 토픽 브랜치를 만들어 머지를 먼저 하고 난 후에 마스터에 다시 머지하는 것이 안전하고 좋다.
이메일로 받은 Patch 적용하기
$ git apply <patchName>
$ git am <patchName>
리모트 브랜치로부터 통합하기
$ git remote add <remoteName> <gitAddress>
$ git fetch <remoteName>
기여한 사항 확인하기
$ git diff <branch1> ... <branch2>
Release 버전에 Tag 달기
- Tag를 달아놓으면 적당한 시점으로 돌아가기가 좋다.
$ git tag -s <version> -m '<Message>'
빌드 넘버 만들기
$ git describe master
Release 준비하기
$ git archive master --prefix='project/' | gzip > 'git describe master'.tar.gz
- zip 형식은 '| gzip' 대신에 '--format=zip' 을 써준다.
Git 도구
브랜치 가르키키
$ git show <branchName>
RefLog 로 가르키기
- RefLog 란 HEAD 가 가르켰던 commit 의 이력
$ git show HEAD@{#}
계통 관계로 가르키기
- 이름 끝에 ^을 붙이면 해당 commit 의 부모를 찾는다.
- HEAD^ 는 바로 이전 커밋을 말한다.
$ git show HEAD^
- ~도 역시 부모를 찾는데, 뒤에 숫자를 쓸 수 있다.
$ git show HEAD~3
범위로 커밋 가르키기
- 여러 브랜치가 있을 때 관계를 파악하기 쉽다.
$ git log master..experiment
- 머지하기 전에 무엇이 변경되었나 확인하기가 좋다.
$ git log origin/master..HEAD
- not 이나 ^를 사용해서도 같은 녀석을 구현할 수 있다.
$ git log refA..refB
$ git log ^refA refB
$ git log refB -- not refA
$ git log refA...refB
$ git log --left-right refA...refB
대화형 명령어
$ git add -i
Stashing
- 한 브랜치에서 일을 하고 있었는데, 중간에 다른 브랜치의 일을 먼저 해결해야 하는 경우가 있다. 이럴 경우에 완료하지 않은 일을 커밋하는 것은 껄끄럽다. 커밋하지 않고 나중에 다시 돌아와 일하고 싶을 때 사용하는 것이 Stashing 이다.
- Stash 는 modified 이면서 tracked 된 파일들과 staging area 에 있는 파일들을 저장해 놓는 곳이다. 스택에 잠시 저장해 두었다가 나중에 다시 불러올 수 있다.
하던 일 stashing 하기
$ git stash
$ git stash list
$ git stash apply <stashName>
- stash 를 복구할 때는 꼭 해당 브랜치일 필요도, 작업이 없는 깨끗한 상태일 필요도 없다. 충돌이 나면 알려준다.
- stash 를 복구할 때 staged 상태를 기억해서 복원해주지 않는다. staged 상태까지 apply 하고 싶다면 --index 옵션을 주면 된다.
$ git stash apply --index
- apply 를 해도 스택에는 남아 있다. drop 을 통해 삭제해 줄 수 있다.
$ git stash drop <stashName>
- pop 명령은 apply 와 drop 을 동시에 수행한 효과이다.
Stash 되돌리기
- stash를 적용하고 나서 아차싶을 때는, 다음 명령어를 통해 복구할 수 있다.
$ git stash show -p stash@{0} | git apply -R
Stash 브랜치 만들기
- stash 를 적용할 때 깔끔한 환경이 아니라면 충돌이 생기기 쉽다. 이럴 경우 stash를 적용하는 새로운 브랜치를 만들면 쉽게 해결된다.
$ git stash branch <branchName>
히스토리 단장하기
- 커밋 히스토리를 수정할 수 있다.
- 커밋 순서도, 커밋 메세지와 커밋 파일도 변경할 수 있다.
- 여러개의 커밋을 하나로 합칠수도, 하나의 커밋을 여러개로 나눌수도 있다.
- 하지만 이 모든 것이 다른 사람들이 코드를 공유하기 전에 해야 한다.
마지막 커밋 수정하기
$ git commit --amend
- git add 나 git rm 을 통해서 staging 상태를 바꾼 후 git commit --amend 를 해주면 해당 파일들을 변경할 수 있다. 이미 push 한 커밋은 수정하면 안된다.
커밋 메세지를 여러 개 수정하기.
$ git rebase -i HEAD~3
- 위와 같은 명령어로 여러개를 동시에 수정할 수 있다. 커밋내용을 편집기를 통해 보여준다. 제일 위에 오는 것이 가장 오래된 녀석이다.
- 리베이스 스크립트를 닫으면 어떤 명령어들을 수행해야 하는지 알려준다.
- 절대 push 한 내용을 수정해서는 안된다.
커밋 순서 바꾸기
- 리베이스 스크립트에서 순서를 바꾸어주면 된다.
커밋 합치기
- 스크립트에서 합치려는 녀석들을 squash로 표시하고 합쳐지는 녀석만을 pick으로 남겨준다.
커밋 분리하기
- 스크립트에서 분리하려는 녀석을 edit 로 변경한다.
filter-branch 포크레인
- 모든 커밋의 공통된 정보의 변경이나, 어떤 파일 삭제 등의 작업은 filter-branch를 통해서 할 수 있다.
모든 커밋에서 파일 제거하기
- 잘못된 파일들이 추가되거나, 암호 파일들이 추가된 경우, 히스토리에서 완전 제거할 수 있다.
$ git filter-branch --tree-filter 'rm -f <fileName>' HEAD
- --tree-filter 옵션은 각 커밋에 명시한 명령어를 수행하고 그 결과를 재커밋한다.
하위 디렉토리를 루트 디렉토리로 만들기
$ git filter-branch --subdirectory-filter <subDirectoryName> HEAD
모든 커밋의 이메일 주소 수정하기
$ git filter-branch --commit-filter 'script'
Git 으로 버그찾기
파일 어노테이션
$ git blame -L 12,22 <fileName>
이진 탐색
$ git bisect start
$ git bisect bad // 현재 commit 을 bad 라 표시
$ git bisect good <tagName | commit > // 괜찮았던 commit 이나 tag 명시
- 이렇게 수행하면 중간에 있는 녀석을 자동으로 checkout 해준다.
$ git bisect <good | bad >
$ git bisect reset
서브 모듈
- git 저장소 안에 다른 git 저장소를 둘 수 있다.
서브모듈 시작하기
$ git submodule add <gitAddress> <directoryName>
- submodule 은 directory mode가 16000 이 된다.
- submodule 은 독립적으로 관리된다.
서브모듈이 있는 프로젝트 clone 하기
- main을 clone 하면 서브모듈은 디렉토리만 존재하고 내용물은 없다.
$ git submodule init
$ git submodule update
슈퍼 프로젝트
- git 에서는 각 하위 디렉토리 모듈들을 별도의 git 저장소로 만들어야 한다.
서브 모듈을 사용할 때 주의해야 할 것들
$ git submodule update
'프로그래밍 놀이터 > Tips' 카테고리의 다른 글
Specification By Example. Introduction (0) | 2012.11.11 |
---|---|
[git] Git Tutorial ( 기초 강좌 ) - 기본 사용 마스터. (0) | 2012.11.10 |
[Git] git에서 submodule 제거 하는 방법 (0) | 2012.10.31 |
[http] white space url encode 방법 (0) | 2012.10.24 |
[DB] mongo db basic shell command ( 몽고디비 기초 쉘 커맨드들 ) (0) | 2012.10.24 |
댓글