저는 git을 사용하며 명령어를 사용하는 방법에 대해서만 주로 글을 남겼는데요. 오늘은 git이 어떻게 버전관리를 할 수 있는지 내부에 대한 이야기를 해보겠습니다.
Git은 아주 단순한 Key-Value 데이터 저장소입니다. Git 오브젝트는 이러한 데이터 저장소를 의미하는 말이죠. 우리가 어떠한 파일을 작성하거나 지우는 모든 과정을 objects라는 곳에 저장하게 된다는 의미입니다.
init 명령을 통해 초기화를 진행하면, 실제로는 아무런 파일도 생기지 않습니다. 오직 .git이 생기죠. 이 내부에는 objects라는 디렉토리가 있고, 그 하위에는 pack, info 디렉토리가 생기게 됩니다. 그리고 objects 디렉토리가 데이터 저장소의 역할을 하게 되는 것이지요.
Key 값은 SHA-1 알고리즘을 이용해서 생성하게 됩니다. 그리고 이 값은 문자열로 40자입니다.
Key값으로 지정할 데이터는 어떤 데이터를 사용할까요? 데이터의 타입, 이름, 내용으로 구성되어 SHA-1 값을 생성합니다. 물론 생성하기 이전에 zlib으로 압축하게 되죠.
우리가 어떠한 파일을 생성해서 스테이징 하게 되면 objects 디렉토리에 하위 디렉토리와 파일이 생기게 됩니다. 이러한 것을 BLOB 오브젝트라고 합니다. 여기서 Key는 마찬가지로 SHA-1로 생성한 40글자입니다. 이 앞의 2글자는 디렉토리가 나머지는 파일의 이름이 됩니다.
우리는 파일 뿐만 아니라 디렉토리도 생성할 수 있습니다. 그러한 경우에는 BLOB이 아니라 TREE라는 오브젝트가 생성됩니다. TREE는 여러 BLOB 또는 TREE를 가질 수 있습니다.
COMMIT 오브젝트는 이러한 TREE 오브젝트 값과 이전 COMMIT 오브젝트의 값을 참고하여 커밋을 만들어냅니다.
Git 내부에서는 BLOB, TREE, COMMIT 만을 이용하여 스테이징과 커밋을 진행하게 됩니다. 그리고 이 모든 과정은 Key-Value 데이터 저장소인 objects 에 저장되는 것이죠!