본문 바로가기
프로그래밍 놀이터/Tips

[git] Git Tutorial ( 중급 강좌 ) - 기본+ 사용.

by 돼지왕 왕돼지 2012. 11. 10.
반응형




Git Tutorial ( 중급 강좌 ) - 기본+ 사용.

Git 서버

프로토콜

- Local, SSH, Http, Git 의 4가지 프로토콜을 제공한다.

- Http 를 제외하고는 모두 해당 프로토콜이 Git 서버에 설치되어 있어야 한다.

로컬 프로토콜

- 저장소가 디스크의 다른 디렉토리에 존재.

$ git clone /localPath/project.git

- copy 를 한다.
 

$ 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

- 공백문자에 대한 오류를 확인할 수 있다. ( 잘못사용된 공백을 'XXX' 로 표현해준다. )

- 최대한 하나의 issue 에 대한 수정사항을 하나로 커밋해야한다.

- 여러가지 이슈를 한번에 수정했어도 스테이지에 한번에 다 넣지 않아야 한다. 나누어 넣으면서 커밋해야 한다.

- 같은 파일의 다른 부분을 수정하는 경우에는

$ git add -patch

이용하여 한 부분씩 나누어 stage 에 저장할 수 있다.

- 커밋메세지를 잘 작성해야 한다.




비공개 소규모 팀

- 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 될지 볼 수 있다.


- 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>

- 2개의 branch 를 비교해 볼 수 있다.




Release 버전에 Tag 달기

- Tag를 달아놓으면 적당한 시점으로 돌아가기가 좋다.

$ git tag -s <version> -m '<Message>'

-s 는 서명한다는 의미, 서명을 하게 되면 사용한 PGP 공개키도 공개해야 한다.




빌드 넘버 만들기

$ git describe master

- 가장 가까운 태그이름, 얼마나 더 많은 커밋이 쌓였는가, 그리고 해당 커밋의 SHA-1 일부를 가져다 빌드넘버를 만든다. 




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

- 세번째 전 commit 을 보여준다. ( HEAD^^^ 와 같다. ) 




범위로 커밋 가르키기

- 여러 브랜치가 있을 때 관계를 파악하기 쉽다.

$ git log master..experiment

- master 에는 없지만 experiment 에는 있는 commit 들을 보여준다.
 

- 머지하기 전에 무엇이 변경되었나 확인하기가 좋다.

$ 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

- output 중 < 로 표시되는 것이 refA 에만 있는 녀석이고, >  로 표시되는 것이 refB 에만 있는 녀석이다.





대화형 명령어

$ git add -i

- 대화형 명령형으로 들어갈 수 있다.







Stashing

- 한 브랜치에서 일을 하고 있었는데, 중간에 다른 브랜치의 일을 먼저 해결해야 하는 경우가 있다. 이럴 경우에 완료하지 않은 일을 커밋하는 것은 껄끄럽다. 커밋하지 않고 나중에 다시 돌아와 일하고 싶을 때 사용하는 것이 Stashing 이다.

- Stash 는 modified 이면서 tracked 된 파일들과 staging area 에 있는 파일들을 저장해 놓는 곳이다. 스택에 잠시 저장해 두었다가 나중에 다시 불러올 수 있다.

하던 일 stashing 하기

$ git stash


$ git stash list

- stash 된 스택들을 확인할 수 있다.

$ git stash apply <stashName>

- stash 스택을 로드할 수 있다. ( 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

- subDirectory를 root-directory 로 만들어준다.




모든 커밋의 이메일 주소 수정하기

$ git filter-branch --commit-filter 'script'




Git 으로 버그찾기

파일 어노테이션

$ git blame -L 12,22 <fileName>

- SHA-1 값, 누가, 언제 그 줄을 커밋했는지 히스토리를 한줄한줄 볼 수 있다. SHA-1 앞에 ^ 가 붙어있다면 그 라인이 처음 커밋되었다는 것을 의미한다.




이진 탐색

$ git bisect start
$ git bisect bad    // 현재 commit 을 bad 라 표시
$ git bisect good <tagName | commit >    // 괜찮았던 commit 이나 tag 명시  

- 이렇게 수행하면 중간에 있는 녀석을 자동으로 checkout 해준다.

$ git bisect <good | bad >

 - 위 명령어를 통해 문제가 있는 commit 의 범위를 좁힐 수 있다.

$ git bisect reset

- 이진탐색모드를 종료한다.






서브 모듈

- git 저장소 안에 다른 git 저장소를 둘 수 있다.

서브모듈 시작하기

$ git submodule add <gitAddress> <directoryName>

- submodule 을 추가한다.

- submodule 은 directory mode가 16000 이 된다. 

- submodule 은 독립적으로 관리된다.




서브모듈이 있는 프로젝트 clone 하기

- main을 clone 하면 서브모듈은 디렉토리만 존재하고 내용물은 없다.

$ git submodule init
$ git submodule update 

 - 위 명령어를 통해 submodule 들의 내용들도 받아와야 한다.




슈퍼 프로젝트

- git 에서는 각 하위 디렉토리 모듈들을 별도의 git 저장소로 만들어야 한다.




서브 모듈을 사용할 때 주의해야 할 것들

$ git submodule update

update 시, 슈퍼프로젝트의 브랜치를 checkout 해버린다. 그럼 detached HEAD 상태가 되곤 한다. 데이터를 잃을 수 있기 때문에 detached HEAD 상태는 피하는 것이 좋다.



도움이 되셨다면 손가락 꾸욱~ ( 로그인 필요 x )






반응형

댓글