이 포스팅은 나를위한 간략 정리이고, 좀 더 자세한 내용을 원한다면 git book 을 참조하면 좋을 거 같다. 이 포스팅도 정리해가며 git book내용을 다수 참고함.
기존 VCS(Version Control System)들은 파일단위로 이루어졌다. 변경된 파일들만 버전을 올려가며 관리하는 방식이었다. Git은 리누스 토발즈가 linux 커널을 관리하기 위해 직접 만들며 좀 다른 개념을 가지고 만들었다. 일단, 새로만들면서 다음과 같은 목표를 가졌다.
- 빠른속도
- 단순한 구조
- 비선형적 개발 (브랜치를 사용)
- 분산 시스템
- Linux Kernel같은 큰 프로젝트에 유용할 것
명령어를 알기전 알아야 할 개념들
첫번째 새로운 개념이라 할 수 있는건, 파일단위의 버전 관리가 아니라 전체의 스냅샷을 저장하고 여기에 버전을 메긴다. 딱히 오버헤드가 생기지 않는건, 변경되지 않은 파일은 기존의 파일에 대한 링크만 가져가기 때문이다. 파일단위로만 버전을 변경하는 경우, 특정 파일들만 업데이트되어 전체의 일관성이 깨질 수 있다. 그렇지만, 이렇게 전체의 스냅샷을 관리해 나가면, 그런식의 문제는 피할 수 있다.


두번째 새로운 개념은 분산 시스템이다. 기존의 VCS들은 중앙집중식으로 하나의 저장소에 전체 소스를 관리하며, 여기에 연결해야 버전관리가 가능했다. 수정을 해도, 연결이 되지 않으면 올릴수가 없기 때문에, 연결이 되지 않는 곳에서 작업을 하게되면 로컬 작업은 하나의 큰 덩어리로 변경사항을 적용할 수 밖에 없다. Git은 기본적으로 로컬에서 모든 작업이 이루어진다. 당연히 다른 사람들과 작업을 위해 기존 VCS처럼 공유 레포지토리는 존재하지만, 로컬과 리모트 레포지토리라는 개념을 가지고 이 중앙 레포지토리 통째로 각자가 로컬에 받아와 작업을 하게 된다. 로컬에서는 모든 변경 히스토리가 기록되며, 나중에 리모트에 이 히스토리까지 병합하는 작업을 하게된다.
세번째 새로운 개념은 스테이징이다. staging 이란, git에 소스를 반영하기전에 반영할 소스들을 담아놓는 공간이다. 파일단위 버전관리가 아니고 스냅샷이라고 말한 만큼, 변경사항은 기능적 단위로 묶어 반영(commit)하게 된다. 이렇게 반영할 파일들을 staging영역에 먼저 추가 한 후, 다수의 파일을 한번에 적용하는 것이다.

요즘에야 첨부터 Git으로 배우기 시작하기도 하지만, 비슷한 VCS면서도, 이런 차이점으로 인해 git 초기에 기존 CS 사용자들은 꽤 혼란스럽기도 했었다. …그게 바로 나야 나~~
git objects 구조.
git book 의 관련 챕터 참조.
blob : 파일 내용 저장. 파일에 40자 크기의 sha-1 체크섬 해쉬를 고유값으로 파일명으로 생성하고 접근. 실제로는 2글자는 폴더 생성을 하고 38자로 파일명을 만든다고 한다.
tree : 하위 트리 객체 또는 blob를 가짐. 파일이름도 여기에 저장. blob와 tree object로 tree 구조 형성. tree가 node, blob가 leap으로 생각하면 됨.

위와같은 tree구조는 하나의 스냅샷을 형성한다.
commit : git에서 스냅샷을 저장할 때마다, 어떤 스냅샷(tree)을 누가, 언제, 어떤 내용으로 저장했는지가 필요하다. 이것들을 가지고 있는게 commit 개체이다. git log로 보게되는 git history 가 바로 이 commit 개체들을 보는 것이다. commit 개체들은 각각 스냅샷 트리를 갖고 있으므로, commit 개체로부터 스냅샷에 대한 파일 정보들도 얻어 올 수 있다.
위 3개의 개체가 git의 핵심이고 이들은 전부 .git/objects 폴더 아래에 저장된다.
위 내용대로라면 git을 사용하면서 항상 SHA-1 해쉬값을 알아야 한다. 그러나 우리가 보통 사용시, 사람들이 인식하고 쓰기 쉬운 branch 이름을 사용한다. 이들은 .git/refs/ 폴더에 저장된다. 이름에 해당하는 commit 개체의 SHA-1 해쉬값이 나열되어 있다고 생각하면 된다. 이들 참조자들은 일종의 포인터로 가르키는 commit 객체를 변경 할 수 있다. 이를 이용해 다른 branch나 이전에 commit한 개체에 대해 참조하도록 하여 checkout으로 불러올 수 있다.
지금까지의 내용으로 git의 자료구조를 살펴보면 다음과 같다.

위와 같은 구조가 단순한 파일 구조로 구성되어 있다는걸 안다면, 최초 만들어질 때 “단순한 구조”를 목표로 한다는 것이 이해가 될 것이다.
조금 더 사족을 달아 HEAD나 Tag에 대해서 말해보자. HEAD는 .git/HEAD 파일의 존재를 확인 가능한데, SHA-1값이 아니라, 현재 사용중인 refs 이름을 가르킨다. 간단하게 cat .git/HEAD 로 확인도 가능하다.
cat .git/HEAD
ref: refs/heads/mainTag는 주로 release시에 사용되는데, commit개체와 유사하면서 누가, 어떤 내용으로 tag를 달았는지 정보와 해당하는 commit 개체 정보를 가지고 있다.