개발/Git

[Git] .git 안에는 무엇이 있고 어떻게 동작할까

growing-dev 2023. 3. 22. 21:50

git을 사용하면서 동작하는 원리가 궁금할 때가 있었다. git의 원리를 제대로 이해하지 못하고 명령어만 사용한다면 실수할 확률이 높고 이해도 잘 안 되어 명령어를 잊어버리기 쉽다. 만약 git이 어떤 식으로 파일을 관리하고 동작하는지 이해한다면 git을 사용할 때 훨씬 더 자유롭게 사용할 수 있고 실수할 확률이 줄어든다. git의 동작을 파악하기 위해 git repository에 필수적으로 존재하는. git 디렉터리를 살펴보고 어떤 식으로 동작하는지 공부해 본다.

여러 블로그들을 보았지만 아래 블로그가 정리가 잘되어 있어서 참고했다.

https://it-eldorado.tistory.com/4

 

 

. git 안에는 무엇이 있고 어떻게 동작할까

  • . git 디렉터리 구조 파악
  • git 동작 파악

 

. git 디렉터리 구조 파악

아래는. git 내부에 존재하는 것들을 tree로 표시하도록 한 것이다.

├── COMMIT_EDITMSG
├── FETCH_HEAD
├── HEAD
├── ORIG_HEAD
├── branches
├── config
├── description
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-merge-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   └── master
│       └── remotes
│           ├── origin
│           │   └── HEAD
│           └── upstream
│               ├── master
│               └── release
├── objects
│   ├── 18
│   │   └── 511b953a1a3fe957b1a5badd7a5bacc2dc9db3
│   ├── 6c
│   │   └── a0c5648cc79f17fb1b9d9207ef835c5fa94213
│   ├── d5
│   │   └── c121c40ecc2aca1fd8010ff29c91b551d16a22
│   ├── info
│   └── pack
│       ├── pack-610814ad79609d873aaf02870ed39b0b499c2308.idx
│       ├── pack-610814ad79609d873aaf02870ed39b0b499c2308.pack
│       ├── pack-7e63ffdce12f9e8efe4b888dfe65e6d4474271f2.idx
│       └── pack-7e63ffdce12f9e8efe4b888dfe65e6d4474271f2.pack
├── packed-refs
└── refs
    ├── heads
    │   └── master
    ├── remotes
    │   ├── origin
    │   │   └── HEAD
    │   └── upstream
    │       ├── master
    │       └── release
    └── tags
        ├── v2.8.0
        ├── v2.8.1
        ├── v2.8.10

 

잘 정리되어 있는 그림이 있어서 참조하였다. 이 그림 하나로 많은 것들이 정리가 된다.

주요 3가지 개념

개념 실제 위치 설명

Working
Directory


프로젝트 
폴더
현재 수정하거나 추가하는 파일에 해당 하는 공간이다.
Index
= Staging
Area


프로젝트
폴더 하위
.git/index
파일
개념적으로는 커밋이 이뤄질 준비가 된 파일의 내용들이 위치하는 영역을 의미하며, 실제로는 하나의 파일(.git/index)로서 존재한다. 로컬에 변동 사항이 생겼을 경우, git add 명령어를 수행하면 해당 변동 사항을 인덱스 영역에 반영시킬 수 있다. 참고로, 인덱스 파일(.git/index)에는 커밋이 이뤄질 준비가 된 파일의 내용들 각각에 대하여 그 파일명과 해당 파일의 내용을 담고 있는 Blob 파일의 주소(이름)가 기록된다.
Repository 프로젝트
폴더 하위
.git/objects/ 폴더
깃이 버전 관리를 하기 위해 필요로 하는 데이터들을 저장하는 곳이다. 대표적으로, 버전 관리를 시작한 시점부터 현재 시점까지 관리해온 여러 버전들에 해당하는 파일들의 내용이 Blob 파일로서 이곳에 저장되어 있다. 이곳에 저장된 파일들을 특별히 오브젝트 파일이라고 부르며, Blob 파일도 오브젝트 파일의 한 종류이다.

 

오브젝트 파일

오브젝트 파일이란. git/objects/ 폴더에 존재하는 파일을 가리키며, 다음과 같이 분류된다.

종류 설명
Blob 파일 버전 관리하는 파일들 각각의 내용은 깃의 저장소에서 Blob 파일의 형태로 저장된다. 파일의 내용에 SHA1이라는 해싱 기법을 적용하여 Blob 파일의 이름을 얻어내기 때문에, 내용이 같은 파일들은 모두 하나의 Blob 파일로서 저장된다. 이러한 원리로 깃은 여러 버전에 걸쳐 존재하는 파일들의 내용을 중복 없이 관리할 수 있게 된다.
Commit 파일 하나의 버전을 생성한다는 것은 하나의 Commit 파일을 만드는 것을 의미한다. Commit 파일은 하나의 Tree 파일을 가리키게 되어 있다. 이 파일에는 가리키고 있는 Tree 파일의 주소(이름)와 직전 버전에 해당하는 Commit 파일의 주소(이름)가 기록된다.
Tree 파일 커밋 시점의 파일들 각각에 대해 그 파일명과 해당 파일의 내용을 담고 있는 Blob 파일의 주소(이름)가 기록된다. 위에서 설명했던 인덱스 파일(.git/index)과 성격이 유사하다.

 

HEAD와 브랜치 포인터

명칭 실제 위치 설명
HEAD .git/HEAD 현재 체크아웃되어 있는 브랜치의 포인터를 가리키는 포인터이다. 브랜치의 포인터가 아닌 일반적인 Commit 파일을 가리키게 할 수도 있다(이러한 경우를 detached HEAD라고 표현한다).
브랜치 포인터 .git/refs/heads/{브랜치명} 해당 브랜치의 가장 최신 Commit 파일을 가리키는 포인터이다.

 

HEAD와 브랜치 포인터의 히스토리

실제 위치 설명
ORIG_HEAD HEAD 값의 변화를 기록한 것으로, 위험한 명령(EX. git reset)을 수행하기 직전의 커밋을 조사하기에 유용하다.
.git/logs/refs/heads/{브랜치명} 해당 브랜치의 포인터가 어떤 명령에 의해 어떻게 바뀌었는지를 기록한 파일

 

결론

Git을 사용하면서 원리를 어느 정도 이해하고 나니 git add, git commit 등의 명령어를 수행함에 따라 Git이 어떻게 변하는지 대략적으로 감을 잡을 수 있었다. GUI로 활용하던 CLI 입력으로 Git을 사용하던 원리를 이해하면 훨씬 더 자유롭고 생산성 있게 Git을 활용할 수 있는 것 같다.

 

반응형