원문 캡처 · app.learngit.io
원문 캡처 · app.learngit.io

Git 커밋은 변경된 파일을 통째로 묶어 저장하는 방식이 아니다. 파일 내용과 파일 이름·구조, 커밋 정보를 각각 다른 객체로 저장하고 해시로 연결한다.

LearnGit.io는 Git 저장소 안에서 커밋이 만들어지는 과정을 설명하는 인터랙티브 자료를 공개했다. 커밋 객체가 무엇인지, .git/objects/에 어떤 데이터가 저장되는지 살펴보려는 사람에게 유용하다.

커밋은 어떤 정보를 담나?

Git의 객체 데이터베이스는 도서관의 분류표를 떠올리면 쉽다. 파일 내용은 블롭(blob), 파일 이름과 객체의 묶음은 트리(tree), 작성자·날짜·메시지와 스냅샷 정보는 커밋(commit) 객체에 담긴다. 이 객체들은 서로의 해시값을 가리킨다.

커밋은 특정 시점에 함께 저장된 파일의 스냅샷과 메타데이터를 묶는다. Git 저장소의 .git/ 디렉터리에는 Git이 저장하거나 조작하는 데이터가 들어 있다. 그중 커밋 객체가 저장되는 곳이 객체 데이터베이스인 .git/objects/다.

파일은 어떻게 객체가 되나?

파일을 스테이징하고 커밋하면 Git은 파일 내용을 해시 알고리즘으로 처리한다. 만들어진 해시값은 해당 파일 내용과 연결되며, 이 내용과 해시값의 쌍을 블롭이라고 한다. 파일 내용을 바꾸고 다시 스테이징·커밋하면 새로운 객체가 저장된다.

자료는 다음 CSS 예시를 수정해 해시가 달라지는 모습을 확인하도록 구성돼 있다.

css
body {
 font-family: system-ui;
}

객체 데이터베이스의 파일은 디스크에 저장된 파일이며, 화면에 보이는 체크섬이 파일 이름으로 쓰인다. 실제 Git 프로젝트에서는 객체 파일을 압축해 저장한다. 저장소의 객체 목록은 다음 명령으로 확인할 수 있다.

bash
git cat-file --batch-check --batch-all-objects

객체 내용을 읽을 때는 다음 명령을 쓴다.

bash
git cat-file -p [filename]

커밋 객체에서 트리 객체를 따라가면 그 커밋에 포함된 파일 변경, 즉 블롭 객체를 찾을 수 있다. 트리는 블롭과 파일 이름을 연결하지만, 블롭 자체에는 파일 이름이 저장되지 않는다. 자료에 나온 커밋 객체의 내용은 다음과 같다.

text
commit 169 bytes
tree 72311fa33cf1e01048a29c8eec7ce71cc9c59dc0
author Jack Lot <jack@learngit.io> 1787865638 -0400
committer Jack Lot <jack@learngit.io> 1787865638 -0400

initial commit

어디까지 설명하나?

자료는 저장소 내부의 HEAD, 설정 파일인 config, 스테이징 영역인 index, 브랜치와 태그 이름을 담는 refs/ 등도 소개한다. 브랜치가 커밋을 어떻게 연결하는지, 여러 브랜치가 병렬로 진행되거나 병합되는 과정은 설명에서 제외했다. 그 내용은 후속 글에서 다룰 예정이라고 밝혔다.

브랜치와 병합까지 이해하려면 이 자료의 범위를 넘어서는 설명이 필요하다. 원문은 후속 글의 공개 시점과 Git 객체 압축의 세부 방식은 밝히지 않는다.