Git은 내부적으로 어떻게 동작할까?
git init 명령어를 통해 현재 디렉토리에 새로운 Git 저장소를 생성한다.
해당 명령을 내리면 현재 디렉토리에 .git 디렉토리가 생성된다. 또한, 내부에 index, HEAD, config 파일, objects 디렉토리 등 다양한 파일 및 디렉토리가 만들어진다.
각각은 어떤 역할을 할까?
📌 Git object
.git/objects 디렉토리에는 해시값으로 변환된 객체들이 저장된다. 변환된 각 객체들은 objects 디렉토리에 40자의 체크섬 중 앞 2글자를 디렉토리명으로, 나머지를 파일명으로 하여 저장된다.
이때 Git의 객체는 총 4가지인데 여기선 3가지를 중점적으로 살펴볼 것이다.
1️⃣ Blob 객체
Blob(binary large object)객체는 파일의 내용만을 저장하는 객체이다. 파일 이름이나 파일 형식은 저장되지않고 오로지 파일의 내용만 저장된다. 따라서 텍스트, 이미지 등의 다양한 형식이 지원된다.
2️⃣ Tree 객체
Tree 객체는 파일 시스템과 비슷한 방법으로 저장된다. 트리 객체는 Blob객체와 Tree객체를 포함한다. 이때 파일 이름을 저장한다. 따라서 Blob의 해시값과 파일명, 또는 또 다른 Tree의 해시값과 디렉토리명이 담겨있다.
간단하게 표현하면 위 그림과 같은 구조를 가진다.
3️⃣ commit 객체
commit 객체는 실제 commit 명령 시 함께 생성되는 tree의 체크섬(해시값)과 커밋 메세지, Author/Committer 정보를 담고있다. 각 커밋 객체는 이전 커밋 객체를 가리키도록 구현되어 따로 커밋 히스토리를 관리하지는 않는다.
📌 git add 명령을 하면 무슨일이?!
git add 명령 시 stage area에 변경 사항이 올라간다.
파일의 수정사항이 생겼을땐, 변경 사항만을 담아 Blob 객체로 저장하는 것이 아닌 전체 파일을 해시값으로 변환하여 저장한다.
만약, 내용이 똑같은 Blob객체가 이미 존재한다면 새로 생성되지않고 해당 Blob의 해시값을 index파일에 파일명과 함께 저장한다. 앞서 말했듯이 변경된 파일들이 index파일에 Blob객체의 해시값과 파일명 등이 저장되어 관리된다.
📌 git commit 명령은???
git commit 명령 시 새로운 commit 객체와 tree 객체가 생성된다.
먼저 stage area에 올라온 파일 정보를 모두 담아서 tree 객체를 생성한다. 이 tree객체의 해시값을 commit 객체에 담아서 트리정보와 커밋정보를 함께 관리한다!
이때 HEAD 파일도 이전 HEAD를 부모로하는 커밋 객체가 생성되며, 새로운 커밋 HEAD로 갱신된다.