Git 내부

key-value storage
Content-addressable
filesystem
파일내용을 SHA1 해시값을 키값으로 저장
추후 해시값을 통해서 데이터 조회
.git ?

HEAD
index
objects
refs
Plumbing
Porcelain
Git의 명령어
git add, git commit, git reset.....
Blob 개체
Git 에서 파일 내용을 저장할때 사용 (파일명 X)
$ git hash-object
$ git cat-file -p <SHA1 hash>
내용을 바이너리 형태로 저장 후 SHA1 키 리턴
SHA1 키를 통해서 내용을 조회
.git/objects
Tree 개체
Git 에서 파일 이름 기본 속성 등 메타 데이터 저장
$ git cat-file -p master^{tree}

Git의 저장 형태
Tree 만들기
$ git updat-index --add --cacheinfo <파일모드> <SHA1> <파일명>
Index 에 추가하기
파일 모드
- 100644 - 일반 파일
- 100755 - 실행 파일
- 120000 - 심볼릭 링크
Tree 개체로 저장
$ git write-tree
Read Tree
$ git read-tree <SHA1>
Tree 정보 Index 로 읽어오기
Index -> working checkout
$ git checkout-index -f -u -a
--prefix 옵션을 주면 하위 디렉토리로 추가

Commit
Tree 는 파일목록과 그 내용에 대한 포인터를 갖는다.
누가, 언제, 왜 저장했는지 알 수 없다.
Commit은 누가, 언제, 왜 에 대한 정보를 남긴다
$ git commit-tree <Tree SHA1> -m <메시지>

-p 옵션을 통해서 이전 커밋을 가리키며 연결할 수 있음
$ git commit-tree -m "second commit" be756b0 -p 29d187
$ git commit-tree -m "third commit" 63452b -p 12735d

$ git log --stat <Commit SHA1>
Git은 변경된 파일을 Blob 개체로 저장
Index에 따라 Tree개체를 만듬
이전 Commit 개체와 최상위 Tree개체를 참고해서 커밋 개체를 만듬
Blob, Tree, Commit 은 모두 .git/objects 디렉토리에 저장

Git Refs
Git log <SHA1> 을 통해 히스토리 확인 가능
SHA1 = Key = Pointer
기억하기 어려움...
이름으로 된 포인터를 저장
= Ref
Ref 만들기
$ echo f1da0f > .git/refs/heads/master
브랜치 ❌ 이름있는 포인터 ⭕️
안전하게 고치기
$ git update-ref refs/heads/master f1da0f
$ git log

$ git branch <branch> 명령은 내부적으로 update-ref를 실행
git branch test
=
git update-ref refs/heads/test <마지막 SHA1>
HEAD는 현 브랜치를 가리키는 간접 Refs
HEAD
간접 Refs = SHA1이 아닌 Ref를 가리킴

$ git symbolic-ref 로 안전하게 변경가능
$ git symbolic-ref HEAD refs/heads/test
커밋과 유사하지만 태그는 Tree개체가 아닌 Commit 개체를 가리킴
Tag
branch 와 같이 커밋을 가리키지만 옮기지 못한다.
Lightweight
단순히 특정 커밋에 대한 포인터
Annotated
저자, 이메일, 생성일 등 부가정보 같이 저장
Tag 만들기
$ git update-ref refs/tags/v.1.0.0 f1da0f
Git 내부
By y0c
Git 내부
- 177