1.         기타 자료와 도구

Git 패키지에는 많은 뛰어난 도구들이 직접 포함돼있다.
하지만 Git apt-get이나 MacPorts 같은 패키지 관리자로 설치했다면, 이런 도구들을 별도로 설치해야 할 수도 있다.

 

gitk

gitk는 저장소 이력을 시각화하여 모든 브랜치가 어떻게 존재하고 있는지 보여준다.
gitk
Git 저장소의 이력을 탐색하기 위한 순수하게 Tcl/Tk로만 작성된 GUI로 발표되었다.

home 디렉터리의 .gitk 파일에 인터페이스를 자신에 맞게 변경하는 설정값을 추가할 수 있다.

11포인트 크기의 Panic Sans폰트를 사용하는 .gitk파일

set mainfont {{Panic Sans} 11}

set textfont {{Panic Sans} 11}

set uifont {{Panic Sans} 11 bold}

 

git-gui

git-gui: 저장소를 사용할 때 필요한 기본 명령어에 대한 인터페이스를 제공한다.

git-gui를 사용하여 추적되지 않는 파일이나, 변경된 파일, 스테이징된 파일을 볼 수 있으며, 변경 사항을 스테이징하거나 커밋할 수도 잇다.

 

gitweb Git 저장소에 대한 웹 클라이언트다.

gitweb은 저장소를 확인하는데 필요한 모든 기능을 웹 인터페이스로 제공한다.

 

GitX OS X 전용으로 개발된 gitk의 복제본이다.
OS X
애플리케이션 고유의 UI를 빼면 모든 기능이 동일하다
.
gitk
와 동일하게 한 번에 하나의 브랜치 혹은 여러 개의 브랜치를 동시에 확인할 수 있으며, 가장 최신 버전의 경우 git-gui처럼 커밋하는 기능도 포함한다.

 

Komodo IDE : ActiveState Git을 포함한 몇 종류의 분산 버전 관리 시스템을 Komodo IDE 5.0 릴리스에 통합하여 지원하기로 발표했다. Komodo는 스크립트 언어와 웹 개발에 특화된 통합 개발 환경이다.

 

이클립스 Git 플러그인 : www.eclipse.org/egit

 

TextMate Git 번들 : 스크립트 언어를 위한 놀라운 지원과 사용의 편리함으로 OS X을 사용하는 개발자들에게 인기 있는 편집기. gitorious.org/projects/git-tmbundle

 

VCSCommand : 편집기 Vim의 플러그인이다.
VCSCommand
.vimrc 파일에 추가된 몇 개의 단축키를 조합하면, 모든 플랫폼에서 프로그래밍 프로젝트를 대부분 시작할 수 있다.

 

GitNub : gitk와 비슷한 맥 전용 도구. 기본적인 이력 보기 기능을 제공하며, GitNub의 호스팅 서비스를 이용하고 있다면 GitHub의 타임라인 뷰어와 통합해서 사용할 수 있다.
github.com/Caged/gitnub

 

TicGit : 티켓 추적 시스템은 누가 무슨 일을 하고 있는지 추적한다. 기존의 티켓 추적 시스템을 도입하면 분산 도구 모음 속에서 중앙 집중식 시스템을 사용할 수 밖에 없게 된다.
TicGit
Git안에서 동작하는 간단한 분산 티켓 시스템으로 연결이 끊긴 분산 환경ㅇ르 유지하도록 해준다.

 

git-sh : Git명령어를 입력할 때 git을 입력하지 않아도 된다. 체크아웃을 할 때는 checkout, 커밋할 때는 commit만 입력하면 된다.

git-sh Git에 특화된 쉘을 실행하고 모든 Git 명령어에 대해 별칭을 생성한다.
또한 명령 프롬프트가 위치한 현재 저장소명과 브랜치명을 추가하면 현재 브랜치를 보려고 git branch를 입력할 필요가 없다.

 

 

 

2.         GitHub로 저장소 호스팅하기

직접 Git 서버를 운용하지 않을 때 사용할 만한, 저장소 호스팅 서비스가 몇 개 있다.

오픈 소스로만 사용이 가능한 서비스부터 상업적으로 이용 가능한 서비스까지 존재.

 

repo.or.cz : 오픈 소스 프로젝트를 위한 무료 Git 저장소를 제공.

GitHub : 오픈 소스 프로젝트에는 무료지만, GitHub를 이용하여 프로젝트를 관리하려는 회사가 비용을 지불하면, 사용할 수 있는 접근이 제한된 사설 호스팅도 사용할 수 있다.

Gitorious : 무료 Git 호스팅 서비스.

 

git.or.cz : Git과 관련된 모든 소스가 있는 Git의 주요 웹사이트.

Git 매뉴얼 : www.kernel.org/pub/software/scm/git/docs/

Git 메일링 리스트 : git@vger.kernel.org

#git IRC 채널

forums.pragprog.com/forums/64

 

 

 

출처: [인사이트]Git, 분산버전 관리시스템


출처 : http://youmin3.egloos.com/1991175

1.         Git 명령어 요약

1.1.        설정과 초기화

전역 사용자명/ 이메일 구성하기

$ git config --global user.name YOUR NAME

4 git config --global user.email YOU@EXAMPLE>COM

 

저장소 하나에 사용자명 / 이메일 구성하기

주의: 저장소마다 사용자명과 이메일 주소를 설정할 수 있다. 따라서 프로젝트마다 각각 다른 사용자명과 이메일 주소를 사용할 수 있다.

$ cd /path/to/repo

$ git config user.name YOUR NAME

$ git config user.email YOU@EXAMPLE.com

 

Git의 출력결과 색상 활성화하기

$ git config --global color.ui auto

 

새로운 저장소 초기화하기

$ mkdir /path/to/repo

$ cd /path/to/repo

$ git init

$ git add .

$ git commit m initial import

 

저장소 복제하기

$ git clone <저장소 url>

 

기존 디렉터리에 Git 추가하기

$ cd /path/to/existing/directory

$ git init

$ git add .

$ git commit m initial import of some project

 

새로운 원격 저장소 추가하기

저장소 디렉터리에서 실행한다

$ git remote add <원격 저장소> <저장소 url>

 

 

 

1.2.        기본적인 사용법

새로운 파일을 추가하거나 존재하는 파일 스테이징하고 커밋하기

$ git add <file>

$ git commit m <message>

 

파일의 일부를 스테이징하기

$ git add p [<file> [<file> [기타 파일들 ]]]

커밋하려는 헝크를 선택한다.

 

add 명령에서 Git 대화모드를 사용하여 파일 추가하기

$ git add i

 

수정되고 추적되는 파일의 변경 사항 스테이징하기

git add u [<경로> [<경로>]]

 

수정되고 추적되는 모든 파일의 변경 사항 커밋하기

$ git commit m <message>a

 

작업 트리의 변경 사항 돌려놓기

$ git checkout HEAD <file> [<file>]

 

커밋되지 않고 스테이징된 변경 사항 재설정하기

$ git reset HEAD <file> [<file>]

 

마지막 커밋 고치기

.. 변경하고 스테이징한다

$ git commit m <message>amend

 

이전 커밋을 수정하고 커밋 메시지를 재사용하기

$ git commit C HEAD --amend

 

 

 

1.3.        브랜치.

지역 브랜치 목록 보기

$ git branch

 

원격 브랜치 목록 보기

$ git branch r

 

지역과 원격을 포함한 모든 브랜치 목록 보기

$ git branch a

 

현재 브랜치에서 새로운 브랜치 생성하기

$ git branch <새로운 브랜치>

 

다른 브랜치 체크아웃하기

$ git checkout <branch>

 

현재 브랜치에서 새로운 브랜치 생성하고 체크아웃하기

git checkout b <새로운 브랜치>

 

다른 시작 지점에서 브랜치 생성하기

브랜치는 저장소 이력에 존재하는 어떤 위치에서도 생성될 수 있다.
브랜치를 생성할 위치는 다른 브랜치나 커밋명 혹은 태그가 될 수 있다.

$ git branch <새로운 브랜치> <브랜치를 생성할 위치>

 

기존의 브랜치를 새로운 브랜치로 덮어쓰기

$ git branch f <기존 브랜치> [<브랜치를 생성할 위치>]

 

브랜치를 옮기거나 브랜치명 변경하기

<새로운 브랜치>가 존재하지 않을 경우

$ git checkout m <기존 브랜치> <새로운 브랜치>

 

브랜치를 무조건 덮어쓴다.

$ git checkout M <기존 브랜치> <새로운 브랜치>

 

다른 브랜치를 현재 브랜치로 합치기

$ git merge <브랜치>

 

커밋하지 않고 합치기

$ git merge --no-commit <브랜치>

 

선택하여 합치기

$ git cherry-pick <커밋명>

 

커밋하지 않고 선택하여 합치기

$ git cherry-pick n <커밋명>

 

브랜치의 이력을 다른 브랜치에 합치기

$ git merge --squash <브랜치>

 

브랜치 삭제하기

삭제할 브랜치가 현재 브랜치에 합쳐졌을 경우에만

$ git branch d <삭제할 브랜치>

 

삭제할 브랜치가 현재 브랜치에 합쳐지지 않았어도

$ git branch D <삭제할 브랜치>

 

 

 

1.4.        이력

모든 이력 보기

$ git log

 

변경 사항을 보여주는 패치와 함께 로그 표시하기

$ git log p

 

1개의 항목만 보이도록 로그 개수 제한하기

$ git log -1

 

20개의 항목과 패치만 보이도록 로그제한하기

git log -20 p

 

6개월 동안의 커밋 로그 보기

$ git log since=6 months

 

2일 전까지의 커밋 로그 보기

$ git log before=2 days

 

HEAD 보다 3개 이전의 커밋 로그 보기

$ git log -1 HEAD-3

or

$ git log -1 HEAD^^^

or

$ git log -1 HEAD~1^^

 

두 지점 사이의 커밋 로그 보기

<시작 지점> <끝 지점>은 커밋명이나 브랜치명 혹은 태그명이며, 조합하여 사용할 수 있다.

$ git log <시작 지점><끝 지점>

 

각 항목의 로그 이력 한 줄씩 보기

$ git log pretty=oneline

 

각 항목마다 영향 받은 줄의 통계보기

$ git log --stat

 

커밋할 시점의 파일 상태 보기

$ git log --name-status

 

현재 작업 트리와 인텍스의 차이점 보기

$ git diff

 

인덱스와 저장소의 차이점 보기

$ git diff --cached

 

작업트리와 저장소의 차이점 보기

$ git diff HEAD

 

작업트리와 특정 위치 간의 차이점 보기

<시작지점>은 커밋명이나 브랜치명 혹은 태그명이다.

$ git diff <시작지점>

 

저장소의 두 지점 사이의 차이점 보기

$ git diff <시작지점> <끝 지점>

 

차이점의 통계보기

$ git diff --stat <시작지점> [<끝지점>]

 

파일의 커밋 정보 줄 단위로 보기

$ git blame <file>

 

파일의 줄 단위의 복사, 붙여 넣기, 이동 정보 보기

$ git blame C C <file>

 

로그에서 복사와 붙여 넣은 정보 보기

$ git log C C p 1 <특정 지점>

 

 

 

1.5.        원격 저장소

저장소 복제하기

$ git clone <저장소>

 

마지막 200개의 커밋만 포함하여 저장소 복제하기

$ git clone depth 200 <저장소>

 

새로운 원격 저장소 추가하기

$ git remote add <원격 저장소> <저장소 url>

 

모든 원격 브랜치 목록 보기

$ git branch r

 

원격 브랜치에서 지역 브랜치 생성하기

$ git branch <새로운 브랜치> <원격 브랜치>

 

원격 태그에서 지역 브랜치 생성하기

$ git branch <새로운 브랜치> <원격 태그>

 

origin 저장소에서 합치지 않고 지역 브랜치로 변경 사항 가져오기

$ git fetch

 

원격 저장소에서 합치지 않고 지역 브랜치로 변경 사항 가져오기

$ git fetch <원격 저장소>

 

원격 저장소에서 변경 사항을 가져와 현재 브랜치에 합치기

$ git pull <원격 저장소>

 

origin 저장소에서 변경 사항을 가져와 현재 브랜치에 합치기

$ git pull

 

지역 브랜치를 원격 브랜치에 푸싱하기

$ git push <원격 저장소> <지역 브랜치>:<원격 브랜치>

 

지역 브랜치를 동일한 이름의 원격 브랜치에 푸싱하기

$ git push <원격 저장소> <지역 브랜치>

 

새로운 로컬 브랜치를 원격 저장소에 푸싱하기

$ git push <원격 저장소> <지역 브랜치>

 

지역 변경 사항을 origin 저장소에 푸싱하기

이러한 방식은 origin 저장소에 존재하는 브랜치에만 푸싱한다.
새로운 브랜치에 푸싱하려면 반드시 git push <저장소명> <지역 브랜치> 형태로 실행해야 한다.

$ git push

 

원격 브랜치 삭제하기

$ git push <원격 저장소> :<원격 브랜치>

 

원격 저장소에서 쓸모가 없어진 원격 브랜치 제거하기

$ git remote prune <원격 저장소>

 

원격 저장소를 제거하고 관련된 브랜치도 제거하기

$ git remote rm <원격 저장소>

 

 

 

1.6.        GitSVN 연결하기

서브버전 저장소 전체를 복제하기

$ git svn clone <svn 저장소>

 

표준 레이아웃을 사용하는 서브버전 저장소 전체를 복제하기

표준대로 trunkbranches tags를 저장소 구조로 사용하는 저장소를 복제할 때 사용한다.

$ git svn clone s <svn repository>

 

비표준 레이아웃을 사용하는 서브버전 저장소 전체를 복제하기

$ git svn clone T <트렁크 경로> -b <브랜치 경로> -t <태그 경로> <svn 저장소>

 

표준 레이아웃을 사용하는 서브버전 저장소 전체를 복제하기

$ git svn clone s r 2321

 

표준 레이아웃을 사용하는 서브버전 저장소를 복제하고, 모든 원격 브랜치에 접두어를 추가하기

$ git svn clone s --prefix svn/ <svn 저장소>

 

상위의 서브버전 저장소에서 갱신하고 재정렬 하기

$ git svn rebase

 

상위의 서브버전 저장소에 커밋 푸싱하기

$ git svn dcommit

 

상위 서브버전 저장소에 푸싱될 커밋 목록 보기

$ git svn dcommit n

 

서브버전 저장소 로그 보기

$ git svn log

 

서브버전 저장소 파일의 커밋정보 줄단위로 보기

$ git svn blame <파일>

 

출처 : http://youmin3.egloos.com/1991150

1.         Gitosis를 이용하여 Git 서버 운용하기

Git은 분산 버전 관리 시스템이기도 하지만, 파일시스템을 기반으로 사용하고 있으면서, 내용을 버전으로 관리하면, 효과적인 애플리케이션을 구축하기 위한 플랫폼이기도 하다.

Gitosis는 원격 Git 서버와 서버의 저장소를 관리하기 위한 도구이며,
저장소에 Gitosis의 구성을 저장하여 이런 관리 작업을 처리한다
.
서버의 구성을 변경하려고 한다면, 새로운 구성을 Gitosis 저장소에 푸싱하기만 하면 된다.

 

Gitosis .git/hooks/ 디렉터리에 있는 후킹(hooking) 스크립트를 이용해서 이런 작업들을 처리한다.
후킹 스크립트는 커밋 전(pre-commit 스크립트)이나 커밋 후(post-commit 스크립트)와 같은 이벤트에 따라 실행된다.

또한, Gitosis는 후킹 스크립트를 통해 생성한 저장소에 대한 구성 파일도 갱신하는데,
빈 저장소를 만들고, 사용자에게 저장소 읽기, 쓰기 권한을 설정하는 등의 작업을 할 수 있다.

Gitosis 설치 단계는 다음과 같다.

(1)    의존성을 만족하는지 확인하기

(2)    Gitosis 설치하기

(3)    Gitosis를 위한 서버구성

(4)    관리자 인증서(credential) 생성하기

(5)    Gitosis 초기화하기

(6)    Gitosis 구성하기

 

 

 

1.1.        의존성을 만족하는지 확인하기

Gitosis는 몇 가지 의존성을 가진다.
먼저, Gitosis가 파이선으로 작성되었기 때문에 시스템에 파이선이 설치되있어야 한다.

그 다음은 Python Enterprise Application Kit, PEAK에서 EasyInstall 패키지가 필요하다.
EasyInstall
은 개발자들이 파이선 기반 애플리케이션을 설치하고 관련 의존성을 해결하도록 돕는다. EasyInstall도 잘 알려진 패키지이니 먼저 시스템에 설치되어 있는지 다음 명령어를 실행해서 확인해보자.

$ python c import setuptools

EasyInstall setuptools 모듈이 이용 가능하다면 아무런 출력도 보여주지 않는다.

 

 

 

1.2.        Gitosis 설치하기

Gitosis는 지금도 활발히 개발 중에 있으므로 소스 코드로부터 직접 설치해야 한다.

다음 명령어로 Git 저장소를 복제하여 Gitosis의 소스 코드를 바로 받을 수 있다.

$ git clone git://eagain.net/gitosis

이제 gitosis 디렉토리에 Gitosis의 소스 코드가 있다.
Gitosis
를 설치하려면 다음과 같이 gitosis 디렉터리로 이동해서 setup.py를 실행한다.

$ cd gitosis

$ sudo python setup.py install

 

Gitosis를 설치했으니 Gitosis가 이용할 서버의 사용자 계정을 설정해야 한다.
Gitosis
를 위한 사용자 계정을 설정하려면 사용자에 대한 인증서가 필요하다.

 

 

 

1.3.        관리자 인증서 생성하기

SSH에서 사용자의 연결을 검증할 때 비밀번호 대신 SSH 공개키를 사용하므로, Gitosis 관리자에 대한 SSH 공개키를 반드시 생성해야 한다.

사용하던 공개키가 있다면 새로 생성하는 대신 기존의 키를 이용해도 된다. 가지고 있는 공개키가 없다면 새로 생성하자. 공개키는 커맨드 라인에서 ssh-keygen 명령어를 실행해서 생성한다.

ssh-keygen 명령어는 Gitosis가 동작하는 서버에 접속할 때 사용하는 자신의 컴퓨터에서 실행해야 한다. 커맨드 라인에서 다음 명령어를 실행해서 자신의 키를 생성한다.

$ ssh-keygen t rsa

 

ssh-keygen 프로그램은 사용자의 키를 생성하고, 새로 생성된 키에 대한 정보를 알려준다.
생성 위치와 이름을 기본값으로 그냥 뒀다면 다음 경로에 공개키가 생성된다.

/home/<사용자명>/.ssh/id_rsa.pub

이 파일을 서버에 복사한다. 이 파일은 이어지는 내용에서 Gitosis를 초기화할 때 바로 사용한다.

 

 

 

1.4.        Gitosis를 위한 서버 구성하기

Gitosis가 사용자의 서버에서 동작하려면 서버에 Gitosis 전용 사용자 계정이 있어야 하고, 모든 저장소를 저장할 디렉터리도 필요하다.

시스템에 Gitosis를 위한 새로운 사용자가 있어야 한다.
Gitosis
용 사용자 계정의 홈 디렉터리에 Gitosis 관련 구성값과 저장소를 보관한다
.
대부분의 리눅스 시스템에서는
home /path/to/home 형식을 추가하면 홈 디렉터리를 지정할 수 있다.

사용자 홈 경로는 시스템의 어디를 지정해도 상관없지만, Gitosis의 규약은 /srv/example.com/git로 설정하는 것이다. 여기서 example.com을 자신의 도메인으로 바꾸기만 하면 된다.

 

사용자명을 git으로 설정한 예.

$ sudo adduser --shell /bin/sh \

               --group \

               -- disabled-password \

               --home /srv/example.com/git

               git

 

 

 

1.5.        Gitosis 초기화하기

Gitosis에는 초기화 과정을 수행하는 gitosis-init이라는 프로그램이 있다.

gitosis-init을 실행할 때 지정해야 할 옵션은 없지만, 이전 절에서 생성한 사용자 계정으로 실행해야 한다.

$ sudo H u git gitosis-init < /path/to_id_ras.pub

 

프로그램이 실행되면 Gitosis와 저장소가 초기화된다.
오래된 setuptools를 이용하고 있다면, 실행 권한이 빠질 수 있다고 한다. 그런 경우 다음 명령어를 실행해서 실행 권한을 추가하도록 권고하고 있다.

$ sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

 

$PATH 변수에 존재하지 않는 위치에 Git을 설치했다면, OSError 오류를 겪게 된다. OSError 오류는 gitosis-init 명령어에서 Git을 찾을 수 없을 때 발생한다.

이 문제를 해결하려면 git 사용자가 Git의 명령어들을 이용할 수 있도록 해야 한다.
Gitosis
가 동작하는 사용자의 $PATH 변수를 수정하거나, Gitosis의 사용자 $PATH 변수에 포함된 아무 경로에서나 git 바이너리의 심볼릭 링크를 추가하면 된다.

 

 

 

1.6.        Gitosis 구성하기

Gitosis의 구성 저장소를 복제해야 한다.

구성 저장소는 새로운 저장소를 관리하는 데 필요한 모든 구성값을 가지고 있다. 구성 저장소는 SSH 공개키를 생성한 컴퓨터에서 복제해야 한다.

$ git clone git@example.com:gitosis-admin.git

 

새로 복제한 디렉터리에는 gitosis.conf 파일과 keydir/ 디렉터리가 있다.
gitosis.conf
는 단순한 INI 형식의 파일이다
.
대괄호로 각 영역을 나타내며 각 항목은
이름=의 형식이다
.
파일을 열어보면 다음과 유사한 기본 구성을 볼 수 있다.

[gitosis]

 

[group gitosis-admin]

writable = gitosis-admin

members = travis

 

[group gitosis-admin]이후
첫째 줄에서 이 그룹이 gitosis-admin 저장소에 쓰기 권한을 가진다고 지정한다.

둘째 줄에서는 열거한 사용자들이 이 그룹에 포함된다고 지정한다. 여기서는 travis 한 명만 포함시켰다.

members 필드의 값은 공백으로 구분한다.
이때, members 필드에 기록된 각 사용자의 이름은 keydir/ 디렉터리에 있는 동명의 .pub 확장자를 가진 파일을 참조한다. 예를 들면, 필자의 키는 keydir/travis.pub에 있다.

 

새로운 사용자를 추가하려면, 추가하려는 사용자의 공개 SSH키가 필요하다.
저장소에 접근하려는 모든 개발자는 자신의 컴퓨터에서 SSH 공개키를 생성해야 한다
.
공개키의 생성은 앞에서 이용한 명령어를 그대로 이용하면 되지만, 반드시 접근하려는 개발자의 컴퓨터에서 생성해야 한다. 생성된 공개키는 특정 컴퓨터에 종속적이기 때문이다.

각 개발자의 공개키 복사본을 전달 받으면 공개키에 사용자명을 붙여서 keydir/ 디렉터리에 복사하고, 접근을 허용할 저장소에 파일명에서 이용한 사용자명을 추가한다. 방금 변경한 내용은 지역 저장소에 커밋한 후 git push 명령어를 이용해서 Gitosis 서버에 푸싱해야 한다.

 

 

 

1.7.        새로운 저장소 추가하기

Gitosis가 생성하는 초기 구성에는 하나의 구성 저장소가 있다. 하지만 원하는 만큼의 저장소를 관리할 수 있다. 필요하다면 새로운 writable 영역에 gitosis-admin 그룹에 추가할 수 있다. 하지만 이렇게 하면 저장소에 접근 가능한 모든 사람이 Gitosis 구성을 변경할 수 있다. 보다 안전하게 관리하려면 관리를 위한 그룹과 개발자를 위한 그룹으로 2개의 그룹을 만든다.

[gitosis]

 

[group gitosis-admin]

writable = gitosis-admin

members = travis

[group team]

writable = mysite

members = travis Susannah

 

첫 번째 [group]은 앞에서 작성했던 부분이다.
기존 그룹은 그대로 두고 team이라는 그룹을 새로 추가했다. 추가한 그룹에 포함된 구성원에게는 mysite 저장소에 대한 쓰기 권한을 부여했다. 이렇게 하면 travis susannah가 쓰기 권한을 얻는다.

생성하려는 저장소마다 생성할 저장소 이름을 포함하는 새로운 writable 줄을 추가한다. 다시 한번 변경 사항을 커밋하고 서버에 푸싱한다. 변경사항을 푸싱하고 나면 새로운 원격 저장소에 내용을 추가할 수 있다.

모든 지역 Git 저장소에서는 새로운 원격 저장소로 내용을 보낼 수 있다. 물론 전송하려면 지역 저장소에는 적어도 하나의 커밋이 있어야 한다. 저장소의 작업 트리에서 다음 명령어를 실행하면 원격 저장소를 자신의 구성에 추가할 수 있다.

$ git remove add origin git@example.com:mysite.git

이 명령어는 mysite 원격 저장소를 지역 저장소의 구성에 origin 저장소로 추가한다.

 

자신의 지역 저장소의 내용을 원격 저장소에 푸싱하기

아직 원격 저장소에 존재하지 않는 브랜치이므로 반드시 푸싱 대상 브랜치명을 지정해야 한다.

$ git push origin master

접근 권한을 가진 다른 사용자가 저장소를 복제할 수 있고, 쓰기 권한을 줬다면 변경 사항을 푸싱할 수도 있다.

 

오픈 소스 프로젝트라면 일반 대중이 저장소에 접근할 수 있어야 하며, 지역 가상 사설망(VPN)이라면 자신의 저장소를 회사의 모든 사람에게 열어둬야 한다. 하지만 누가 내용을 읽었는지에 대한 로그를 추적할 필요는 없을지도 모른다.

git daemon을 이용하면 자신의 저장소를 익명의 사용자에게 읽기 전용으로 공개하도록 설정할 수 있다.

 

 

 

1.8.        공개 저장소 설정하기

자신의 저장소를 읽기 전용을 설정하기.

일일이 사용자를 설정하는 게 아니라 자신의 작업을 다른 개발자와 공유하려는 경우에만 읽기 전용으로 설정한다. 읽기 전용 저장소는 누구라도 저장소를 읽을 수 있는 오픈 소스 개발에서 매우 흔한 방식이다.

읽기 전용으로 설정할 때는 2단계를 따른다.
먼저, 자신의 저장소를 Gitosis로 공유할 수 있도록 구성한다
.
다음으로, git daemon을 실행하여 요청에 대해 응답할 수 있도록 한다.

Gitosis를 구성하려면 앞에서 봤던 gitosis.conf를 편집해야 한다.

이번에는 repo라는 영역을 저장소 이름과 함께 추가한다.
예를 들어, 자신의 저장소 이름이 web이라면 다음과 같이 추가하면 된다.

[repo web]

 

이 내용은 새로운 영역을 추가하기 위한 INI 설정이다.
이 부분 이후에 나오는 내용은 모두 이 영역에 포함된 내용임을 표시한다
.
이제 daemon = yes라는 줄을 추가해서 git daemon이 이 저장소를 읽을 수 있다고 표시한다. 지금까지 추가한 내용은 다음과 같다.

[repo web]

daemon = yes

 

이것으로 구성 단계는 모두 마치고, 변경 사항을 커밋하고 서버에 푸싱하자.
이제 git daemon을 설정할 차례다.

 

앞에서 생성한 git 사용자로 git daemon을 실행해야 한다.
명령어 앞에 sudo
u git을 붙여서 실행하는 게 가장 간단한 방식이다.

그 외에 git daemon에 지정해야 하는 매개변수로는 --base-path가 있다.
--base-path
로 저장소의 위치를 지정한다
.
지금까지 사용해온 구성을 따르면 저장소는 /srv/example.com/repositories에 있다.

git daemon을 실행하는 실제 명령어는 다음과 같다.

$ sudo u git git daemon \

       --base-path /srv/example.com/repositories/

 

제대로 동작하는지 확인해보려면 자신의 읽기 전용 저장소 중에 하나를 복제해 본다. web 저장소를 복제할 경우 명령어는 다음과 같다.

$ git clone git://example.com/web.git

 

여기서 실행한 git daemon 명령어는 사용자가 로그인한 동안만 동작한다. 그리고 서버가 부팅할 때마다 실행되지도 않는다. 운영체제에 따라서 이런 문제는 약간씩 다르게 다룰 수 있다.

필자는 서버에서 로그아웃한 후에도 git daemon을 동작하도록 하려고 nohup을 이용한다. 그렇다고 서버를 재부팅한 다음에도 자동으로 실행될 필요는 없었다. 이용한 명령어는 다음과 같다.

$ nohup sudo u git git daemon --base-path /srv/example.com/repositories &

명령어의 마지막 &, 실행되는 명령어를 현재 터미널 세션에서 분리하며,
명령어의 시작에 있는 nohup은 현재 사용자에 종속되지 않도록 한다.

 

출처 : http://youmin3.egloos.com/1990886

1.         Git으로 옮겨가기

1.1.        SVN과 통신하기

 

서브버전 명령어에 해당하는 Git 명령어

svnadmin create

git init

svn checkout

git clone

svn update

git pull

svn add

git add

svn commit

git add

git commit

svn status

git status

svn switch <branch>

git checkout <branch>

svn merge <branch>

git merge <branch>

svn revert <file>

git checkout <file>

 

CVS 명령어에 해당하는 Git 명령어

cvs d<repo> init

git init

cvs d<repo>

checkout <module>

git clone

cvs update dP

git pull

cvs add

git add

cvs commit

git add

git commit

cvs status

git status

cvs co r <branch>

git checkout <branch>

cvs update j

git merge

cvs update C

git checkout <file>

 

서브버전에서 Git으로 옮겨오는 방식에는 2가지가 있다.
첫 번째는 서브버전에서 모든 이력을 가져오고, 서브버전을 대체해서 Git을 버전 관리 시스템으로 이용하는 방식이다.

두 번째는 서브버전을 그대로 유지하고, Git을 활용해 서브버전에서 변경사항을 가져오고, 변경된 내용을 서브버전에 다시 푸싱하는 방식이다.

 

서브버전 저장소 가져오기

서브버전 저장소

git svn clone è

자신의 Git 저장소

 

서브저번 저장소를 상위 저장소로 이용하기

서브버전 저장소

git svn clone è

 

git svn rebase è

çgit svn commit

자신의 Git 저장소

 

 

 

1.2.        git-svn 설치 확인하기

git-svn Git에서 서브버전 저장소와 통신할 때 사용하는 도구이다.
Git
을 어떻게 설치했는지에 따라 git-svn이 이미 설치돼 있을 수도 있다
.
다음 명령어를 실행하여 확인해 보자.

$ git svn version

git-svn version 1.6.0.2 (svn 1.4.4)

 

정상적인 메시지 대신 오류 메시지를 출력한다면 다음 2가지 중 하나이다.

l       Git에서 SVN이 명령어가 아니거나 치명적인 오류(fatal error)라고 알려주는 메시지.

l       SVN/Core.pm을 찾을 수 없다는 메시지

 

 

 

1.2.1.       Git 명령어가 아니거나 치명적인 오류인 경우

이 문제는 우분투의 apt-get이나 OS X MacPorts와 같은 패키지 관리자를 이용해 Git을 설치한 경우 흔히 발생하는데, 패키지 관리자를 통해 패키지를 설치할 때 의존 관계에 있는 패키지를 줄이려고 Git을 여러 개의 작은 패키지로 나눠두었기 때문이다.

리눅스에서 git-svn을 설치하려면 서브버전 하위 명령어를 포함하는 패키지를 찾아야 한다.
우분투에서는 apt-get을 이용해 git-svn을 지정하면 설치할 수 있다.

$ sudo apt-get install git-svn

 

2.1 Git 설치하기에서 설명한 대로 MacPorts를 이용해 설치했다면, 따로 git-svn을 설치하지 않아도 된다. 마찬가지로, 소스에서 컴파일해서 설치한 경우도 추가로 설치하지 않아도 된다.

 

 

 

1.2.2.       SVN/core.pm을 찾을 수 없는 경우

다른 오류로는 SVN/core.pm이 없다는 perl 메시지가 있으며, 설치된 서브버전에 대한 펄 바인딩이 없을 때 발생한다.

필요한 파일을 얻는 데는 몇 가지 방법이 있지만, 대부분의 경우 패키지 관리자를 이용하는 편이 가장 쉽다.

우분투에서는 누락된 페키지를 subversion-perl이라 부르며, 다음 명령어를 실행하여 설치한다.

$ sudo apt-get install subversion-perl

 

맥 사용자라면 MacPorts 패키지 관리자를 이용해 subversion-perlbindings를 설치한다.

$ sudo port install subversion-perlbindings

 

CPAN을 사용하여 펄 라이브러리를 최신 상태로 유지하고 있다면, 필요한 패키지를 바로 설치할 수 있다. 설치할 패키지는 SVN::Core이다.

$ sudo cpan install SVN::Core

 

 

 

1.3.        서브버전 저장소 가져오기

git svn clone 명령어를 이용한다는 차이를 제외하고, 기존에 Git에서 저장소를 가져오던 방식과 동일하게, 서브버전 저장소의 이력을 가져올 수 있다.

git svn clone은 서브버전 저장소의 전체 이력을 가져와서 자신의 Git 저장소에 저장한다.

 

맥에서 CPAN 사용에 주의할 사항.

필자는 MacPorts에서는 필요한 것이 모두 설치됐다고 알려주는데도 Git에서는 왜 인식하지 못하는지 이유를 알아내려고 이틀을 허비했다.
원인은 시스템에 펄 서브버전 바인딩이 2가지 버전으로 설치돼 있었기 때문이다
.
오래된 버전은 처음 컴퓨터에 서브버전을 설정하면서 함께 설치되었고, 새로운 버전은 MacPorts를 이용해 설치됐다
.
상황이 나빠지려고 그랬는지 문제를 파악하지도 못한 상태에서 CPAN을 통해서 하나를 더 설치해버렸다. 그래서 총 3가지 버전의 펄 서브버전 바인딩이 설치되었다
.
CPAN
을 통해 설치한 버전은 잘 동작했지만, Git에서 이용하려고 하면 의존성 오류가 발생했다. CPAN 라이브러리가 필요한 모든 라이브러리를 설치하지 않는다는 사실을 안 후에는 쉽게 해결할 수 있었지만, 결국 이 문제를 해결하는 데 몇 시간 이상을 소비했다.

 

서브버전 저장소를 복제할 때는 Git에 서브버전 저장소의 구조를 알려줘야 한다.
저장소가 서브버전 저장소의 레이아웃으로 권장되는 구조를 따르고 있다면, -s 매개변수를 지정해서 표준 레이아웃을 이용하고 있다고 Git에게 알려준다.

 

branches tag 디렉터리가 다른 위치에 있다면, -b옵션과 -t옵션을 이용해서 위치를 지정할 수 있다. 마찬가지로 트렁크가 trunk말고 다른 이름을 이용하고 있다면 -T옵션으로 위치를 지정할 수 있다.

$ git svn clone prefix svn/ -s svn://svnrepo/sunshine

 

저장소 크기 줄이기

100여개 이상의 커밋 이력을 포함하는 서브버전 저장소를 복제하면, 디스크 공간이 현저히 줄어드는 것을 볼 수 있다.

저장소에 수백 건을 커밋할 때와 마찬가지로, 새로 받은 서브버전 복제본에도 가능하면 빨리 git gc를 실행하여 디스크 공간을 절약하자.

저장소를 복제하고 다른 동작 없이 바로 git gc를 실행할 때는 안심하고 --aggressive 옵션을 지정해도 된다. 물론 옵션을 지정하면 시간이 걸리기는 한다. 개인적으로는 31,000개 이상의 커밋을 가진 복제된 저장소를 압축하는데 14시간 이상 소요되는 경우도 봤다.

 

서브버전은 전체 이력 가져오기와 같은 요청을 처리하지 못한다.
따라서, git-svn은 한 번에 하나의 리비전만 가져온다
.
때문에 저장소가 수만 개의 이력을 포함할 정도로 크다면, 가져오는데 거의 하루 종일 걸릴 수도 있다.

앞에서는 git svn clone 명령어에 --prefix 매개변수를 포함시켰다.
--prefix
매개변수는 서브버전에서 가져온 모든 브랜치에 접두어를 추가한다
.
이를 테면, 원격 브랜치의 이름 앞에 원격 저장소임을 나타내는 이름을 붙일 수 있다
.
매개변수를 지정하지 않으면, 이름으로는 원격 브랜치와 지역 브랜치를 구별하기 어렵다
.
--prefix
매개변수를 지정하지 않으면, git branch
a를 통해 지역 저장소와 원격 저장소를 모두 볼 때 알아보기 어려워진다.

오래된 커밋이 별로 중요하지 않다면, -r옵션을 이용해서 복제를 시작할 리비전을 지정할 수 있다. 리비전을 지정하면, 지정한 리비전의 이력만 복제하므로 이후의 변경 사항을 가져오려면 다른 명령어를 더 실행해야 한다.
프로젝트를 초기에 가져온 다음
상위서브버전 저장소에서 변경 사항을 가져올 때는 git svn rebase 명령어를 이용한다.

 

 

 

1.4.        서브버전 저장소를 최신 상태로 유지하기

현재 사용 중인 서브버전 저장소를 이용하든지, git svn clone r 을 이용해서,
초기에 한 번 최신 사항을 가져와야 한다면
,
서브버전 저장소의 변경 사항을 가져오는 2가지 방법이 있다.

첫 번째 방법은 git svn fetch이다.
이 명령어를 이용하면, 모든 원격 변경 사항을 원격 브랜치에 풀링 하지만, 로컬 브랜치와 합치지는 않는다. 이 명령어는 서브버전에 추가된 새로운 브랜치를 가져올 때도 사용한다.

둘째는 git svn rebase를 이용한 방법이며, 더 많이 사용된다.
이 명령어는 git svn fetch를 실행한 다음에 바로 git rebase를 실행하는 것과 동일하다
.
명령어를 실행하면 상위 서브버전 저장소에서 모든 커밋을 가져오고 원격 브랜치에 맞춰서 현재 브랜치를 재정렬한다.

git rebase를 이용할 때와 마찬가지로, 이미 서브버전에 적용한 지역 커밋이 있다면 재정렬할 때 다시 적용하지 않으며, 작업 트리에 커밋 하지 않은 변경 사항이 있다면 git svn rebase를 실행할 수 없다.

 

이 오류는 무슨 의미지?

복제하려는 프로젝트가 서브버전 저장소의 가장 오래된 리비전에 없다면, 다음과 같은 에러가 발생한다.

W: Ignoring error from SVN, path probably does not exist: (175002): RA layer request failed:

(경고: SVN에서 발생한 오류를 무시했음. 요청한 경로가 존재하지 않는 것으로 보임: )

REPORT request failed on /test/!svn/bc/100:

REPORT of /test/!svn/bc/100:Could not read chunk size: Secure connection truncated (svn://svnrepo)

W: Do not be alarmed at the above message

git-svn is just searching aggressively for old history.

(경고: 겁먹지 말 것. git-svn이 오래된 이력을 계속 찾기 때문에 나오는 메시지다)

 

두번째 경고 메시지에서 알 수 있듯이 걱정할 필요가 없다. git-svn은 서브버전 저장소를 복제할 때 접근할 수 있는 가장 오래된 리비전부터 요청한 코드를 포함하는 리비전을 찾을 때가지 최신 리비전 방향으로 이동한다.

경고 메시지는 단지 가장 오래된 리비전에서 요청한 코드를 찾을 수 없을 때 발생한다.
이후 복제하기로 한 프로젝트가 처음 존재하는 리비전을 찾을 때까지 계속해서 이력을 조사한다.

 

서브버전 저장소 복제하기의 대안

서브버전 저장소를 복제하는 일은 시간이 많이 걸린다.
필자는 복제하는 데에 20시간 이상 소요된 큰 저장소를 복제한 적이 있다
.
기존의 저장소가 크다면 복제를 시작하기 전에 먼저 부트스트랩(bootstrap) 저장소를 찾아보자.

부트스트랩 저장소는 추적하려는 서브버전 저장소를 복제한 Git 저장소를 tar 파일로 묶어둔 형태다. 오픈 소스 커뮤니티에서는 부트스트랩 저장소를 보통 매주 업데이트한다.

부트스트랩 저장소를 이용하면, git svn rebase를 실행해서 부트스트랩 저장소 이후의 변경 사항만 가져오면 된다. 전체 이력을 복사하는 것보다 훨씬 빠르다.

 

 

 

1.5.        변경 사항을 SVN에 푸싱하기

다른 유명한 분산 버전 관리 시스템과 비교해서, Git이 가지는 장점은,
서브버전 저장소에서 풀링 해 올 수 있을 뿐만 아니라
,
변경한 내용을 다시 푸싱할 수도 있다는 점이다.

변경 사항을 다시 서브버전 저장소로 푸싱하는 명령어는 git svn dcommit이다.
이 명령어를 이용하면, 자신의 컴퓨터에서 커밋한 내용을 서브버전 저장소에 하나씩 커밋한다.

커밋하는 동안 지역 커밋이 서브버전 서버에서 가져온 정보를 반영하도록 복사본을 재정렬한다.
git svn rebase
와 마찬가지로 git-svn이 이미 동기화된 이력을 파악하기 쉽게 해준다.

-n 옵션을 지정하면 가상 수행(dry run)을 수행할 수도 있는데, 이를 통해 모든 이력과 서브버전 저장소에 보낼 수 있는 커밋 목록을 확인할 수 있다.

 

 

 

1.6.        CVS에서 가져오기

CVS 저장소를 Git으로 변환하는 가장 확실한 방법은,
cvs2svn
명령어를 이용해서 CVS 저장소를 먼저 서브버전 저장소로 변환하는 것이다
.
cvs2svn
CVS 저장소를 서브버전 저장소로 변환하는 도구이다. (http://cvs2svn.tigris.org)

Git에는CVS 저장소를 가져오기 위한 git cvsimport 도구도 있지만, cvs2svn 명령어를 이용하는 편이 더 안정적이기에 cvs2svn의 사용법만 다룬다.

 

변환을 시작하려면 CVS 저장소에서 리비전 제어 시스템(Revision control System, RCS)파일을 가져와야 한다.
이 파일들을 가져온 다음 cvs2svn 도구를 이용해 svn 덤프 파일로 변환한다.

$ cd /path/to/cvs-rcs-files

$ cvs2svn dumpfile=svndump

 

도구를 이용해 덤프 파일을 생성하면, svndumpfilter와 같은 불필요한 데이터를 필터링 해준다.
새로운 svndump가 준비됐다면, 이 정보를 가져와서 서브버전 저장소를 생성한다
.
svnadmin create
명령어를 이용해서 새로운 저장소를 생성한다.

$ cd ..

$ svnadmin create ./tmpsvn

$ svnadmin load ./tmpsvn < /path/to/cvs-rcs-files/svndump

 

tmpsvn 저장소로 전체 이력을 불러오는데 성공했다면, 이제 Git 저장소로 가져올 준비가 됐다. tmpsvn 저장소의 내용을 Git 저장소로 옮기는 절차는 10.1 SVN과 통신하기에서 다룬 내용과 동일하다.

$ git svn clone file:///path/to/tmpsvn

 

출처 : http://youmin3.egloos.com/1990844

1.         기본을 넘어서

Git은 풍부한 도구 모음을 가지고 있다. 지금까지는 매일 사용하는 Git의 기본 기능만 다루었다.
Git
은 현재 140개가 넘는 명령어를 가지고 있으며, 아마도 이 중에서 상당수는 앞으로도 전혀 사용할 일이 없을 것이다
.
예를 들어, Git 내부적으로 문자열이 유효한 브랜치나 태그명인지 판단하려고 사용하는 git check-ref-format과 같은 명령어는, Git의 확장을 만드는 경우가 아니라면 사용할 일이 없다.

 

하지만, 매일 사용하는 명령어는 아니겠지만, 필요할 때 사용하면 정말로 유용한 명령어도 있다.
*
저장소 이력 압축하기

l       저장소 내보내기

l       브랜치 이력 재정렬하기

l       reflog를 이용해서 저장소 고치기

l       저장소를 양분하여 어떤 변경이 버그를 발생시켰는지 찾기

 

$ git clong git://github.com/tswicegood/mysite-chp8.git

Initialized empty Git repository in /work/mysite-chp8/.git/

remote: Counting objects: 56, done.

 

 

 

1.1.        저장소 이력 최적화 하기

일상 생활에서 주변을 좋은 상태로 유지하려면 약간의 관리가 필요하다.
자동차 오일도 교환해주어야 하고, 바닥 청소도 해야 한다
.
마찬가지로 Git에서는 git gc run을 실행해야 한다.

 

Git은 모든 것을 저장한다.
모든 것을 저장하기에 불필요한 찌꺼기 데이터를 포함하기도 한다
.
예를 들어, git commit --amend 매개변수를 지정해서 커밋을 수정해도, Git은 수정되기 이전 리비전을 기억하고 있다
.
또 다른 예로, git branch
D로 실험용 브랜치를 지워서 해당 브랜치에 대한 연결고리가 없는데도, Git은 브랜치에 어떤 내용이 들어 있었는지 알고 있다.

이런 경우에 git gc를 이용한다.
100
번 커밋한 후나 한 달에 한 번 정도 git gc를 실행하도록 주기를 정해놓으면
,
Git
이 내부적으로 이력을 저장하는 방식을 최적화하므로 지저분한 내용을 깔끔하게 정리할 수 있다
.
이때 git gc를 실행한다고 해서 이력이 변경되지는 않는다. 단지 이력을 저장하는 방식만 바꾼다.

 

저장소에 따라서 git gc를 실행해서 변경되는 정도에도 차이가 있다.
일단 git gc를 실행하면, 앞으로 최적화가 필요할 정도로 변경하기 전까지, 다시 실행하지 않아도 된다.

그럼 출력 결과를 보고 무엇이 최적화 됐는지 알 수 있을까? 디스크 공간이다.
Git
은 속도와 효율 모두를 취하려고 한다. 최적화 일부는 나중에 속도가 문제되지 않을 때 실행할 수 있도록 남겨둔다.

git gcaggressive 매개변수를 지정하면, 한층 더 깊이 최적화한다.

 

Git은 변경 사항을 델타(delta, 델타는 두 비교 대상간의 차이를 나타내는 단위이다) 단위로 저장한다. git gc를 실행하면 이렇게 저장된 델타를 압축하지만 다시 계산하지는 않는다.
최적화를 수행할 때 --aggressive를 추가하면 이런 변경 사항 델타를 처음부터 다시 계산한다.

 

 

 

1.2.        저장소 내보내기

성공적인 프로젝트라면 만든 소프트웨어를 릴리스해야 한다.
작성한 소프트웨어를 파이선, 루비, php같이 유행하는 스크립트 언어로 작성했다면 최종 사용자가 실행할 수 있도록 소스도 함께 포함시켜야 한다.

소스를 직접 받아서 쓸 수 있도록, 공용 Git 저장소의 접근 권한을 줘도 되겠지만,
프로젝트의 스냅샷에 해당하는 공식
릴리스를 만들어서 제공하면
,
사용자가 소프트웨어를 설정하고 실행할 때 알아야 할 내용을 줄일 수 있다.

 

Git은 스냅샷을 찍을 수 있는 편리한 도구로 git archive를 제공한다.
git archive
는 지정한 저장소의 위치에 해당하는 코드의 복사본을 생성해서 tar zip 형식으로 내보낸다.

git archive에는 매개변수 몇 개를 지정해야 한다.
먼저, --format=(파일형식)을 지정해서 어떤 포맷으로 내보낼지 지정해야 한다
.
tar, zip
이 유요한 값이며 반드시 지정해야 한다.

다음은, 압축 파일을 생성하려는 저장소 이력의 위치이며, 반드시 지정해야 한다. 커밋명 브랜치, 태그를 지정할 수 있다.

이외에 유용한 매개변수로 --prefix가 있는데, 내보낼 파일들의 이름 앞에, 원하는 이름을 추가할 수 있다.  --prefix에 디렉터리를 지정하면 내보낼 릴리스를 특정 디렉터리 아래 둘 수 있다.

$ git archive --format=zip \

             --prefix=mysite-release/ \

             HEAD > mysite-release.zip

첫째 줄은 앞에서 얘기한 --format 매개변수를 지정했다.
둘째 줄은 --prefix매개변수다. mysite-release/ 이름에서 볼 수 있듯이 마지막에 슬래시 문자를 넣어서 디렉터리를 나타낸다. 슬래시 문자를 넣지 않고 git archive를 실행하면 파일을 디렉터리에 넣는 대신에 모든 파일명 앞에 해당 문자열을 추가한다.

마지막 줄은 2가지를 나타낸다. 먼저, HEAD에서 압축 파일을 생성하도록 지정했다.
그 다음, > 부호를 사용해서 git archive의 출력을 mysite-release.zip으로 내보내도록 지정했다.

tar 파일을 만드는 명령어도 유사하다. 다만, git archive 출력을 직접 파일로 내보내는 대신에 추가적인 명령어를 지정해야 한다. mysite-release.tar.gz 파일을 만드는 명령은 다음과 같다.

$ git archive --format=tar \

             --prefix=mysite-release/ \

             HEAD | gzip > mysite-release.tar.gz

HEAD 다음에 파이프(|)를 사용해서, 내용을 gzip 명령어로 전달했음을 알 수 있다.
gzip
명령어에서 mysite-release.tar.gz 파일을 생성한다
.
gzip
대신 bzip2로 바꾸면 bzip2를 이용해 압축할 수 있다.

 

tar, zip 파일 형태로 저장소를 내보내면, 저장소의 스냅샷을 편리하게 배포할 수 있다.
저장소의 전체 이력을 알 필요가 없는 사람이나, 특정 지점만 알고 싶어하는 사람에게 유용하다.

 

 

 

1.3.        브랜치 재정렬하기

브랜치를 이용하는 것이 작업을 조직화하는데 훌륭한 방법이지만,
브랜치 간에 모든 것을 동기화하는 작업은 브랜치의 약점이다
.
물론 Git에서 제공하는 합치기 추적을 이용하면 동기화할 때 드는 비용을 급격히 줄일 수 있지만, 여기에서는 합치기 추적이 아닌 다른 방법을 알아본다.

 

예를 들어, 8.2 릴리스 브랜치 다루기에서 RB_1.0.1에 코드를 추가했다.
그래서 1.0.1 태그에는 master 브랜치가 모르는 새로운 코드가 들어있다
.
RB_1.0.1
의 변경 사항을 master의 이력에 합치도록 RB_1.0.1 태그를 이용해서 master를 재정렬할 수 있다. 이렇게 하면 master가 처음부터 해당 변경 사항을 가지고 있던 것처럼 된다.

 

git rebasei 매개변수 없이 사용하면, 다른 브랜치의 변경 사항을 현재 브랜치의 이력에 재정렬하거나 고쳐 쓸 수 있다.
다른 브랜치의 변경 사항이 현재 브랜치에 원래부터 있던 것처럼 이력을 생성하는 방식으로 볼 수 있다.

 

git rebase에 재정렬에 이용할 태그를 지정하고 실행한다.

$ git rebase 1.0.1

 

실행하면 바로 오류가 발생한다.

5.4 충돌 다루기에서 충돌에 대처하는 방법을 다뤘다.
git mergetool
을 이용하는 것이 가장 무난한 방법이겠지만 이번에는 직접 수정하는 편이 더 쉽다.

사용자가 직접 합치는 편이 좋은 이유는 2중에서 선택해야 하는 상황이 아니기 때문이다.
1.0.1
에서 가져온 새로운 문단과 1.0 태그를 생성한 이후에 추가했던 순서 없는 목록 모두 필요하다.

따라서 파일을 직접 합치는 편이 가장 쉽다.

<<<<<<< HEAD:index.html

<p>

  Fixed

</p>

=======

<ul>

  <li><a href=bio.html>Biography</a></li>

</uul>

>>>>>>> add in a bio link:index.html

 

그냥 보통 파일처럼 보이도록 충돌 영역을 표시하는 3줄을 제거한다.
파일을 저장하고 다음 명령어를 실행하면, Git에 충돌이 해결됐음을 알리고 계속해서 재정렬을 수행하도록 한다.

$ git add index.html

$ git rebase continue

Applying: add in a bio link

 

다른 상황으로는 충돌이 있다.
절차는 거의 동일하다
.
이전과 같이 충돌을 수정하고, git add git rebase --continue를 호출한다.

물론 git rebase를 호출할 때, --skip을 지정해서 특정 커밋만 건너뛰거나 abort를 지정해서 재정렬하는 과정을 취소할 수 있다.

--onto 매개변수를 지정하면 이력을 또 다른 방식으로 고쳐 쓸 수 있다.
예를 들어 3개의 브랜치가 있다고 하자
.
master
브랜치와 master브랜치로부터 생성된 contact 브랜치, 그리고 contact 브랜치에서 생성된 search 브랜치다
.
3 브랜치에서 작업했던 내용은 다음과 같다. 연락처 작업 때문에 contact 브랜치의 코드를 이용했지만 도중에 검색 관련 코드를 추가하기로 결정했다
.
새로운 검색 코드를 끝마치고서 난 다음에야 contact 브랜치의 모든 변경 사항이 검색 관련 작업에 필요하지 않다는 사실을 깨달았다.

이런 경우에 --onto 매개변수를 이용한다.

--onto에는 재정렬 대상이 되는 하나의 브랜치를 지정한다.
search
master 브랜치로 재정렬하려는 명령어는 다음과 같다.

$ git rebase onto master contact search

search 브랜치를 contact 브랜치에서 떼어내서 master 브랜치로 옮긴다.

search 브랜치를 master 브랜치로 합치려고 하지만, contact 브랜치의 내용이 필요하지 않은 경우에 유용하다.
물론, 재정렬을 시작해서 변경 사항을 반영할 때 합쳐지면서 충돌이 발생하지 않으려면, search 브랜치의 내용은 완전히 독립적이어야 한다.

 

6.2 리비전 범위 지정하기에서 알아봤던 방식을 이용해서 --onto와 커밋 범위를 조합하면 다른 일도 할 수 있다.
예를 들어, git rebase를 이용해서 리비전을 지울 수 있다
.
2
단계 이전 커밋(HEAD^)을 지우는 명령어는 다음과 같다.

$ git rebase --onto HEAD^^ HEAD^ HEAD

이 명령어는 현재 HEAD로부터 2단계 이전 커밋에 현재 HEAD를 재정렬해서 HEAD^를 지운다.

 

물론 브랜치의 이력을 고쳐 쓰려면, 먼저 무언가 잘못됐을 때 어떻게 돌아올지에 대한 백업 계획을 준비해두는 게 좋다. 사용하고 있는 브랜치에 바로 반영하지 않고 실험용 브랜치를 만들 수도 있다.

Git에서는 브랜치를 생성하는 비용이 저렴하기 때문에 재정렬을 연습할 때는 사용하고 있는 브랜치 대신 연습용 브랜치를 만드는 것도 좋은 생각이다.

 

 

 

1.4.        Reflog 이용하기

리누스 토발스가 Git를 만들면서 정해둔 원칙 중 하나는 안전하다는 것이다.
비 파괴적이라는 말은 저장소의 어떤 시점으로도 다시 돌아갈 수 있어야 함을 의미한다
.
그러기 위해서는 상태에 따른 변경을 추적할 수 있는 기법이 필요하다.

 

Git을 이용하면 대부분의 버전 관리 시스템에서는 할 수 없는 일도 가능하다.
오래된 커밋을 변경하고, 커밋 하나를 여러 개로 쪼개고, 커밋을 제거하고, 중간에 커밋을 추가하는 동작은 Git에서는 가능하지만, 서브버전이나 CVS 같은 버전 관리 시스템에서는 불가능하다.

물론 이런 기능에는 위험이 따른다. git branch D를 이용해서 실수로 브랜치를 지웠거나 git rebase i를 잘못 조작했다면 어떻게 해야 할까?
이럴 때 reflog를 이용한다.

 

reflog는 브랜치가 변경될 때마다 계속해서 추적한다.
5
브랜치 이해하고 활용하기의 내용을 보면 브랜치는 단지 최신 커밋을 가리키고 있을 뿐이었다. reflog는 모든 변경을 추적한다. reflog를 이용하면 삭제한 브랜치를 복원할 때 체크아웃 해야 할 커밋을 찾을 수 있다.

 

예제로 확인할 수 있도록 간단한 저장소를 만든 다음 망쳐버리자.
저장소를 만들어 하나만 커밋하고, 그 다음 브랜치를 만들어 2개의 커밋을 추가한다
.
제대로 된 위치에 커밋하기만 하면 되니 아무 내용이나 넣어서 커밋하자.

이제 git rebase git rebase i를 이용해서 두번째 브랜치의 첫번째 커밋을 삭제한다.

 

git log를 이용해서 저장소의 이력이 어떻게 되었는지 확인해 볼 수 있다.

당연히 git rebase i가 커밋 하나를 지우고 나면 이력에는 2개의 커밋만 있다.

이제 reflog를 실행해보면 사실 더 많은 커밋이 있음을 확인할 수 있다.

$ git reflog

1b41334HEAD@{0}: commit: third commit

5e685deHEAD@{1}: checkout: moving from reflog to 5e685de

0cb04adHEAD@{2}: commit: third commit

71bc515HEAD@{3}: commit: second commit

5e685deHEAD@{4}: checkout: moving from master to reflog

 

git log의 출력 결과와 마찬가지로 최신 커밋이 가장 먼저 나타나며,
출력 결과에는
third commit이라는 메시지를 가진 커밋이 2개가 있다
.
0cb04ad
이 먼저 한 커밋이고, 1b41334 git rebase 71bc515를 지운 다음에 한 2번째 커밋이다.

따라서 먼저 했던 third commit을 복구하려면 단지 해당 커밋을 체크아웃 받으면 된다.

$ git checkout 0cb04ad

note: moving to 0cb04adwhich isnt a local branch

if you want to create a new branch from this checkout, you may do so (now or later) by using b with the checkout command again. Example: git checkout b <new_branch_name>

HEAD is now at 0cb04adthird commit

 

출력 메시지를 보면 알 수 있듯이 지금은 실제 브랜치 위에 있지 않다.
브랜치가 아니라고 해서 이력을 보지 못하는 건 아니지만
,
간단히 git checkout
b 를 실행하면 브랜치를 생성할 수 있다
.
이제 git log를 실행해보면 2번째 커밋이 복구되어 있다.

$ git log pretty=format:%h %s

0cb04ad third commit

71bc515 second commit

5e685de initial commit

 

당연한 얘기지만 브랜치를 생성하려고 체크아웃 받을 필요는 없다.
브랜치를 생성하기 전에 이력을 확인해야 하는 게 아니라면
,
그냥 간단히 git branch를 이용해서 브랜치를 바로 생성할 수 있다.

$ git branch reflog-restored 0cb04ad

$ git checkout reflog-restored

Switched to branch reflog-restored

 

git gc는 오래된 reflog 항목을 더 이상 유효하지 않게 만들 수 있다.
예를 들어, 방금 복구한 커밋은 보통 사흘 후에는 삭제되며, gc.reflogExpireUnreachable 설정을 바꾸면 변경이 가능하다
.
마찬가지로 보통의 reflog 항목들도 gc.reflogExpire를 변경하지 않으면 9일 후에는 유효하지 않게 된다 reflog가 너무 커지지 않도록 하기 위해서이다.

 

 

 

1.5.        저장소 양분하기

사람은 완벽하지 않기 때문에 이따금씩 발생하는 버그에 대비해야 한다.
단위테스트와 같은 도구는 버그의 위치를 찾을 수 있도록 돕는다
.
단위 테스트를 통해서도 버그의 위치를 찾지 못했다면, 저장소를 활용해서 버그가 발생한 시점을 찾아볼 수 있다
.
git bisect
는 버그가 나타난 시점을 찾을 때 이용하는 도구다.

 

git bisect는 이미 알고 있는 안전하지 않은 커밋과 안전한 커밋을 기반으로 한단계씩 옮겨가는 방식으로 동작한다. 버그를 야기한 커밋을 고립시킬 때까지 안전(good)과 안전하지 않음(bad)으로 표시하면서 이력을 따라간다.

먼저 버그를 확인하는 테스트 케이스를 만든다.
안전하지 않다고 확인된 커밋에서 테스트 케이스가 실패하는지 확인한다
.
그리고 안전하다고 확인된 커밋에서 테스트 케이스가 통과하는지도 확인한다.

 

 

안전한 커밋

 

 

 

안전하지 않은 커밋

 

 

v

?

?

?

X

 

 

이제 저장소의 위치를 안전하지 않은 커밋으로 돌려두고 git bisect start를 호출해서 저장소를 쪼개는 과정을 시작하자. 그 다음 git bisect bad를 실행하고, 마지막으로 git bisect good <커밋이나 태그>를 실행한다.
전체 과정은 다음과 같다.

$ git bisect start

$ git bisect bad

$ git bisect good 1.0

 

안전하지 않은 지점과 안전한 지점을 표시하면 git bisect는 사용자의 현재 위치를 저장소의 다른 위치로 변경한다.
2
지점 사이의 커밋을 취한 다음 이를 절반으로 쪼갠다. 그리고 나서 중간지점을 체크아웃 받는다. 이제 저장소는 다음과 같다.

 

git bisect는 중간 지점에서 시작한다.

 

 

안전한 커밋

 

양분화 시작 지점

 

안전하지 않은 커밋

 

 

v

?

?

?

X

 

 

이제 테스트를 다시 실행해서 이 커밋이 안전한지 아닌지를 확인해보자. 이번에는 커밋이 안전하지 않은 것으로 확인됐으니 해당 커밋을 git bisect bad로 안전하지 않다고 표시한다.

git bisect bad

 

이제 안전하지 않은 커밋과 안전한 커밋 사이에는 하나의 커밋만 남아있다.
논리적으로 생각해보면 이전 커밋은 안전하고 이 지점 이후의 커밋은 모두 안전하지 않으니, 이 지점이 안전하다면 다음 커밋이 버그의 원인이고, 이 지점이 안전하지 않다면 이 커밋이 버그의 원인이다
.
단위테스트를 해보자. 여기서는 이 커밋에서 버그가 발생했다고 여기자.

이 커밋도 안전하지 않다고 표시하면 Git은 버그를 발생시킨 커밋을 찾았음을 알아채고 이에 대한 로그를 보여준다. 지금까지 이력의 범위를 좁혀서 안전하지 않은 커밋을 파악했다.
이제 남은 일은 커밋에서 정확히 어떤 변경이 문제를 야기했는지 파악하고 문제를 고치는 일이다.

git bisect는 각 커밋을 확인하는 과정에서 사용자의 브랜치를 변경한다.
따라서 변경을 반영하기 전에 다시 이전에 작업하던 브랜치로 돌아가야 한다
.
git bisect reset
을 실행하면 된다.

$ git bisect reset

Switched to branch master

 

Git의 다른 명령어들과 마찬가지로 git bisect는 이렇게 단순한 형태보다 더 많은 것을 지원한다. git bisect visualize를 이용하면 변경 이력을 시각적으로 보여주므로 이해하기가 쉽다.

git bisect log를 이용하면 텍스트 형태로 어떤 커밋이 안전하다고 표시됐고, 어떤 커밋이 안전하지 않다고 표시됐는지를 볼 수 있다. 이 명령어는 잘못 표시한 커밋을 나중에 찾을 때도 유용하다.

 

잘못 표시한 커밋을 다시 제대로 표시하려면 git bisect log의 출력을 파일로 저장하고, 파일에서 실수한 시점 이후의 모든 내용을 제거하고 저장한다. 그러고 나서 저장한 파일을 git bisect replay <파일> 명령어의 매개변수로 지정하면 파일에 기록된 지점까지만 수행한다.

 

git bisect를 이용해서 버그가 발생된 커밋을 찾아가는 작업이 정말 좋기는 하지만, 수많은 작업을 일일이 손으로 해야 한다. 해야 할 일의 양도 양이지만, 사람이 하는 일이므로 오류가 발생할 수도 있다. 자동화된 테스트 스위트(test suite)가 있다면 수작업이 어느 정도는 줄겠지만, git bisect가 테스트 스위트를 알아서 실행하도록 만들면 수작업을 더 줄일 수 있다.

이렇게 하려면 커맨드 라인에서 실행할 수 있는 스크립트가 필요하다.
작성한 스크립트는 테스트가 통과하면 종료코드가 0으로 끝나고, 실패하면 종료코드가 0보다 큰 수로 끝나야 한다. 대개 실패하면 종료코드로 1을 사용한다.

이때, 125를 종료코드로 사용하면 현재 커밋에 표시하지 않고 다음 커밋으로 건너뛰므로 이런 용도가 아니라면 125를 사용하면 안 된다.
안전한지 아닌지를 테스트 할 수 없는 경우가 아니라면 보통은 커밋을 건너뛰려고 하지는 않을 것이다.

 

git bisect run을 실행하면 자동적으로 작성한 스크립트를 실행한다.
예를 들어, run-tests라는 스크립트를 만들었다면 다음과 같이 실행할 수 있다.

$ git bisect start HEAD 1.0

$ git bisect run /work/run-tests

running /work/run-tests

 

/work/run-tests라는 스크립트의 종료 코드를 이용한다는 차이를 제외하고는,
git bisect
는 사용자가 직접 하던 대로 계속해서 동작한다
.
스크립트에서 0이 아닌 숫자를 반환할 때마다 안전하지 않은 커밋으로 취급한다.

이 명령어에서는 저장소가 밖의 다른 디렉터리에 있는 스크립트 파일을 지정했음을 볼 수 있다. 실행할 스크립트 파일을 저장소 밖에 두면 git bisect가 실행되면서 저장소가 변경돼도 스크립트 파일이 바뀌지 않음을 보장할 수 있다. 꼭 저장소 밖의 파일을 이용해서 테스트를 진행해야 하는 것은 아니지만 불필요한 문제를 피할 수 있다.

 

출처 : http://youmin3.egloos.com/1990779

1.         저장소 조직하기

1.1.        태그를 이용하여 마일스톤 표시하기

프로젝트가 진행되면 마일스톤을 달성하게 된다.
마일스톤을 달성하면 릴리스를 배포하고, 새로운 버전을 생성하는 등의 작업을 한다
.
태그를 사용하면 마일스톤을 쉽게 표시할 수 있고, 나중에 원하는 마일스톤으로 돌아갈 수 있다.

태그는 저장소의 책갈피처럼 동작한다.
태그를 붙여두면 나중에 그 태그의 위치로 곧장 되돌아갈 수 있다
.
필요하다면 커밋에도 태그를 붙일 수도 있다.

보통 태그는 프로젝트에서 코드를 릴리스 할 때 가장 많이 사용한다.
태그를 사용하면, 릴리스 한 후에도, 버그 수정이나 변경이 필요한 경우, 릴리스 된 코드로 돌아갈 수 있다.

서브버전 사용자에게 익숙한 태그와 달리 Git의 태그는 읽기 전용이다.
읽기만 가능하다는 말은 브랜치와는 다르게 태그의 내용을 변경할 수 없음을 의미한다
.
이를 통해 태그를 붙였을 당시의 정확한 내용을 알 수 있고, 그 내용이 변경되지 않았음을 확신할 수 있다. 이는 읽기만 가능한 태그의 장점이다.

 

Git에서 태그를 붙이는 명령은 git tag이다.
현재 어떠한 태그들이 있는지 살펴보려면 git branch 처럼 매개변수를 지정하지 않고, 명령어를 실행하면 된다.

$ git tag

 

태그 1.1을 붙이는 명령

$ git tag 1.1

 

Git에서는 태그가 성공적으로 붙여졌다고 알려주지 않는다.
매개변수 없이 git tag를 실행하면, 새로 붙인 태그를 확인할 수 있다.

 

Git의 태그를 붙이는 명령어는 성공할 때와는 달리, 문제가 발생하면 바로 알려준다.
예를 들어, 태그명에 공백이 포함된 경우처럼 적합하지 않은 태그명으로 태그를 붙이려 한다면, 오류 메시지를 보여준다
.
유효한 이름에 대해서는 8.3
브랜치와 태그에 유효한 이름 사용하기참고

$ git tag version 1.1

fatal: version 1.1is not a valid tag name.

 

git tag에 태그명만 지정하고 실행하면, Git은 현재 작업 트리의 커밋에 태그를 붙인다.
원하는 커밋에 태그를 붙이려면 매개변수를 추가하면 된다
.
추가할 매개변수로 유효한 커밋명이나 브랜치명을 사용할 수 있다.

예를 들면, 다음과 같이 git tag를 실행하면, contacts 브랜치의 가장 최신 커밋에 태그를 붙일 수 있다.

$ git tag contacts/1.1 contacts

$ git tag

1.0

1.1

contacts/1.1

 

태그를 이용해서 태그를 붙여둔 저장소의 상태로 돌아갈 수 있다.
비록 태그의 내용을 변경할 수는 없지만, 브랜치처럼 체크아웃 할 수 있다.

$ git checkout 1.0

 

이 상태는 마치 주인 없는 땅에 와있는 것과 같다.
지금은 브랜치에 있지 않아서 변경사항을 추적할 수 없다
.
지역 브랜치를 보려고 git branch를 실행하면, 현재 브랜치가 아님을 알 수 있다.

$ git branch

* (no branch)

about

alternate

contacts

master

new

 

다음과 같이 git checkout b 매개변수를 지정하고, 체크아웃하면 새로운 브랜치를 생성할 수 있다.

$ git checkout b from-1.0

Switched to a new branch from-1.0

이제는 다시 변경 사항을 추적할 수 있다.
물론 Git의 다른 기능과 마찬가지로, 다른 방법으로 태그에서 브랜치를 만들 수도 있다.

 

git branch git checkout b 2번째 매개변수로 태그명을 사용하면, 새로운 브랜치를 생성한다.

$ git checkout b another-from-1.0 1.0

Switched to a new branch another-from-1.0

git log를 실행해보면 1.0 태그를 만들 때의 커밋만 있음을 확인할 수 있다.

 

버그를 수정하거나 릴리스된 코드를 약간 변경하려고 할 때,
태그에서 릴리스 브랜치를 생성하면 유용하다.

 

 

 

1.2.        릴리스 브랜치 다루기

릴리스 브랜치는 릴리스할 코드를 준비하는 장소다.
개발팀에서는 일반적으로 릴리스할 코드를 분리할 목적으로 릴리스 브랜치를 사용한다
.
분리하려는 대상이 무엇인지는 개발팀에 따라 다르다.

 

릴리스 브랜치를 생성할 시점도 개발팀과 개발 스타일에 따라 다르다.
여기서는 편의상 릴리스 브랜치의 생성 시점을 다음과 같이 정의한다
.
릴리스 브랜치는, 프로젝트에서 이번 릴리스에 포함하기로 한 기능 구현이 끝나면 생성한다
.
, 아직 완전히 검토되지 않은 상태인 브랜치이다.

 

릴리스 브랜치에서는 최소한의 변경만 발생하며,
버그나 로직의 수정에만 집중할 뿐, 새로운 기능을 추가하지 않는다.

따라서 릴리스 브랜치를 이용하면 master 브랜치에 새로운 기능을 쉽게 추가할 수 있으며,
이때, 개발팀은 master 브랜치에 추가되는 코드에 영향을 받지 않고, 릴리스 준비를 할 수 있다.

 

일반적으로 릴리스 브랜치에는 RB_ 라는 접두어를 붙이며,
그 뒤에 릴리스 번호를 붙인다
.
따라서 1.2 버전 릴리스는 RB_1.2가 되고, 1.3버전은 RB_1.3이 된다.

 

릴리스 브랜치는 해당 릴리스가 요구하는 마지막 테스트까지 통과하는 짧은 기간 동안만 존재한다.
일단 릴리스 준비가 완료되면, 해당 릴리스를 표시하는 태그를 붙이고 브랜치를 삭제한다.

 

브랜치를 삭제한다고 걱정할 필요는 없다.
다시 말하자면, 이력을 유지하려고 브랜치를 유지할 필요가 없다
.
태그가 해당 위치를 표시하고 있다
.
브랜치 목록이 난잡해지도록 브랜치를 유지할 필요는 없다.

 

릴리스된 코드에서 갑자기 발생한 어쩔 수 없는 버그 수정은 어떻게 할까?
이전 절에서 했던 방식대로, 태그에서 새로운 릴리스 브랜치를 생성하면 된다
.
RB_
접두어 형식의 브랜치명과 분기해 나올 태그명을 지정한다.

 

$ git branch RB_1.0.1 1.0

$ git checkout RB_1.0.1

Switched to branch RB_1.0.1

 

여기서는 git branch의 두번째 매개변수로 태그명을 사용했다.
git branch
는 태그가 참조하는 커밋을 기반으로 브랜치를 생성한다.

 

새로운 브랜치는, 태그를 붙였을 때의 릴리스 브랜치 상태와 같다.
이전에 태그를 붙이고 삭제했던 릴리스 브랜치와 이력도 동일하다
.
git log
로 이러한 내용을 확인해 보자.

$ git log pretty=format:%h %s

 

이제 문제를 수정하고, 수정이 완료됐다면 새로운 태그를 붙이자.

$ git tag 1.0.1

 

버그를 수정하고 새로운 태그를 붙였다면, 이전 릴리스 브랜치와 마찬가지로, 새로운 브랜치를 삭제한다.
현재 위치에서 브랜치를 삭제할 수 없으므로, master 브랜치로 다시 전환하자.

$ git checkout master

Switched to branch master

$ git branch D RB_1.0.1

Deleted branch RB_1.0.1

 

여기서는 git branch D로 브랜치를 삭제했는데, master 브랜치가 RB_1.0.1과는 연관이 없다고 취급했다.

 

릴리스 브랜치는 릴리스에 가까워질 때 개발팀의 작업흐름을 조직하는데 도움을 준다.
릴리스 브랜치를 이용하면, 버그 수정이나 고객의 급작스런 변경요청과 같이 반드시 필요한 코드만 릴리스에 반영함으로써, 새로운 기능 추가나 버그로부터 릴리스에 영향을 미치지 않도록 한다.

 

 

 

1.3.        브랜치와 태그에 유효한 이름 사용하기

Git에서 사용하는 이름 대부분은 원하는 형태로 사용할 수 있지만, 피해야 할 몇 가지가 있다.

 

먼저, 태그와 브랜치의 이름에서 슬래시(/)를 사용할 수 있지만, 슬래시로 끝날 수는 없다.
슬래시를 이용하면 태그와 브랜치를 디렉터리와 비슷한 구조로 조직할 수 있다.

 

이름에도 마침표(.)도 사용할 수 있지만, 각 경로명은 마침표로 시작할 수 없다.
예를 들어, releases/1.0은 유효한 태그명이지만, releases/.1.0이나 .releases/1.0은 유효하지 않다.

리눅스나 BSD, OS X 파일시스템과 같이, 마침표와 관련된 제약사항을 갖는다.
해당 운영체제에서는 마침표로 시작하는 파일이나 디렉터리를 숨겨진 자원으로 다룬다.

 

태그와 브랜치의 이름에는 몇 가지 특수문자를 사용할 수 없다.
사용할 수 없는 특수문자에는 공백, 물결표(~), 캐럿(^), 콜론(:), 물음표(?), 별표(*), 왼쪽 대괄호([)가 있다
.
ASCII
제어문자(
040보다 작은 문자)나 삭제 키(ASCII 177)도 허용되지 않는다.
여기서 언급한 ASCII 문자는 실수로라도 입력할 수 없으므로, ASCII 문자가 뭔지 모른다거나 어떻게 입력해야 할지 모른다고 걱정할 필요는 없다.

 

마지막으로 이름에 마침표를 두 번 연속해서 사용할 수 없다.
6.2
리비전 범위 지정하기에서 다룬 리비전의 범위를 지정하는 구문을 떠올려 보자
.
범위는 <첫 번째 커밋>..<두 번째 커밋> 구문을 사용한다
.
모호해질 수 있으므로, 태그와 브랜치 이름에서 연속된 마침표는 허용되지 않는다.

 

브랜치와 태그는 유효한 파일이나 디렉터리 형태라면 어떠한 이름도 사용할 수 있다.
브랜치와 태그를 보통의 파일 시스템을 사용하듯이, 정렬하기 쉽도록 디렉터리와 비슷한 구조로 조직할 수 있다.

 

 

 

1.4.        프로젝트 여러 개를 추적하기

회사들은 대부분 다수의 프로젝트를 진행한다.
하나의 제품도 다른 구성요소라면, 모두 분리해야 한다
.
그렇게 해야 개발팀의 구성원이 전체 코드를 뒤질 필요 없이 필요한 코드를 찾을 수 있다.

 

Git에서는 프로젝트 여러 개를 다룰 수 있는 몇 가지 방법을 제공한다.
프로젝틀 모두를 저장소 하나에 저장할 수도 있고, 프로젝트마다 개별 저장소를 가질 수도 있다. 두 가지 방식 모두 장점과 단점이 있다.

 

 

 

1.4.1.       프로젝트 여러 개를 저장소 하나에 저장하기

가장 직관적인 방법은, 저장소 하나를 생성하고 프로젝트 여러 개를 저장하는 방식이다.
저장소 안에서 각 프로젝트마다 각기 다른 최상위 디렉터리를 생성하여, 이 방식을 사용할 수 있다.

 

서브버전에서 프로젝트 여러 개를 저장소 하나에 저장할 때 이렇게 사용하므로 서브버전 사용자라면 익숙할 것이다.
이는 모든 프로젝트를 함께 저장하기에 편리한 방식이며, 저장소 하나만 복제하면 모든 프로젝트를 이용할 수 있다
.
이 방식은 함께 릴리스되는 컴포넌트가 여러 개로 구성된 프로젝트처럼, 공통된 이력이 필요한 프로젝트에 적합하다.

CMS나 주문 입력 시스템과 같이, 여러 개의 분리된 컴포넌트로 구성되어 있지만, 패키지 형태로 한 번에 릴리스되는 모든 종류의 프로그램에 공통의 이력이 필요한 프로젝트에 해당된다.

 

작은 프로젝트나 컴포넌트가 큰 프로젝트의 일부로만 릴리스된다면 이력을 함께 공유하는 게 좋은 생각이다. 저장소의 모든 이력이 큰 프로젝트 하나를 중심으로 관리된다.

작은 프로젝트나 컴포넌트가 따로 릴리스된다면, 아마도 해당 프로젝트만의 고유한 이력이 필요할 것이다.
Git
에서는 태그와 브랜치를 일부 영역에만 적용할 수 없고, 저장소 전체에 적용하므로, 프로젝트의 일부분을 별도로 릴리스해야 한다면 저장소를 분리하는 게 좋다.

 

여러 프로젝트의 릴리스 일정이 서로 다르다면, 생성해야 할 브랜치와 태그의 수가 기하급수적으로 늘어난다.
대신에 Git에서는 저장소를 생성하는 비용이 적으므로 프로젝트마다 저장소를 생성하는 일이 그리 어려운 일이 아니다.

 

 

 

1.4.2.       프로젝트 하나를 저장소 하나에 저장하기

저장소 하나에 프로젝트 여러 개를 저장하는 방식의 대안은,
프로젝트마다 저장소를 생성하는 것이다
.
이 방식은 약간의 설정이 필요하지만 프로젝트마다 고유한 이력을 갖는다.

 

 

 

1.5.        Git 하위 모듈을 사용하여 외부 저장소 추적하기

때로는 저장소 여러 개를 마치 저장소 하나에 있는 것처럼 추적해야 한다.
이런 상황에는 외부 라이브러리에 종속되거나, 자체 개발 프로젝트가 관리하기 용이하도록 프로젝트 여러 개로 나뉘어질 경우가 있다.

 

Git에서는 하위모듈(submodule)을 사용하여 외부 저장소를 추적할 수 있다.

하위모듈(submodule)을 사용하면, 두 저장소 이력을 별도로 관리하면서, 저장소 하나를 다른 저장소 안에 저장할 수 있다.
서브버전의 svn:externals와 같은 기능이다.

 

 

 

1.5.1.       새로운 하위 모듈 추가하기

하위 모듈 저장소를 둘 새로운 저장소를 생성한다.
magic
이라는 새로운 저장소를 생성한다.

$ mkdir /work/magic

$ cd /work/magic

$ git init

 

git init으로 초기화된 빈 저장소에서 연관된 하위 모듈을 보려면 git submodule을 실행한다.

$ git submodule

 

아직 하위 모듈을 정의하지 않았으므로, 아무런 결과도 표시되지 않는다.
새로운 하위 모듈 추가는 간단하다. git submodule add 명령어를 사용한다
.
git submodule add
에는 2개의 매개변수가 필요하다
.
첫번째는 외부 저장소이고, 두번째는 저장소를 저장할 경로이다.

 

ex) GitHub에 있는 저장소를 hocus 디렉토리에 저장소를 저장하자.

$ git submodule add git://github.com/tswicegood/hocus.git hocus

 

다시 git submodule을 실행하면 hocus 저장소가 표시된다.

$ git submodule

-20asdflajsldfa09sd8fa7sdfa6df8 hocus

 

Git의 하위 모듈은 원격 저장소에 있는 특정 리비전을 추적한다.
해당 리비전은 해시로 표시되며, 이어서 하위 모듈명으로 hocus가 나온다
.
해시 앞의
기호는 hocus 하위 모듈이 아직 초기화되지 않았음을 나타낸다.

 

간단하게 초기화 할 수 있다.

$ git submodule init hocus

 

git submodule init hocus를 실행하면,
.git/config
파일에 하위 모듈에 대한 정보를 추가해서, Git hocus 디렉터리에 하위 모듈을 포함하고 있음을 인식하도록 한다
.
이제 추가하고 초기화하는 작업이 모두 끝났으니, 저장소에 일어난 변화를 확인해 보자.

$ git status

 

.gitmodules는 하위 모듈에 대한 모든 정보를 저장하는 일반 텍스트 파일이다.
Git
에서는 저장소 내부에서 이 파일을 추적한다
.
이 파일을 저장소에서 관리함으로써 자신의 저장소를 다른 사람과 공유했을 때
,
저장소를 복제한 사람이 하위 모듈을 설정하는데 필요한 정보를 얻을 수 있다.

 

 

 

1.5.2.       하위 모듈과 함께 저장소 복제하기.

처음 복제한 저장소에 하위 모듈을 설정하려면, 몇 가지 절차가 필요하다.
우선 magic 저장소를 복제한다.

$ cd /work

$ git clone magic new-magic

Initialized empty Git repository in /work/new-magic/.git/

$ cd new-magic

$ ls

hocus

 

hocus 디렉터리가 존재하지만 비어 있다.
git submodule
을 실행하면, 하위 모듈이 아직 초기화되지 않았음을 알 수 있다.

$ git submodule

-20234k2lrjfljaldfjasdjflafa hocus

첫 번째 문자로 기호가 나타나면, 하위 모듈이 초기화되지 않았음을 의미한다.

 

초기화되도록 git submodule inti 명령을 실행.

$ git submodule init hocus

Submodule hocus(git://github.com/twsicegoold/hocus.git)

registered for path hocus

 

hocus 디렉토리는 아직도 비어 있는데,
하위 모듈의 변경 사항을 가져오려면 git submodule update 명령을 실행한다.

다른 git submodule 명령어와 마찬가지로 git submodule update도 현재 작업 중인 하위 모듈명을 매개변수로 지정한다.

$ git submodule update hocus

Initialized empty Git repository in /work/new-magic/hocus/.git/

remote:

remote:

remote:

Receiving objects: 100% (7/7), done.

Submodule path hocus: checked out

20234k2lrjfljaldfjasdjflafa

이제 hocus 디렉터리에 해시명이 2023인 커밋의 모든 파일이 저장되었다.

현재는 하위 모듈이 커밋 하나만 추적한다.

 

 

 

1.5.3.       하위 모듈이 추적하는 커밋 변경하기.

Git 하위 모듈은 저장소의 최신 커밋을 추적하지 않는다.
, 독립된 커밋 하나만을 추적한다
.
처음에는 하위 모듈을 추가할 당시의 마지막 커밋인 HEAD를 추적한다
.
하위 모듈이 추적하는 커밋을 변경하려면 다른 작업이 필요하다.

 

이러한 과정은 서브버전을 사용해 본 사람이라면 의아할 것이다.
서브버전은 저장소를 추적하며 갱신하면, 알아서 최신의 커밋을 가져온다
.
개별 리비전을 추적하려면 명시적으로 설정해야 한다.

언뜻 보기에 이러한 방식이 더 편리해 보이지만 문제가 발생할 수 있다.
추적하는 저장소에서 버그가 발생하거나, 자신의 원격 저장소 리비전이 다른 개발자의 버전과 다를 경우 어떻게 될까? 명시적으로 하나의 커밋만 추적하면 이런 문제는 발생하지 않는다.

 

Git에서는 하위 모듈을 생성할 때, 추적할 커밋이 결정된다.
, 저장소에서 해당 커밋만 가져온다
.
하위 모듈은 사실 특정 커밋을 체크아웃 하여 완전히 복제된 저장소다
.
hocus
디렉토리로 이동한 다음, 브랜치 목록을 보면 이것을 확인할 수 있다.

$ cd hocus/

$ git branch

* (no branch)

  master

 

이 저장소는 2개의 커밋만 가진다.
둘째 커밋 대신에 첫째 커밋으로 변경해보자

HEAD
바로 전으로 체크아웃하자.

$ git checkout HEAD^

Previous HEAD position was 20cc9ddinitial commit

HEAD is now at 7901f67initial commit with README

 

다음은 Git에게 변경된 하위 모듈을 사용한다는 사실을 알려야 한다.
매개변수를 지정하지 않고 git subodule을 실행하면 Git은 변경이 있음을 감지할 수 있다.

$ cd ..

$ git submodule

+7901f67. hocus (7901f67)

+ 기호는 Git이 예상하던 커밋이 아님을 의미한다.
git status
를 실행해 보면 hocus 디렉터리가 변경됐음을 볼 수 있다.

 

$ git status

# On branch master

# Changed but not updated:

#    (use git add <file>…“to update what will be committed)

#

#        modified: hocus

#

no changes added to commit (use git addand/or git commit a)

 

이제 hocust 디렉터리를 추가하고 변경 사항을 커밋해야 한다.
이렇게 하면 Git은 새로운 커밋을 사용하여 하위 모듈을 추적한다.

$ git add hocus

$ git commit m update commit to track in submodule

Creaated commit fedf2bc: update commit to track in submodule

1 files changed, 1 insertions(+), 1 deletions(-)

 

 

 

1.5.4.       하위 모듈을 이용하여 작업할 때의 주의 사항.

git add를 실행할 때 명령어가 슬래시(/)로 끝나서는 안 된다.
Git
은 슬래시(/)를 추가하면, 하위 모듈이 추적하는 커밋을 업데이트하는 대신
,
참조하고 있는 저장소의 모든 파일을 현재 지역 저장소에 추가하라는 요청으로 해석한다
.
커밋하기 전에 git status를 실행해 보면 혹시 실수했는지 확인할 수 있다.

 

또 다른 주의 사항으로는,
git submodule update
는 충돌을 고려하지 않고 덮어쓴다는 점이다
.
갱신 명령을 실행하면, 하위 모듈에 있는 아직 커밋되지 않은 변경 사항까지 덮어쓴다
.
git submodule update
를 실행해서 변경사항을 수정하기 전에, 바꾼 내용은 없는지 하위 모듈의 작업 트리를 다시 한번 확인하자.

 

마지막 주의사항은 하위 모듈의 저장소에 직접 새로운 내용을 추가하는 것과 관련한 사항이다.
먼저 변경하기에 앞서, 변경한 내용을 반영하려는 브랜치를 체크아웃하자
.
하위 모듈이 일반 브랜치에서 가져왔음을 기억하자
.
간단히 git checkout으로 수정한다.

그 다음은 일단 변경 사항을 커밋했다면, 변경 사항을 하위 모듈 체크아웃에 공유하기 전에 원격 저장소에 변경 사항이 존재하는지 확인해야 한다.
git submodule update
를 실행하려고 시도할 때, 하위 모듈을 참조하는 커밋이 원격 저장소에 존재하지 않는다면, Git은 예상과 다르게 동작할 것이다.

 

출처 : http://youmin3.egloos.com/1990629

1.         원격 저장소를 이용하여 작업하기

1.1.        네트워크 프로토콜

Git에서는 원격 저장소와 통신하는 데는 3종류의 프로토콜을 사용한다.

l       SSH

l       git

l       HTTP/HTTPS

 

1.1.1.       SSH

SSH(Secure Shell)로 저장소에 접근하는 방식은, 한 가지 차이점을 제외하고는 저장소의 파일 시스템에 직접 접근하는 방식과 유사하다.
원격 저장소에 대해서는 저장소 경로 앞에 도메인명을 추가하고, 필요하다면 사용자명도 추가한다.

 

git@github.com부분이 기본 파일 시스템 URL에 추가된 SSH URL의 유일한 차이점이다.
이 정보를 바탕으로 Git, SSH를 사용하여 git이라는 사용자명으로 github.com 서버에 로그인하고 tswicegood/mysite-chp6.git 경로에 위치한 저장소를 복제한다.

 

git@github.com/tswicegood/mysite-chp6.git

git

사용자명

github.com

서버

tswicegood/mysite-chp6.git

저장소 경로

 

git@ 에 해당하는 사용자명은 필수 사항이 아니다.
자신의 컴퓨터에서 사용하는 사용자명과 접속하려는 원격 서버의 사용자명이 동일한 경우 사용자명을 지정하지 않아도 된다.

서버에 로그인 하려고 하나의 사용자 계정을 팀원 간에 공유하고, 원격 서버에 대한 접근 권한은 각 사용자가 제공한 인증서를 통해서 확인하는 경우는 흔하다.

 

1.1.2.       git

Git에는 속도를 위해 설계된 전용 프로토콜이 있다.
가장 빠른 프로토콜이긴 하지만 다른 네트워크에서 사용하지 않는 9418번 포트를 사용하므로 방화벽에 차단되는 문제가 발생할 수 있다.

 

아래는 git 프로토콜을 사용하는 저장소 URL 형태를 나타낸다.
git://
은 프로토콜을 명시하며 뒤이어 서버를 의미하는 github.com과 저장소 명이 나온다.

 

git://github.com/tswicegood/mysite-chp6.git

git

프로토콜

github.com

서버

tswicegood/mysite-chp6.git

저장소 경로

 

위 예에서 저장소의 전체 경로를 지정하지는 않았다.
Git
서버를 시작할 때 저장소가 포함된 디렉터리를 지정해야 한다
.
클라이언트는 접근하려는 저장소명만 지정하면 된다.

 

암호화 기능을 제외하고 익명 접근을 사용한다는 점이 git 프로토콜과 SSH의 가장 큰 차이점이다. 저장소를 읽기 전용으로 공개할 생각이라면 익명 접근을 허용하는 게 괜찮은 생각이지만, 쓰기 권한까지 허용한다면 위험할 수 있다.
URL
git://으로 시작한다면 대부분은 읽기 전용이라고 생각하면 된다.

 

일반적으로 개발자들은 변경 사항을 가져오려고 풀링 할 때는 git 프로토콜을 활용하고, 공유하려고 푸싱할 때는 SSH를 사용한다.

 

1.1.3.       HTTP/HTTPS

HTTP 프로토콜은 일반적으로 마지막 수단으로 고려된다.
변경사항을 풀링 하는데 가장 비효율적인 방법이고, 네트워크 부하도 크긴 하지만, 거의 대부분의 방화벽에서 허용되며 설정 또한 비교적 쉽고 빠르기 때문이다.

 

만약 GitHub가 저장소에 HTTP 접근을 허용하고 github.com 서버에 있는 mysite-chp6.git 를 계속해서 사용한다면 다음과 같은 URL GitHub에 접근할 수 있다.

 

http://github.com/tswicegood/mysite-chp6.git

 

1.1.4.       네트워크 고르기

git 프로토콜, SSH, HTTP/HTTPS 중에서 어떤 네트워크를 사용할지 결정하는 데는 다양한 고려사항이 있다. 한가지만 선택한다면 어렵지 않다.

l       속도가 가장 중요한 경우 git 프로토콜을 사용한다.

l       보안에 가장 큰 가치를 둔다면 SSH가 적합한 프로토콜이다.

l       방화벽을 재설정하기 싫다면 HTTP/HTTPS가 유용한 방법이다.

 

문제는 인증인데 git 프로토콜은 익명 접근을 사용하므로 누구라도 저장소를 고칠 수 있다.
SSH
로 저장소에서 작업하려면 적합한 사용자 권한이 필요하고
,
HTTP/HTTPS
WebDAV (Web-based Distributed Authoring and Versioning, 원격 웹 서버에 있는 파일을 여러 사용자가 함께 수정하고 관리할 수 있도록 돕는 일련의 HTTP 확장) 서버가 필요하다.

 

반드시 하나의 프로토콜만 사용해야 한다는 법은 없다.
속도와 보안의 균형을 맞추려면 한 가지 이상의 프로토콜을 섞어서 사용할 수 있다.

 

개인 저장소에서 SSH git 프로토콜을 조합하여 사용할 수 있다.
서버에 쓰기를 할 때는 SSH키를 사용하여 사용자를 인증하며
,
git
프로토콜을 이용하여 익명의 읽기 권한을 허용한다
.
설정은 Gitosis라는 프로그램을 사용하면 간단하다.

 

 

 

1.2.        원격 저장소 복제하기

원격 저장소를 복제하면 저장소의 지역 복사본이 생성된다.

복제 명령을 통해 생성된 지역 복사본은, git init으로 직접 생성한 저장소처럼 동작한다.
복제한 시점까지의 저장소 이력을 얻을 수 있는 게 유일한 차이점이다.

작업하려는 저장소를 복제하려면, 항상 git clone 명령어를 사용한다.
복제하려는 저장소명만 매개변수로 지정하는 게 가장 단순한 형식이다.

 

$ git clone git://github.com/tswicegood/mysite-chp6.git

 

git clone 은 서버에서 저장된 저장소를 다운로드하고, mysite-chp6 디렉토리에 저장소의 지역 복사본을 설정한다.

 

 

 

1.3.        최신 상태 유지하기

복제한 시점까지의 저장소 이력을 가져올 수는 있지만,
복제한 이후에도 다른 개발자들은 여전히 변경 사항을 만들어내고 저장소를 갱신한다.

따라서 원격 저장소에서 갱신된 변경 사항을 가져와야 한다
git fetch
명령어를 사용하면 변경 사항을 가져올 수 있다.

변경 사항을 가져오면 지역 저장소의 원격 브랜치가 갱신된다.
git branch
를 실행하면 지역 브랜치를 확인할 수 있으며, 여기에
r 매개변수를 추가하면 원격 브랜치를 볼 수도 있다.

 

$ git branch r

origin/HEAD

origin/master

 

원격 브랜치도 일반 브랜치와 마찬가지로 체크아웃 할 수는 있지만, 변경하면 안 된다.
원격 브랜치를 변경하려면, 먼저 원격 브랜치로부터 지역 브랜치를 생성한 다음 변경할 수 있다.

git fetch를 실행하면, 지역 저장소의 원격 브랜치가 갱신된다.
이때, 지역 브랜치에 가져온 변경사항을 합치지는 않는다
.
원격 서버에서 변경 사항을 가져와서 동시에 지역 브랜치에 합치려면 git pull을 사용한다.

git pull 2개의 매개변수가 필요한데,
풀링해서 가져오려는 원격 저장소와

가져온 내용을 반영할 브랜치이며, 브랜치명에는 origin/ 접두어를 사용하지 않는다.

원격 브랜치 명의 origin/ 접두어는 지역 브랜치와 원격 브랜치를 구분하려고 사용한다.
origin
은 복제할 때 지역 저장소에 할당된 기본 원격 저장소명이다.

이제 원격 저장소로부터 변경 사항을 가져오거나(fetch) 풀링(pull)할 수 있다.

 

 

 

1.4.        변경 사항 푸싱하기

변경 사항을 푸싱한다는 말은, 변경 사항을 다른 저장소에 보냄을 의미한다.
푸싱은 자신의 커밋을 다른 저장소에 보낼 때 필요한 단계다
.
커밋을 하면 알아서 중앙 저장소에 전달되는 전통적인 버전 관리 시스템과는 다르게, 분산 버전 관리 시스템에서 추가된 단계다.

git push에 매개변수를 지정하지 않으면 실행되는 몇 가지 기본동작이 있다.
우선 origin 저장소에 푸싱한다고 생각하며, 또한 지역 저장소의 현재 브랜치를 원격의 같은 이름의 브랜치에 푸싱한다고 여긴다 (기본동작은 동일한 이름의 브랜치에 푸싱하도록 되어 있다. 브랜치를 다른 브랜치에 푸싱하도록 기본 구성을 변경할 수도 있지만, 흔한 경우가 아니므로 다루지 않는다). 이때, 원격 저장소에 같은 이름의 브랜치가 존재해야 한다.

 

$ git push

 

git push --dry-run 매개변수를 지정하면, 푸싱된 변경 사항을 확인할 수 있다.

git pull 에서처럼 푸싱하려는 저장소를 지정할 수도 있는데, git pull과 동일하게 git push <저장소> <참조> 형식을 사용한다.
<
저장소>에는 모든 유효한 저장소를 지정할 수 있다. 7.1
네트워크 프로토콜 URL이라면 잘 동작한다
.
또한 7.5
새로운 원격 저장소 추가하기에서 다루는 저장소의 별칭을 이용해도 잘 동작한다.

 

<참조>의 가장 간단한 형태는 태그, 브랜치, HEAD와 같은 특수 키워드다.
<
참조>를 사용하여 푸싱할 브랜치와 푸싱될 위치를 지정할 수 있다
.
예를 들면, git push origin mybranch:master를 사용하여 mybranch의 변경 사항을 원격 master 브랜치에 푸싱할 수 있다.

 

1.4.1.       푸싱된 변경 사항 가져오기

흔하지는 않지만 다른 사람이 변경 사항을 자신의 개인 저장소에 푸싱하는 것을 허용해야 할 경우가 있으며, 자신이 푸싱해야 할 경우도 있다.
다양한 운영체제에서 코드를 테스트해야 할 경우, 다른 가상 머신에 있는 개인 저장소에 변경 사항을 푸싱한다
.
자신의 저장소에 푸싱된 변경사항은 작업트리에 반영되지 않는다. 이를 통해 작업 트리에 있는 아직 커밋하지 않은 변경 사항을 누군가가 덮어쓰지 못하도록 한다
.
저장소의 최신 변경 사항 전부를 작업 트리에 풀링하려면, git checkout HEAD를 실행한다. 이때 발생한 충돌은 5.4
충돌 다루기의 방법으로 처리할 수 있다.

 

 

 

1.5.        새로운 원격 저장소 추가하기

읽기나 쓰기 권한이 있다면 어떠한 저장소에도 푸싱하거나 풀링 할 수 있다.
동기화할 때마다 저장소명 전체를 매번 입력하는 것은 귀찮다
.
특히 동일한 저장소와 계속해서 동기화한다면 정말 귀찮은 일이다.

 

기본 원격 저장소는 origin이라고 하며, 복제한 저장소의 전체 이름에 대한 별칭이다.
팀에 Erin이라는 개발자가 속해 있고, 그녀의 저장소로부터 빈번하게 변경사항을 풀링하고 있다고 하자
.
Erin
의 저장소에서 한 번만 풀링 한다면 git pull에 그녀의 저장소를 지정하여, 다음과 같이 실행할 수 있다.

$ git pull git://ourcompany.com/dev-erin.git

 

한 번이라면 괜찮지만, 여러 번 풀링 한다면 키보드 입력을 줄일 수 있도록, 별칭을 추가하는 게 나은 선택이다.
원격 저장소에 새로운 별칭을 추가하려면, git remote add <이름> <저장소 URL>을 사용한다
.
다음 명령은 Erin의 저장소에 별칭을 지정한다.

$ git remote add erin git://ourcompany.com/dev-erin.git

 

이제 변경 사항을 푸싱하거나 풀링 할 때 전체 저장소명 대신에, 별칭인 erin을 사용하면 된다. 별칭을 이용해서 이전과 동일한 풀링을 다음과 같이 할 수 있다.

$ git pull erin HEAD

 

별칭은 사용자가 원하는 어떠한 형태의 이름도 지정할 수 있어나, 반드시 고유한 이름을 지정해야 한다. erin이나 origin은 오직 한 개만 사용할 수 있다.

origin으로 지정된 저장소가 없다면, git remote add를 사용하여 저장소에 origin 별칭을 추가할 수 있다. origingit init으로 자신의 컴퓨터에서 저장소를 시작한 다음 원격 저장소로 보내야 할 때 유용하다.

git remote 명령어에는 몇 가지 유용한 기능이 더 있다.
우선 매개변수를 지정하지 않고 실행하면 추가한 모든 원격 저장소의 목록을 확인할 수 있다
.
또한, git remote show <이름>을 실행하면 지정한 원격 저장소의 정보를 볼 수 있다
.
별칭이 더 이상 필요하지 않거나, 다른 저장소의 별칭을 사용하고 싶다면 git remote rm을 실행하여 별칭을 제거할 수 있다.

 

1.5.1.       로컬 컴퓨터에서 생성된 프로젝트를 원격 저장소에 추가하기.

이미 이력이 있는 진행 중인 프로젝트라면 저장소를 복제하여 작업을 시작하는 게 좋지만, 자신의 컴퓨터에서 git init로 프로젝트를 생성했다면, 변경 사항을 어떻게 원격 저장소에 푸싱할 수 있을까?
7.5
새로운 원격 저장소 추가하기에서 알아본 git remote add 명령어로 푸싱하려는 저장소를 추가하면 된다
..
변경 사항을 푸싱하려는 저장소가 기본 저장소라면, 원격 저장소를 origin으로 별칭을 지정한다
.
예를 들어, 프로젝트를 git@example.com:/repos/pocus.git 이란 원격 저장소에 추가한다면 다음과 같이 실행할 수 있다.

$ git remote add origin git@example.com:/repos/pocus.git

$ git push origin master

Git 출력 결과

 

출처 : http://youmin3.egloos.com/1966754

1.1.        변경 취소하기

변경 사항을 커밋하고 나서 공유해서는 안 되는 비밀번호가 포함된 사실을 깨달을 수도 있다.

모든 변경사항을 중앙 저장소에 보내야 하는, 중앙 집중식 저장소를 사용하고 있다면 정말 운이 없는 경우다. 관리자 권한을 가졌다면 어떻게든 처리할 수 있겠지만 잘못하면 데이터가 깨질 수 있다.

반면 Git은 이런 종류의 실수에도 대비하고 있다. 모든 변경은 자신의 컴퓨터에서 일어나며 공용저장소에 푸싱했을 때만 공유된다. 자신만이 지역 저장소와 동기화하고 있으므로 이력을 원하는 대로 고쳐 쓸 수 있다.

 

 

 

1.1.1.       이력 고쳐 쓰기의 위험성

주의) Git을 중앙 집중식 저장소처럼 모든 커밋을 상위 저장소에 보내고 있다면, 이 절의 명령어를 실행할 때 주의해야 한다. 이미 다른 사람이 이전에 올려둔 내용을 가지고 있다면 무언가 공유한 이후에 이력을 변경하면 큰 골치거리가 되기 쉽다.

 

6.6변경 취소하기에서 다루는 git revert를 제외한, 이 절에서 배우는 모든 명령어는 저장소의 이력을 변경한다. 중앙집중식 저장소에서는 저장소의 이력을 변경하는 동작은 매우 위험하다. 그렇다면 저장소에서 커밋이 이리저리 옮겨지고, 이름을 바꾸거나 심지어는 없어져 버린 경우에는 어떻게 이력을 추적할 수 있을까?

완벽한 분산 개발의 장점 중 하나는 준비가 된 경우에만 공유한다는 점이다.
푸싱하기 전에 먼저 변경 사항을 공유할 준비가 됐는지부터 확실해 해야 한다
.
공유할 준비가 되기 전까지 모든 지역 변경 사항을 지역 저장소에 유지하면
,
저장소의 이력을 고쳐 쓸 때, 다른 사람에게 발생할 수 있는 문제를 걱정하지 않아도 된다.

 

변경 사항을 푸싱하면 이런 유연성을 어느 정도 잃게 된다. 자칫 잘못하면 팀원 모두가 변경사항 때문에 문제가 발생했다고 우리를 귀찮게 할 수도 있다.

 

일단 변경 사항을 푸싱했다면, 다시 이력을 변경해서 이전과 다른 내용을 푸싱하면, 이전 내용을 이미 받아둔 사람들에게 문제가 생길 수 있다.
변경사항 푸싱하기는 7.4 참고.

 

 

 

1.1.2.       커밋 수정하기

익숙하지 않은 새로운 언어로 코드를 작성할 때, 줄의 끝에 구두점이나 세미콜론을 빠뜨리는 상황은 흔히 겪는 일이다.

Git에서 이러한 사소한 오류를 고치는 일은 쉽다.
제대로 수정하고, 변경 사항을 스테이징한 다음, 커밋할 때 --ammend를 추가하면 된다.

 

이 기능을 확인할 수 있도록 자신의 블로그나, 자주 방문하는 사이트의 링크를 contact.html 파일에 추가하고 일부러 오타를 내보자.

$ git commit m add link to bloga

 

이제 URL을 제대로 수정하고 커밋 명령어에 --amend를 추가하고 변경사항을 다시 커밋한다.

$ git commit C HEAD a --amend

 

이번에는 아직까지 사용하지 않았던, 새로운 옵션인 C를 사용했다.
-C
옵션을 추가하면 새로운 메시지, 대신 지정한 커밋의 로그 메시지를 이용한다.

이번 경우에는 HEAD의 로그 메시지를 사용했지만, 모든 유효한 커밋명을 사용할 수 있다.

대문자 대신 소문자로 c를 사용하면 커밋을 마치기 전에, 기존의 메시지를 수정할 수 있도록 편집기를 열어준다.

커밋 수정하기는, 마지막으로 실행한 커밋에만 사용해야 한다.
실수한 이후에 여러 번 커밋했고, 이를 바로 잡고자 할 경우, 다음 절에서 알아볼 git revert를 사용한다.

 

 

 

1.1.3.       커밋 돌려놓기

때로는 어떤 이유로 다른 사람의 컴퓨터에서는 내가 작성한 코드가 동작하지 않을 수 있다.
특정 아키텍처에 종속적이거나 다른 팀원들이 사용하지 않는 외부 소프트웨어에 의존하는 경우, 다시 변경해서 커밋 하거나 커밋을 돌려놓아야 한다.

가장 간편한 방법으로 기존 커밋을 돌려놓으려면 git revert 를 이용하면 된다.
git revert
는 원본 커밋에서 변경한 모든 내용을 거꾸로 변경해서 저장소에 새로 커밋 함으로써 원본 커밋을 돌려놓는다.

보통 돌려놓는 내용을 바로 커밋하지만 n 매개변수를 추가하면 커밋하지 않는다.
이는 다수의 커밋을 돌려놓으려고 할 때 유용하다
.
그냥
n 매개변수를 지정해서 git revert 명령어를 여러 번 실행하면, Git이 모든 변경 사항을 스테이징하고 커밋하기를 기다린다.

git revert를 사용할 때는 돌려놓을 대상을 알 수 있도록 커밋명을 지정해야 한다.
예를 들어, 540ecb7 HEAD 커밋을 돌려놓고자 한다면 다음 명령어를 이용한다
.
이때, 항상 역순으로 돌려놓아야 한다. 가장 최신 커밋을 먼저 돌려놓자. 그래야만 다수의 커밋을 돌려놓을 때 처리해야 할 불필요한 충돌을 피할 수 있다.

 

$ git revert n HEAD

$ git revert n 540ecb7

$ git commit m revert 45eaf98 and 540ecb7

 

기본적으로 git revert는 커밋 메시지를 작성하도록 편집기를 실행시킨다.
실행된 편집기에는

Revert <원본 로그 메시지>(<원본 로그 메시지>를 돌려놓는다) 라는 텍스트 다음에
This reverts commit <커밋명>(<커밋명> 커밋을 돌려둔다) 가 기본 메시지로 추가되어 있다.
그냥 기본 메시지를 이용하고자 한다면 git revert--no-edit를 추가한다.

일반적으로 커밋할 때와 같이 커밋하는 이유에 대해서 잘 설명해야 한다.

 

 

 

1.1.4.       변경 사항 재설정하기

엔터키를 입력하자마자 개인 비밀번호가 들어있는 구성 파일을 커밋 했음을 깨달았다고 하자. 중앙집중식 버전 관리 시스템에서는 커밋의 모든 흔적을 마법처럼 지우려면 시스템 관리자에게 요청해야 한다.

 

Git은 사용자가 이와 같은 종류의 실수를 하리라고 가정하고 있다.
따라서 원하는 상태로 저장소를 재설정할 수 있다
.
저장소를 재설정하려면 git reset 명령어의 매개변수로 커밋명을 지정하면 된다. 커밋명을 지정하지 않으면 기본값으로 HEAD를 이용한다.

리비전을 지정할 때 ^ ~N 형식의 커밋명을 이용할 수 있다.
HEAD^
은 두개의 커밋을 재설정하고, 540ecb7~3 540ecb7 이전 3개의 커밋을 재설정한다.

git reset은 저장소를 갱신하고 커밋할 수 있도록 변경 사항을 스테이징한다.
이 기능은 이전 커밋에서 발견한 오류를 수정하려는 경우에 유용하다.

--soft 를 추가하면, 이전 커밋을 모두 스테이징하지만 커밋하지는 않는다.
이렇게 하면, 이전 커밋에 내용을 추가하거나 내용을 빼서 수정할 수 있도록 한다
.

git reset의 모든 옵션은 커밋을 지우지만,
기본값인
mixed는 스테이징 영역만 재설정하고 작업트리는 재설정하지 않으며
,
--soft
는 스테이징 영역과 작업 트리 모두 재설정하지 않는다
.
--hard
는 스테이징 영역과 작업 트리 모두를 재설정한다.

 

--hard 옵션은 조심해서 사용해야 한다.
--hard
를 추가하면 저장소와 작업 트리에서 커밋을 제거해버린다
.
저장소에서 이 기능은
되돌리기버튼이 없는 삭제 버튼과 다름없다.

 

$ git reset --hard HEAD^

이 명령어는 HEAD 이전 커밋으로 저장소를 재설정한다.
이렇게 하면 이전 2파일을 돌려둔 커밋은 없었던 일로 된다.

 

 

 

1.2.        이력 고쳐 쓰기

정규 코드 리뷰를 통해 자신의 코드를 샅샅이 살펴보는 작업은, 지난 주나 지난 달에 했던 가정이 아직 타당한지 확인하는 좋은 방법이다.
Git
를 이용하면 한 걸음 더 나아가 코드의 이력을 검토할 뿐 아니라 수정해서 고쳐 쓸 수 있다.

 

다음은 코드 고쳐 쓰기가 유용한 몇 가지 사례이다.

l       의미가 더 적합하도록 이력의 순서를 변경하기

사용할 일이 정말 드물기는 하지만, 언제 사용할지 닥치면 알 수 있다.
하나 이상의 커밋이 엉뚱한 위치에 있고 논리적인 순서도 맞지 않을 때 사용하다.

l       여러 개의 커밋을 하나의 커밋으로 합치기

다수의 커밋이 사실은 모두 동일한 사항과 관련되어 있으므로 하나의 큰 커밋이 되어야 한다고 느낀다면 사용한다.

l       하나의 커밋을 여러 개의 커밋으로 나누기

커밋 합치기의 반대 사례이다.
변경사항을 살펴보다, 하나의 커밋에 개별적인 커밋으로 만들고 싶은 여러 개의 변경 사항이 포함되어 있을 때 사용한다.

 

git rebase i 를 사용하면 이력을 다듬을 수 있다.
다음은 저장소의 마지막 3개의 커밋이다.

 

$ git log --pretty=format:%h %sHEAD~3..

45eaf98 add link to blog

540ecb7 copy original to show cross-file blame

222cb82 adding copied lines to showcase git blame

 

 

 

1.2.1.       커밋 순서 변경하기

git rebase 대화형 모드는 이력을 고쳐 쓸 때 사용하는 도구이다.
대화형 모드로 실행하면 편집기가 실행되어 원하는 대로 변경할 수 있다
.
Git
에서 편집기를 찾는 방법에 대해서는 4.2
변경 사항 커밋하기참고.

 

rebase 를 실행할 때, 작업을 시작할 리비전을 지정해야 한다.

여기서는 HEAD~3이 필요하다.

$ git rebase i HEAD~3

설정해놓은 대로 편집기가 실행된다.

pick 222cb82 adding copied lines to showcase git blame

pick 540ecb7 copy original to show cross-file blame

pick 45eaf98 add link to blog

 

# Rebase b87524b..45eaf98 onto b87524b

# Commands:

#

 

편집기에서 #으로 시작하는 줄은 Git에서 무시하는 주석이다.
처음 3줄이 여기서 조작하려는 3개의 커밋이다
.
pick 45eaf98
줄을 가장 위로 옮겨보자.

pick 45eaf98 add link to blog

pick 222cb82 adding copied lines to showcase git blame

pick 540ecb7 copy original to show cross-file blame

 

편집기의 내용을 저장하고 종료한다.
그러면 Git은 재정렬을 시작한다
.
작업이 끝난 다음 git log 를 다시 실행하면, 새로운 순서를 확인할 수 있다.

 

$ git log --pretty=format:%h %sHEAD~3..

8c764d3 copy original to show cross-file blame

be53bab adding copied lines to showcase git blame

4f7621d add link to blog

 

 

 

1.2.2.       여러 개의 커밋을 하나로 합치기

블로그와 트위터 커밋을 하나로 합칠 수 있다. 그러니 다시 한번 재정렬한다.
이번에는 트위터 링크 이전 커밋인 0bb3dfb^에 대해서 재정렬한다.

 

$ git rebase i 0bb3dfb^

설정해놓은 대로 편집기가 실행된다.

pick 0bb3dfb add link to twitter

pick b87524b commit of original text file

pick 4f7621d add link to blog

pick be53bab adding copied lines to showcase git blame

pick 8c764d3 copy original to show cross-file blame

#...

 

이번에는 pick 4f7621d pick 0bb3dfb 뒤에 오도록 옮겼다.
그리고 옮긴 줄의 pick squash로 바꾼다
.
이렇게 변경한 내용은 다음과 같다.

 

pick 0bb3dfb add link to twitter

squash 4f7621d add link to blog

pick b87524b commit of original text file

pick be53bab adding copied lines to showcase git blame

pick 8c764d3 copy original to show cross-file blame

 

다시 저장하고 종료한다.
재정렬 작업이 시작되면, 다시 편집기가 뜨면서, 합치려는 2커밋의 커밋메시지를 요청한다
.
기본 메시지로 다음과 비슷한 메시지가 채워져 있다.

 

# This is a combination of two commits.

# The first commits message is:

 

add link to twitter

 

# This is the 2nd commit message:

 

add link to blog

 

메시지를 적절히 조합해서 원하는 대로 수정하고 저장한 후 편집기를 종료하면 Git이 계속해서 재정렬 작업을 진행한다. git log 를 실행해보면 새로운 이력을 볼 수 있다.

 

$ git log --pretty=format:%h %sHEAD~4..

7509494 copy original to show cross-file blame

8184d47 adding copied lines to showcase git blame

9a750b3 commit of original text file

b02376d add link to twitter and blog

 

b02376d2개의 커밋으로 나눠서 방금한 커밋을 돌려놓자

 

 

 

1.2.3.       하나의 커밋을 여러 개로 나누기

지금까지 커밋 순서를 변경하고 2개의 커밋을 하나로 합쳤다.
하나의 커밋을 2개로 쪼개는 일은 약간 더 작업해야 하지만 시작은 동일하다.

git rebase i 를 다시 실행한다. 편집기가 실행되면 내용을 다음과 같이 수정한다.

 

$ git rebase i HEAD~4

편집기가 실행된다

edit b02376d add link to twitter and blog

pick 9a750b3 commit of original text file

pick 8184d47 adding copied lines to showcase git blame

pick 7509494 copy original to show cross-file blame

 

첫줄을 edit로 바꿨다.
저장하고 편집기를 종료하면 재정렬 작업이 시작된다
.
Git
은 편집(edit)하라고 지정해둔 커밋을 만나면 재정렬 작업을 멈추고 다음 내용을 출력한다.

 

Stopped at b02376dadd link to twitter and blog

You can amend the commit now, with

 

    git commit --amend

 

Once you are satisfied with your changes, run

 

    git rebase --continue

 

git log 1을 실행하면 마지막 커밋이 이전 절에서 하나로 합친 커밋임을 확인할 수 있다. 이 커밋을 edit로 지정했다.

$ git log -1

add link to twitter and blog

 

재정렬 직업은 일시 중지 상태로 사용자가 저장소를 편집할 때까지 기다린다.
마지막 커밋을 취소하고, 2개의 개별적인 커밋이 생성되도록 git reset을 이용해서 커밋을 쪼갤 수 있다.

 

$ git reset HEAD^

contact.html: locally modified

$ git diff

diff --git a/contact.html b/contact.html

 

git diff를 실행하면 커밋하려고 대기 중인 모든 변경사항을 보여준다.
2
번째 링크를 제거하고 contact.html 파일을 저장한다. 트위터에 대한 링크만 남겨두고 변경한 내용을 커밋한다.

 

$ git commit m add link to twittera

 

이제 블로그에 대한 링크를 다시 추가하고 새로 커밋한다.

 

$ git commit m add link to bloga

 

이제 커밋을 2개로 나누는 모든 변경 사항이 끝났으니 git rebase continue를 실행한다.

 

$ git rebase continue

 

로그를 살펴보면 합쳐진 커밋 대신에 다시 2개의 커밋이 존재함을 확인할 수 있다.
물론 이런 기능은 git rebase가 제공하는 다른 기능이 없었다면 지원할 수 없었을 것이다
.
git rebase
는 브랜치를 동기화하거나 이리저리 옮길 때도 사용한다. 이 기능은 9.3
브랜치 재정렬하기에서 다룬다.


출처 : http://youmin3.egloos.com/1965572

1.         Git 이력 이용하기

1.1.        Git 로그 살펴보기

$ git log

 

Git 출력 결과는 less 를 이용해서 출력되므로, 화면에 보여줄 수 있는 양보다 내용이 많다면, 로그를 스크롤 해서 볼 수 있다.

화면 하단에 콜론(:)이 있다면 출력 결과가 더 남아 있음을 의미한다.

 

git log의 기본 출력은 4가지 정보를 보여주는데,
각각은 커밋명, 작성자, 날짜, 로그 메시지이다
.
처음 3줄에 커밋명과 날짜, 로그 메시지가 표시된다
.
다음 커밋명이 나올 때까지의 영역이 로그 메시지다.

 

-p 옵션을 추가하면 리비전이 생성될 때 변경된 내용을 비교해서 보여준다.

 

지정한 수의 커밋을 볼 수 있다.

git log -1 1개의 커밋만 보여주고,

git log -2 2개의 커밋을 보여준다.

git log -10 은 마지막 10개의 로그를 보여준다.

이런 식으로 숫자를 지정할 수 있다.

 

옵션으로 리비전(커밋명)을 전달하면 해당 리비전으로 시작하는 로그를 볼 수 있다.

$ git log 7b1558c

전체 커밋명에 7자리의 짧은 커밋명을 사용햇다.
Git
은 사용자가 제공한 어떤 해시명이라도 일치시키려고 시도한다
.
물론 커밋명은 고유해야 한다.

대개는 4자리나 5자리의 해시명을 지정해도 일치하지만, 7이나 8자리의 해시명을 이용하면 거의 고유하다고 생각해도 된다.

 

 

 

1.2.        리비전 범위 지정하기

보고자 하는 커밋만 필터링하는 유용한 방법.

 

지난 5시간 동안의 커밋만 보려면 since=5 hours를 추가하면 된다.

$ git log since=5 hours

 

지난 5시간 동안의 커밋을 제외한 더 오래된 커밋만 볼 수도 있다.

$ git log before=5 hours-1

 

--since--before 옵션에는, 날짜를 표현할 수 있는 영어식 표현을 지정할 수 있다.

Gitsince=24 hours, --since=1 minute, --before=2008-10.01과 같은 형식을 모두 이해한다.

2008-10.01 처럼 하이픈(-)과 점(.)을 섞어서 사용해도 날짜를 파싱할 수 있다.

 

오래된-리비전 최신-리비전의 형식으로 범위를 지정할 수도 있다.
이때는 항상 오래된 리비전을 먼저 지정해야 Git가 이해한다.

$ git log 18f822e..0bb3dfb

리비전 18f822e 에서 0bb3dfb 까지를 요청했는데 결과는 그렇지 않다.

이런 종류의 명령은 18f822e 도 포함하리라 생각하기 쉽지만,
Git
은 그렇게 동작하지 않고, 18f822e 이후부터 0bb3dfb 까지의 모든 커밋이라고 해석한다.

 

HEAD는 저장소에서 현재 브랜치의 최신 리비전을 의미한다.

앞의 명령을 다음과 같이 변경할 수 있다.

$ git log 18f822e..HEAD

 

Git은 마지막 값을 비워두면, HEAD를 의미한다고 판단하므로 HEAD를 생략해도 된다.

$ git log 18f822e..

 

범위를 입력할 때, 커밋명 대신, 태그명을 사용해도 된다.

태그명을 이용하면 특정 태그 이후에 어떤 변화가 있었는지 확인하거나,
두 태그 사이의 리비전 이력을 보려고 할 때 유용하다.

$ git log --pretty=format:%h %s1.0..HEAD

format:%h %s옵션을 추가하면 짧은 해시와 커밋로그의 첫 번째 줄을 보여준다.
보통 커밋 로그의 첫번째 줄은 커밋에 대한 요약 정보다.

 

--pretty=oneline 은 짧은 해시가 아닌 전체 해시와 커밋 로그의 첫 번째 줄을 보여준다.

 

일반적으로 찾고자 하는 리비전은, 다른 리비전과의 관계를 통해 설명할 수 있다.
2
가지 연산자를 사용할 수 있다.

(1)    ^: 캐럿 문자는 -1로 취급한다. 18f822e^ 18f822e와 일치하는 리비전 바로 이전 리비전으로 해석한다.
여러 개의 캐럿 문자를 사용할 수도 있다
.
18f822e^^
18f822e 2번째 앞 리비전을 나타낸다.

(2)    ~N: ~기호와 숫자 연산자는 커밋명에서 N만큼 뺀다.
마지막 예를 다시 이용해보면, 18f822e~1 18f822e 바로 이전 리비전을 나타내고, 18f822e~2 18f822e 2번째 앞 리비전을 나타낸다.

 

물론 2가지 연산자를 섞어서 사용할 수도 있다.
다음 4개의 명령어는 모두 동일한 리비전을 보여준다.

$ git log -1 HEAD^^^

$ git log -1 HEAD^~2

$ git log -1 HEAD~1^^

$ git log -1 HEAD~3

 

앞의 설명했던 범위도 ^ ~를 이용하여 지정할 수 있다.

$ git log HEAD~10..HEAD

 

 

 

1.3.        버전간의 차이점 자세히 보기

4.3 변경된 내용 살펴보기에서 git diff를 사용해 작업 복사본과 저장소간의 차이를 보는 방법을 배웠다.

저장소의 이력을 볼 때도 git diff를 사용할 수 있다.

$ git diff 18f822e

 

리비전 범위와 범위 지정 연산자는 git log와 동일하다.
유일한 차이는 점진적으로 보여주는 대신에 모든 변경 사항들을 섞어서 한 번에 보여준다는 점이다.

 

git diff를 태그와 함께 이용하면, 릴리스 사이의 통계를 내는데 매우 유용하다.
git diff
에 태그를 이용하면 얼마나 많은 줄이 변경되었고, 얼마나 많이 제거되었는지 알 수 있다.

git diff에는 정말 멋진 기능이 하나 더 있는데, 변경 사항에 대한 통계를 출력하는 기능이다.
--stat
을 추가하면 된다.

$ git diff stat 1.0

지난 주 또는 마지막 태그 이후에 수정된 코드가 얼마나 되는지 알 수 있는 훌륭한 방법이다.
태그를 하나만 지정했다. 2번째 리비전을 지정하지 않으면 HEAD와 비교한다.

 

 

 

1.4.        누구 책임인지 찾기

git blame은 파일의 각 줄 앞에 커밋명, 커밋한 사람, 시간 정보를 추가해서 보여준다.

$ git blame hello.html

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 1) <html>

a5dacabd index.html (Travis S. 2008-09-21 20:37:47 -0500 2) <html>

 

git blame 출력 결과

(1)    처음 8자리 문자는 커밋 해시를 보여준다.
첫 줄에 ^이 있는 것은, 해당 커밋이 저장소에서 첫 번째 커밋임을 의미한다.

(2)    파일명이 index.html로 되어 있다.
처음에는 index.html 파일로 만들었다
.
출력 결과에서 2번째 열에, 현재 파일과 다른 이름이 있다면, 다른 파일이었을 때 변경된 내용임을 나타낸다.

(3)    커밋한 사람의 이름과 커밋한 시간을 보여준다.

(4)    줄번호와 코드 한줄을 보여준다.

 

전체 파일에 대해서 이런 정보가 필요한 경우는 별로 없다.
따라서 파일의 일부분에서만 해당 정보를 볼 수 있도록
L 옵션을 제공한다
.
-L
옵션을 이용하면 특정 범위만 보여주도록 요청할 수 있다
.
-L
옵션은
<시작>, <>의 매개변수 하나를 받는다.

 

시작과 끝은 숫자일 수 있다.

예를 들어 다음 명령어는 hello.html 파일의 12번째와 13번째 줄에 대한 정보를 보여준다.

$ git blame L 12,13 hello.html

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 12) </body>

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 13) </html>

 

끝나는 줄이 꼭 숫자일 필요는 없으며 +N이나 N의 형식으로 범위를 지정할 수 있다.
다음 명령어는 이전 명령어와 출력 결과가 동일하다.

$ git blame L 12,+2 hello.html

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 12) </body>

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 13) </html>

 

-N 표기법을 사용하면 지정한 숫자만큼 뺀다.
파일의 12번째 줄과 11번째 줄을 보려면
L 12,-2를 이용할 수 있다.

$ git blame L 12,-2 hello.html

4333289e index.html (Travis S. 2008-09-22 07:54:28 -0500 11) </ul>

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 13) </body>

 

줄번호가 표시되는 편집기를 사용중이라면 파일에서 발생한 문제를 확인할 때 숫자를 사용하는 것이 편리하다. 하지만 Git은 시작과 끝을 지정하는 다른 방법도 제공한다.
바로 정규표현식이다. (Git POSIX 정규표현식을 사용한다)

 

이전 blame 명령어를 정규 표현식을 이용하면 다음과 같이 작성할 수 있다.

$ git blame L /<\/body>/hello.html

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 12) </body>

^7b1558c index.html (Travis S. 2008-09-21 14:20:21 -0500 13) </html>

 

보고자하는 리비전을 지정하려면 6.2참고,

4333289e 커밋 이전의 hello.html 파일을 보려고 한다면 다음 명령을 이용할 수 있다.

$ git blame L /<\/body>/,-2 4333289e^ -- hello.html

옵션다음에 실제 파일명이 나오기 전에 -- 가 있음.
--
은 파일명을 지정할 때 사용한다.

 

 

 

1.5.        내용 따라가기

Git은 파일 안에서 내용이 이동했거나, 다른 파일로 옮겨갔어도 추적할 수 있다. 이 기능은 몇 줄의 코드에 대한 원본 커밋과 커밋한 사람을 추적해 갈 때 유용하다.

 

C 언어의 닫는 중괄호나 파이선의 단순한 생성자도 일치시킬 수 있도록, Git은 복사해서 붙여 넣은 코드를 감지하려고 할 때 적어도 3줄 이상을 일치시키려고 시도한다.

 

original.txt

This is the first line.

This happens to be the second line.

And this, it is the third and final line.

새로운 파일을 저장하고, 저장소에 추가하고 커밋하자.

$ git add original.txt

$ git commit m commit of original text file

파일을 다시 열어 전체 내용을 중복시킨다.

단순히 처음 3줄을 복사해서 다음 줄에 붙여 넣고 저장

 

Git이 내용을 알 수 있도록 변경사항을 커밋하고, git blame으로 파일의 각 줄의 이력을 볼 수 있다.

line1 $ git blame original.txt

- b87524b7 (1) This is the first line.

- b87524b7 (2) This happens to be the second line.

- b87524b7 (3) And this, it is the third and final line.

5 222cb821 (4) This is the first line.

- 222cb821 (5) This happens to be the second line.

- 222cb821 (6) And this, it is the third and final line.

 

출력결과는 이보다는 많을 것이다.
출력결과에서
부분은 커밋한 사람과 시간정보이다
.
처음 8자리는 커밋명의 짧은 이름이다
.
내용 앞의 숫자는 텍스트의 줄 번호이다
.
2~4
줄과 5~7은 같은 이름을 가지고 있다. 이는 지금까지 2번 커밋했음을 의미한다.

 

-M 매개변수를 추가하고 명령을 다시 해보자.
-M
git blame이 이동했거나 같은 파일에서 복사된 내용을 찾는다.

$ git blame M original.txt

b87524b7 (1) This is the first line.

b87524b7 (2) This happens to be the second line.

b87524b7 (3) And this, it is the third and final line.

b87524b7 (4) This is the first line.

b87524b7 (5) This happens to be the second line.

b87524b7 (6) And this, it is the third and final line.

이제 모든 커밋명이 동일해졌다. Git은 내용을 추적하므로 반복되는 패턴을 발견하면 동일한 내용이 있다고 판단한다.

 

Git은 파일간에 복사한 경우도 추적할 수 있다.
original.txt
를 새로운 파일인 copy.txt 파일로 복사하자
.
파일 간에 복사한 경우를 확인하려면 git blame 명령어에
C -C 를 추가하면 된다.

$ git blame C C copy.txt

b87524b7 original.txt (1) This is the first line.

b87524b7 original.txt (2) This happens to be the second line.

b87524b7 original.txt (3) And this, it is the third and final line.

b87524b7 original.txt (4) This is the first line.

b87524b7 original.txt (5) This happens to be the second line.

b87524b7 original.txt (6) And this, it is the third and final line.

Git은 원본 커밋명인 b87524b7을 보여줄 뿐 아니라, 원본 파일명인 original.txt도 보여준다.
git log
에도 동일하게
C C 매개변수를 지정하면 전체 파일이 복사됐음을 보여준다.

git log 명령어에서 복사한 내용을 찾을 때는 p 옵션을 추가해야 한다. 기존의 로그 정보 외에도 각 커밋의 변경 사항을 보여준다.

$ git log C C -1 p

commit

Author:

Date:

 

    copy original to show cross-file blame

 

diff git a/original.txt b/copy.txt

similarity index 100%

copy from original.txt

copy to copy.txt

copy.txt 파일이 original.txt 파일과 100% 일치하는 것을 알 수 있다.


출처 : http://youmin3.egloos.com/1965571

1.         브랜치 이해하고 활용하기

1.1.        브랜치란

Git의 비밀을 말해보자면 지금까지 한 모든 작업도 사실 master라는 브랜치에서 진행했다.
Git
은 모든 것을 브랜치로 다룬다
.
따라서 마스터 브랜치명을 바꾸지 못할 이유도 없다.

$ git branch m master mymaster

$ git branch

 

master 브랜치를 mymaster로 변경했다.

첫째 명령은 3개의 매개변수를 지정했다.
m 매개변수는 이동을 의미하며, 다른 2매개변수는 변경하려는 브랜치명과 새로 바꾸려는 브랜치명이다.

둘째 명령은 git branch만 사용했다.
매개변수를 지정하지 않으면 Git은 지역저장소에 있는 브랜치명을 모두 표시한다
.
현재 저장소에는 하나의 브랜치만 있으므로 브랜치명을 한 개만 표시한다.

 

Git에서는 모든 게 브랜치로 간주되므로, 브랜치를 생성하는 비용이 크지 않다.
모든 파일을 새로운 디렉터리로 복사하는 다른 시스템과는 다르게
,
Git
의 브랜치는 해당 브랜치가 만들어진 시점부터 적용된 커밋만 추적한다.

엄밀히 말하면 이것도 진실은 아니다.
Git
의 브랜치는 최신 커밋만을 추적한다
.
최신 커밋에는 부모 링크가 있고, 이 링크를 사용하여 Git은 브랜치에 있는 모든 변경 사항을 찾을 수 있다.

 

사실 브랜치를 생성할 시기를 결정하는 것이 가장 어렵다.

l       실험적인 변경사항
성능이 향상되는지 알아보려고 알고리즘을 다시 작성하거나, 코드의 일부를 특정 패턴으로 리팩터링하려고 하는가? 그렇다면 브랜치를 생성하라.
그러면 배포를 앞두고 있는 변경 사항과는 상관없이 원하는 작업을 해 볼 수 있다.

l       새로운 기능
새로운 기능을 추가할 때마다 브랜치를 생성하라.
작업이 끝나면 브랜치를 합칠 수 있다
.
이때 브랜치의 전체 변경 이력을 가져오거나, 모든 이력을 하나의 커밋으로 합쳐서 가져올 수도 있다
.
2
가지 합치는 방식에 대해서는 5.3.

l       버그 수정
아직 릴리스 하지 않은 코드의 버그거나, 릴리스 하려고 태그를 붙인 코드의 버그에 상관 없이, 버그와 관련된 변경 사항을 추적할 수 있도록 브랜치를 생성하라.
새로운 기능을 추가하는 브랜치와 마찬가지로, 수정한 부분을 기존의 코드에 반영할 때 매우 유연해진다. 특히 수정한 버그에 확신이 서지 않을 경우에 적합하다.

 

 

 

1.2.        새로운 브랜치 생성하기

다음은 new라는 브랜치를 생성한다.

$ git branch new

 

Git은 새로운 브랜치가 생성됐음을 알려주지는 않지만, 매개변수를 지정하지 않고 git branch를 실행하면 확인할 수 있다.

$ git branch

* master

new

 

새로운 new 브랜치가 생성됐음을 알 수 있다.
master
브랜치명 옆에 별표가 있음에 유의하자
.
별표는 해당 브랜치가 현재 체크아웃된 상태임을 의미한다
.
체크아웃된 브랜치는 현재 작업 트리를 나타내는 브랜치다.

 

새 브랜치는 파일 변경을 하기 위해 만들었다.
파일 변경을 하기 전에 브랜치를 먼저 체크아웃해야 한다
.
다음과 같이 checkout 명령어를 사용하여 브랜치를 체크아웃한다.

$ git checkout new

 

대부분은 브랜치를 생성할 때 새로운 브랜치로 바로 체크아웃하려고 할 것이며, 그런 경우 즉시 작업을 시작할 수 있다.
브랜치를 생성할 때는 작업을 시작하는 경우가 많으므로, 새로운 브랜치로 바로 체크아웃하는 것이 편하다. 이 방법도 Git에서는 제공한다
.
git checkout
명령어에
b 매개변수를 추가하면, 브랜치의 생성과 체크아웃을 한 번에 할 수 있다.

git checkout b 를 실행하여 다른 브랜치를 생성해 보자.
각 브랜치는 고유한 이름이어야 한다
.
따라서 master new를 제외한 다른 이름을 지정해야 한다.

$ git checkout b alternate master

 

3 번째 매개변수 master, Git이 현재 브랜치 대신 master 브랜치로부터, 새로운 브랜치를 생성하도록 한다.

물론 git branch로 새로운 브랜치를 생성하는 경우도, 추가적인 매개변수를 지정할 수 있으며, 그러면 Git은 지정한 브랜치로부터 새로운 브랜치를 생성한다.

 

 

 

1.3.        브랜치 간의 변경 사항 합치기

합치기는 말 그대로 2개 혹은 그 이상의 브랜치를 하나로 합치는 것이다.
브랜치 간의 변경 사항을 합치는 방법에는 몇가지가 있는데
,
이 절에서는 다음 3가지를 살펴본다.

l       바로 합치기(Straight Merge)는 하나의 브랜치와 다른 브랜치의 변경 이력 전체를 합치는 방법이다.

l       커밋 합치기(Squashed Commit)는 한 브랜치의 이력을 압축하여 다른 브랜치의 최신 커밋 하나로 만드는 방법이다.

l       선택하여 합치기(Cherry-picking)는 다른 브랜치에서 하나의 커밋을 가져와서 현재 브랜치에 적용하는 방법이다.

 

 

 

1.3.1.       바로 합치기(Straight Merge)

하나의 브랜치를 선택해서 다른 브랜치와 합친다.
해당 브랜치의 전체 이력을 다른 브랜치에 반영하고자 할 때 사용한다.

 

앞에서 생성한 alternate 브랜치에 새로운 변경 사항을 추가하여 합치기를 시도해 보자.
about.html
파일을 추가하고, 약간의 정보를 추가한다
.
새 파일을 생성했다면, 저장소에 추가하고 커밋한다.

$ git add about.html

$ git commit m add the skeleton of an about page

 

현재 alternate 브랜치에 커밋한 내용은 master 브랜치에 존재하지 않는다.
이제 git merge를 이용하여 2 브랜치를 합칠 수 있다.

 

먼저, 현재 브랜치를 합치고자 하는 대상 브랜치로 전환해야 한다.
여기서는 master 브랜치다.

$ git checkout master

 

그 다음 git merge를 실행한다.
가장 간단한 형태로는 git merge에 현재 브랜치에 합치려는 브랜치명을 지정하면 된다.

$ git merge alternate

 

이제 alternate 브랜치의 변경 사항이 master 브랜치에 합쳐졌다.

 

 

 

1.3.2.       커밋 합치기(Squashed Commit)

Git이 브랜치 하나의 모든 이력을 압축하여, 다른 브랜치에 하나의 커밋으로 만들기에 커밋 합치기라고 한다.
커밋합치기를 할 때는 유의해야 한다
.
이력에서 모든 커밋은 대부분 독자적으로 유지되어야 한다
.
브랜치에서 변경한 내용들이 하나의 변경 사항으로 볼 수 있다면, 커밋 합치기를 사용할 후보이다.

커밋 합치기는 이것저것 실험해 봐야 하는 새로운 기능을 만들거나 버그를 수정할 때 유용하다. 실험한 내용은 추적하지 않아도 되므로 커밋할 필요가 없다. 즉 마지막 결과만 필요할 뿐이다.

 

커밋 합치기를 하려면 합치려는 대상이 필요하다.
master
브랜치에서 contact 브랜치를 생성하고 체크아웃 한다.

$ git checkout b contact master

 

contact.html 파일을 추가한 다음 메일 주소를 입력하고 커밋.

$ git add contact.html

$ git commit m add contact file with email

 

추가 메일 주소를 입력하면 연락할 방법이 2가지가 된다. 그리고 다시 커밋

$ git commit m add secondary emaila

 

이제 contact 브랜치에는 2개의 커밋이 존재한다.
2
개의 커밋을 master 브랜치에 한 개의 커밋으로 밀어 넣을 수 있다
.
먼저 master 브랜치로 다시 전환.

$ git checkout master

 

git merge 할 때 squash 를 지정한다.
squash
를 추가하면 git merge에서 지정한 브랜치의 모든 커밋을 하나의 커밋으로 밀어 넣는다.

$ git merge --squash contact

 

contact 브랜치에 있는 2개의 커밋이 작업 트리에 적용되어 스테이징 됐지만, 아직 커밋까지 되지는 않았다.

변경사항을 확인하려면 git status를 실행

 

커밋한다.

$ git commit m add contact page\
-m
has primary and secondary email

 

 

 

1.3.3.       선택하여 합치기(Cherry-picking)

때로는 브랜치 간에 전체를 합치는 대신, 오직 하나의 커밋만 합칠 필요가 있다.
브랜치에 아직 사용할 수 없는 기능이 있거나
,
해당 브랜치에는 아직 준비가 안 된 변경 사항이 있을 수 있기 때문에, 전체 합치기가 적합하지 않은 경우가 있다.

그렇다면 언제 하나의 커밋을 밀어 넣어야 하나? 수정된 버그나 브랜치들 사이에 공유해야 하는 클래스를 추가하는 경우가 이러한 상황에 해당한다.

git cherry-pick 을 사용하면 개별적인 커밋을 밀어 넣을 수 있다.

 

현재 브랜치가 contact인지 확인한다.

$ git checkout contact

 

브랜치를 전환했으니 그 다음은 트위터 계정 같은 연락할 수 있는 새로운 링크를 추가하고 커밋한다.

$ git commit m add link to twittera

 

추가된 커밋명은 321d76f이다.
이 커밋명을 이용하면 어디서나 선택하여 합칠 수 있다.

 

이제 해당 커밋을 master로 가져가자.

$ git checkout master

$ git cherry-pick 321d76f

 

선택하려는 커밋이 여러 개라면 git cherry-pickn 매개변수를 지정한다.
-n
매개변수는 Git을 합치기는 하지만 커밋하지 않게 만든다.

 

먼저 git reset으로 바로 전 커밋을 제거한다.
이 명령어는 6.6.
변경 취소하기.

$ git reset hard HEAD^

 

이제 마지막 커밋이 제거되었고, -n 매개변수를 지정하여 git cherry-pick을 다시 실행할 수 있다.

$ git cherry-pick n 321d76f

 

Git선택하여 합치기 완료(Finished on cherry-pick)에서 중단되었다.

git status를 하여 새로운 파일이 추가되었고, 스테이징되어 커밋할 준비가 됐음을 확인할 수 있다.

 

이제 계속해서 다른 변경 사항을 선택하여 합칠 수 있다.
선택한 커밋을 모두 가져온 후 원하는 대로 메시지를 지정하여 커밋할 수 있다.

가져오기가 끝났다면 변경 사항을 커밋하자.
커밋할 때 메시지를 추가하는
m 매개변수를 지정하지 않아도 된다
.
편집기가 실행되면 기본적으로 가져온 커밋의 메시지가 나타남을 볼 수 있다.

$ git commit

 

 

 

1.4.        충돌 다루기

Git에서 커밋을 자동적으로 합칠 수 없는 경우를 충돌이라고 한다.
충돌은 각 브랜치에서 파일의 동일한 영역을 다르게 변경할 경우 흔히 나타난다.

Git은 사용자가 어떤 것을 원하는지 알 수 없으므로 충돌로 판단해서 실행을 멈추고 사용자가 수정하도록 한다.

 

합칠 내용이 간단하다면 충돌이 발생한 부분을 직접 수정한다.
변경사항을 저장하고, 일반적인 경우와 마찬가지로 변경사항을 스테이징하고 커밋한다.

복잡한 내용을 합칠 때는 코드를 비교하면서 합칠 수 있는 도구가 유용하다.
리눅스에는 kdiff3이 있으며, OS X에는 opendiff가 있다
.
git mergetool
명령어로 합치기 도구를 실행할 수 있다.

 

git mergetool 을 실행하면 합치기 도구를 찾으려고 시도하는데,
때로는 도구가 여러 개 존재할 수 있다. 이럴 때는 사용할 도구를 선택해야 한다
.
git mergetool
은 구성에 있는 merge.tool 값을 확인하여, 합치기에 적합한 도구가 있는지 시스템에 확인한다
.
적합한 도구에는 kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, opendiff가 있다.

 

충돌을 성공적으로 해결했다면, Git은 변경 사항을 커밋할 수 있도록 스테이징한다.
바로 변경 사항을 커밋하자.
m 옵션을 생략하면, 방금 일어난 사항을 설명하는 메시지가 채워진 편집기가 실행된다.

 

 

 

1.5.        브랜치 삭제하기

git branch d 로 오래된 브랜치를 삭제할 수 있다.

$ git branch d about2

 

브랜치 삭제 명령은 삭제하려는 브랜치가 성공적으로 현재 브랜치에 합쳐졌을 때만 동작한다.

 

$ git checkout master

$ git branch d about

 

about 브랜치를 합치지 않고 삭제하기를 원한다면, -d 대신 D를 지정하여 강제로 삭제할 수 있다.
-D
Git이 삭제하려는 브랜치가 현재 브랜치에 합쳐졌는지 확인하지 않고 삭제한다.

 

 

 

1.6.        브랜치명 변경하기

브랜치명을 contacts로 변경한다.

$ git branch m contact contacts

 

-m 은 존재하는 브랜치를 덮어쓰지 못하므로, 새로운 브랜치명은 반드시 고유해야 한다.
만약 존재하는 브랜치 명으로 바꾸려고 한다면 에러 메시지를 출력한다.

 

-m 대신 M 옵션을 지정하면 덮어쓰도록 동작을 바꿀 수 있다.
Git
이 해당 이름을 가진 브랜치가 존재하더라도 강제로 덮어쓰게 하므로 주의하자.


출처 : http://youmin3.egloos.com/1965470

+ Recent posts