-
버전 관리 시스템의 내부 구조를 이해하기 위해 직접 Git과 유사한 시스템을 구현한 사례
-
SHA-256 해시와 zstd 압축을 사용해 Git의 SHA-1과 zlib을 대체, .tvc 디렉터리 구조로 저장소 구성
- Rust로 작성되었으며, 파일 해시·압축·커밋·체크아웃 기능을 단계별로 구현
- 커밋 객체는 트리 해시, 부모 커밋, 작성자, 메시지를 포함하며, 동일한 파일은 해시 중복 방지로 재저장되지 않음
- Git이 콘텐츠 주소 기반 파일 저장소임을 직접 체험하며, 구조적 데이터 포맷의 중요성을 강조
해싱과 압축 방식
- Git은 모든 객체를 SHA-1 해시로 식별하지만, 이 프로젝트에서는 SHA-256을 사용
- SHA-1은 오래되고 보안상 취약하지만, 이 프로젝트는 단순히 파일 내용을 식별하기 위한 용도이므로 보안성은 중요하지 않음
- Git의 zlib 대신 Facebook의 zstd 압축 라이브러리를 채택
- zstd가 더 효율적이라고 판단했으며, Git 호환성은 목표가 아니었음
- 프로젝트 이름은 “tvc (Tony’s Version Control)” 로, .tvc와 .tvcignore 파일을 Git의 대응 구조로 사용
구현 단계
- 구현 절차는 명령 인자 읽기 → 무시 규칙 읽기 → 파일 목록 출력 → 해시 및 압축 → 트리·커밋 생성 → HEAD 관리 → 커밋 체크아웃 순서
- Rust로 작성되었으며, ls 명령은 .tvcignore 규칙을 적용해 비무시 파일을 재귀적으로 탐색하고 각 파일의 SHA-256 해시를 출력
- zstd 라이브러리를 이용해 파일 압축 및 해제 기능을 간단히 구현
커밋 구조
- 커밋 객체는 다음 정보를 포함
- 객체 유형(“commit”)
- 당시 파일 시스템 상태(트리 해시)
- 이전 커밋(HEAD)
- 작성자(author)
- 커밋 메시지
- Git과 달리 작성자와 커미터 구분을 생략, 병합이나 리베이스 기능은 구현하지 않음
- 커밋 생성 시 트리 객체를 생성·해시·압축해 .tvc/objects/에 저장하고, HEAD 파일을 갱신
- 동일한 파일은 해시가 같으면 재저장되지 않아 중복 저장 방지 가능
트리 객체와 체크아웃
-
generate_tree() 함수는 디렉터리를 순회하며 각 파일을 해시·압축·저장하고, 파일명과 해시를 문자열로 구성
- 하위 디렉터리는 재귀적으로 처리해 트리 구조를 형성
- 커밋과 트리 객체를 구조체(Commit, Tree)로 파싱해 메모리에서 다루기 쉽게 구성
-
generate_fs() 함수는 트리 구조를 기반으로 파일 시스템을 재생성하며, 지정된 경로에 체크아웃 수행
프로젝트의 교훈
- Git은 콘텐츠 주소 기반(key-value) 파일 저장소라는 점을 직접 체험
- 가장 어려웠던 부분은 객체 포맷 파싱이었으며, 다음에는 YAML이나 JSON 같은 명확한 포맷을 사용할 계획
- 전체 코드는 GitHub 저장소(tonystr/t-version-control)에서 공개
- 이 프로젝트는 Hacker News 메인 페이지에 소개되어 관련 토론이 진행됨