Git은 데이터를 일련의 snapshot
으로 기록한다.
commit
을 하면 Git
은 현 Staging area
에 있는 데이터의 스냅샷에 대한 포인터, 저자나 커밋 메시지 같은 메타데이터, 이전 커밋에 대한 포인터 등을 포함하는 커밋 개체(object)를 저장한다. 포인터로 이전 커밋을 가리키기 때문에 현재 커밋의 기준을 알 수 있다.
저장소의 커밋 데이터 구조
git commit
을 하면 commit
의 루트 디렉토리 개체
가 만들어진다. 이 루트 디렉토리 개체
는 staged
상태에서 git commit
으로 commit된 시점의 각 파일들의 개체
들을 담고있는 tree 개체
를 가리키는 포인터 정보를 commit 개체(루트 디렉토리 개체)
에 넣어 저장한다.
Git commit의 개체 데이터
다시 파일을 수정하고 commit
하면 이전 commit
이 무엇인지도 저장한다. 이후 commit한 개체
는 이전 commit 개체
를 가리키고 있다.
가장 최근 commit 정보를 가리키는 branch
Git
의 branch
는 커밋 사이를 자유롭게 이동가능한 포인터
라고 할 수 있다.
기본적으로 Git
은 master branch
를 만든다. 최초로 커밋하면 Git
은 master
라는 이름의 branch
를 만들어서 자동으로 마지막 commit(가장 최근 commit)
을 가리킨다.
commit 개체를 가리키는 두 branch
현재 master branch
가 어떤 commit
을 가리키고 있다. 여기에서 testing branch
를 만들어보자.
$ git branch testing
이렇게되면 master branch
와 testing branch
둘 모두 같은 commit
을 가리키게 된다.
HEAD는 현재 작업 중인 branch를 가리킨다.
Git
은 HEAD
라는 특수한 포인터가 있다. 이 포인터는 지금 작업하는 local branch
를 가리킨다.
git branch
를 하게되면 branch
를 만들기만 할 뿐 만들어진 branch
로 옮기진 않는다.
checkout 명령으로 HEAD가 가리키는 branch를 옮길 수 있다.
$ git checkout testing
앞에서 만든 testing branch
로 git checkout 명령을 사용하여 HEAD가 가리키는 branch를 옮겼다.
브랜치 이동하기
현재 HEAD는 master branch
를 가리키고 있다. 이 전 명령에서 생성한 testing branch
를 가리키게 해보자.
$ git checkout testing
새로운 파일을 만들어서 commit을 해보자.
$ vi test.rb
$ git commit -a -m 'made a change'
git commit -a -m ‘made a change’는 add
와 commit
을 동시에하고 commit의 title message
까지 적어준다는 의미이다. 이렇게되면 HEAD
가 가리키고 있는(checkout 하고있는) testing branch
은 앞으로 이동하여현재 commit이
되고 master branch
는 이전 commit
이 된다.
다시 master branch로 HEAD를 옮겨보자.
$ git checkout master
방금 실행한 일은 두 가지다.
master branch
가 가리키는commit
을HEAD
가 가리키게 했다.working directory의 files
도 그시점
으로 되돌려 놓았다.
HEAD -> master branch
HEAD가 master branch를 가리키는 시점에서 다시 files를 수정하고 commit해보자.
$ vi test.rb
$ git commit -a -m 'made other changes'
- 위 작업 전
master branch
가 가리키고 있던commit
이이전 commit
이 된다. - 그리고
master branch
는commit
한 새로운commit
을 가리키게 된다.
이렇게되면 master branch
와 testing branch
는 같은 부모 commit
을 가지게 되므로 각각 독립적인 working directory
가 생성된다.