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