Pro git - 3.1

Updated:

Pro git - 브랜치란 무엇인가

1. 브랜치란 무엇인가

  • Git은 데이터를 Change Set이나 변경사항(Diff)으로 기록하지 않고 일련의 스냅샷으로 기록한다.
  • 커밋하면 Git은 현 Staging Area에 있는 데이터의 스냅샷에 대한 포인터, 저자나 커밋 메시지 같은 메타데이터, 이전 커밋에 대한 포인터 등을 포함하는 커밋 개체(커밋 Object)를 저장한다.
  • 이전 커밋 포인터가 있어서 현재 커밋이 무엇을 기준으로 바뀌었는지를 알 수 있다.
  • 최초 커밋을 제외한 나머지 커밋은 이전 커밋 포인터가 적어도 하나씩 있다.
  • 브랜치를 합친 Merge 커밋 같은 경우에는 이전 커밋 포인터가 여러 개 있다.
1.1 파일이 3개 있는 디렉토리가 하나 있고 이 파일을 Staging Area에 저장하고 커밋하는 예제
  • 파일을 Stage 하면 Git 저장소에 파일을 저장한다. (Git은 이것을 Blob이라고 부른다)
  • 그리고 Staging Area에 해당 파일의 체크섬을 저장한다.
## 예시
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'
  • git commit 으로 커밋하면 먼저 루트 디렉토리와 각 하위 디렉토리의 트리 개체를 체크섬과 함께 저장소에 저장한다.
  • 그다음에 커밋 개체를 만들고 메타데이터와 루트 디렉토리 트리 개체를 가리키는 포인터 정보를 커밋 개체에 넣어 저장한다. (그래서 필요하면 언제든지 스냅샷을 다시 만들 수 있다.)
  • 이 작업을 마치고 나면 Git 저장소에는 다섯 개의 데이터 개체가 생긴다.
  • 각 파일에 대한 Blob 세 개, 파일과 디렉토리 구조가 들어 있는 트리 개체 하나, 메타데이터와 루트 트리를 가리키는 포인터가 담긴 커밋 개체 하나이다.

  • 다시 파일을 수정하고 커밋하면 이전 커밋이 무엇인지도 저장한다.

  • Git의 브랜치는 커밋 사이를 가볍게 이동할 수 있는 어떤 포인터 같은 것이다.
  • 기본적으로 Git은 master 브랜치를 만든다. (처음 커밋하면 이 master 브랜치가 생성된 커밋을 가리킨다.)

  • 이후 커밋을 만들면 master 브랜치는 자동으로 가장 마지막 커밋을 가리킨다.

  • “master” 브랜치가 존재하는 이유는 git init 명령으로 초기화할 때 자동으로 만들어진 이 브랜치를 애써 다른 이름으로 변경하지 않기 때문이다.

2. 새 브랜치 생성하기

  • 브랜치 새로 생성 (testing이라는 이름으로)
  • 새로 만든 브랜치도 지금 작업하고 있던 마지막 커밋을 가리킨다.
$ git branch testing

  • HEAD 포인터는 지금 작업하는 로컬 브랜치를 가리킨다.
  • 브랜치를 새로 만들었지만, Git은 아직 master 브랜치를 가리키고 있다.
  • git branch 명령은 브랜치를 만들기만 하고 브랜치를 옮기지 않는다.

  • git log 명령에 --decorate 옵션을 사용하면 쉽게 브랜치가 어떤 커밋을 가리키는지도 확인할 수 있다.
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) add feature #32 - ability to add new formats to the central interface
34ac2 Fixed bug #1328 - stack overflow under certain conditions
98ca9 The initial commit of my project
  • “master” 와 “testing” 이라는 브랜치가 f30ab 커밋 옆에 위치하여 이런식으로 브랜치가 가리키는 커밋을 확인할 수 있다.

3. 브랜치 이동하기

  • git checkout 명령으로 다른 브랜치로 이동할 수 있다. 이렇게 하면 HEAD는 testing 브랜치를 가리킨다.
$ git checkout testing

  • 이 상태에서 test.rb 파일을 만들고 커밋을 새로 한다.
$ vim test.rb
$ git commit -a -m 'made a change'

  • 새로 커밋해서 testing 브랜치는 앞으로 이동했다.
  • 하지만, master 브랜치는 여전히 이전 커밋을 가리킨다.
  • 여기서 master 브랜치로 가려고 한다.
$ git checkout master

  • master 브랜치가 가리키는 커밋을 HEAD가 가리키게 된다.
  • 그리고 워킹 디렉토리의 파일도 그 시점으로 되돌려진다.
  • 앞으로 커밋을 하면 다른 브랜치의 작업들과 별개로 진행되기 때문에 testing 브랜치에서 임시로 작업하고 원래 master 브랜치로 돌아와서 하던 일을 계속할 수 있다.

  • 다시 여기서 파일을 수정하고 커밋을 한다.
$ vim test.rb
$ git commit -a -m 'made other changes'
  • 두 작업 내용은 서로 독립적으로 각 브랜치에 존재한다.
  • 커밋 사이를 자유롭게 이동하다가 때가 되면 두 브랜치를 Merge 한다.

  • git log 명령으로 현재 브랜치가 가리키고 있는 히스토리가 무엇이고 어떻게 갈라져 나왔는지 보여준다.

  • git log --oneline --decorate --graph --all 이라고 실행하면 히스토리를 출력한다.

$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project