Git

Git 내부 동작 분석

snaildeveloper 2025. 7. 14. 16:38

Github에서 레포지토리를 새로 만들면 다음과 같은 가이드가 나온다.

 

지금부터 init부터 branch까지 명령어에 따라 내부적으로 어떤 방식으로 작업이 이루어지는지 살펴보도록 한다.

 

1. git init

Local에 레포지토리를 연결 할 폴더를 하나 만들고 터미널을 통해 git init 명령어를 실행하면 .git 폴더가 생성된다.

.git Folder

 

.git 폴더 내의 폴더 및 파일들은 Git 작업을 위한 각자의 역할들을 수행한다.


2. git add

git init을 수행한 폴더에 test/test.txt 파일을 만든 후 git add를 수행하면 두 가지의 작업이 실행된다.

 

1) Blob 파일 생성

objects 폴더 내에 Blob 파일이 생성되는데, add 명령어로 추가한 파일 내용으로 Hash 알고리즘을 돌려 나온 Hash Code로 이루어진 폴더와 Blob 파일을 생성한다.

HashCode의 앞 2자리 값을 폴더 이름으로 생성하며, 앞 2자리를 뺀 나머지 HashCode를 파일명으로 생성한다.

test.txt의 HashCode: 91ed12bbf3c1c0dc555a2...

 

 

Blob 파일에는 add한 파일의 내용이 암호화되어 저장된다.

  • Blob 객체 생성
    • Hash Code로 이루어진 폴더와 파일이 생성된다.
      • 폴더 - Hash Code의 앞에서 2개
      • 파일 명 - 폴더에서 뺀 2개를 제외한 나머지
    • 파일 내용은 add한 파일의 내용
    • 파일 내용을 Hash로 변환하기 때문에 파일 내용이 같은 두 개의 파일의 경우 동일한 blob 파일을 갖는다.
      (1개의 blob 파일을 2개의 파일이 가리킴)

 

2) index 파일 생성

Blob 파일과 함께 index 파일이 .git 폴더 내에 생성된다. - .git/index

이 index 파일에는 blob 파일의 HashCode와 파일 명이 저장되어 있다.

//index
//[HashCode] [FileName]
91ed12bb...  test.txt
  • 파일 내용에 대한 Hash Code파일 이름이 생성된다.
    • 폴더의 경우 파일 이름이 dir/filename 의 형식으로 저장된다.
      [HashCode] [Dir/FileName]
  • Commit 이후 수정 된 파일을 다시 add 하는 경우
    • 변경 된 파일의 경우 새로 추가되는 것이 아닌 HashCode 값만 바뀐다.
    • 새로 추가된 파일의 경우, 새로운 파일에 대한 HashCode와 파일 명이 새로 추가
  • 파일 명이 달라도 파일 내용이 같다면 같은 Hash Code를 가리킨다.
    • Git은 파일 내용을 해시 알고리즘(SHA-1)을 통해 Hash 값을 도출하기 때문에 파일 이름이 달라도 파일 내용이 같으면 같은 Hash Code를 가리키게 된다.
    • 파일 명이 다르기 때문에 동일한 Hash Code와 다른 파일 명으로 새로 추가된다.
//index (test.txt와 test3.txt의 내용이 같음)
91ed12bb...  test.txt
67ec12ksn... test2.txt
91ed12bb...  test3.txt

 


3. git commit

git add 한 파일들을 commit 명령어로 commit을 했을 때 다음과 같은 작업들이 이루어진다.

 

1) Commit 파일 

objects 폴더 내에 commit 파일이 생성된다.

폴더와 파일 명은 똑같이 Hash 코드로 이루어져 있고, commit 파일에는 tree 파일의 hash 코드 값이 저장된다.

// commit
tree [HashCode]

 

만인 이전 commit 이력이 존재하는 경우 이전 commit tree의 정보가 parent의 이름으로 추가 저장된다.

// commit
tree [HashCode]
parent [HashCode]

 

2) Tree 파일

tree 파일 또한 마찬가지로 Hash 코드로 폴더와 파일 명이 생성되고, commit 된 blob 파일들의 정보가 저장된다.

// tree
//blob [Blob HashCode] [fileName]
blob  91ed12bbf3c1c0dc555a2... test.txt

 

  • git add로 생성 된 blob 파일의 HashCode가 123abc 인 경우
  • HashCode가 456def 인 tree 파일에 blob 123abc가 저장 및 생성되고
  • tree 456def 가 저장 된 commit 파일이 HashCode로 이루어진 경로에 생성된다. 

tree 파일의 경우 파일 경로마다 생성된다. 예를 들어 파일이 다음과 같이 존재하는 경우

  • root/test.txt
  • root/test/test2.txt
// commit
tree [root tree HashCode]
// root tree
tree [test folder의 tree HashCode] test
blob [test.txt의 HashCode] test.txt
// test folder tree
blob [test2.txt의 HashCode] test2.txt

위와 같이 1개의 commit 파일과 2개의 tree 파일이 생성된다.

 

Commit까지 중간 정리

commit까지의 정보를 요약하자면

 

objects의 폴더에는 add와 commit 명령어를 통해 3가지의 파일이 저장된다.

  • git add
    • blob : 파일 정보
  • git commit
    • tree : blob 또는 폴더에 대한 정보
    • commit : tree 정보

commit에 있는 tree의 HashCode를 통해 tree 내의 blob 파일의 HashCode를 얻을 수 있고, blob 파일을 통해 파일 내용을 알 수 있는데, 이게 가능한 이유는 HashCode로 폴더와 파일명을 생성하기 때문이다.

 

index 파일의 경우 add를 통해 생성 된 blob 파일들의 HashCode와 파일 명이 저장된다.


4. git status

git status 명령어는 현재 파일 목록 중 add 된 파일과 add 되지 않은 파일을 알려준다.

위와 같이 두 개의 text 파일을 생성한 뒤 add-text 파일만 add 하고 status를 실행하면 아래와 같은 결과를 얻을 수 있다.

 

status 명령어로 확인 할 수 있는 이유는 commit 명령어까지의 과정을 이해했다면 다음과 같이 쉽게 유추할 수 있다.

  • 수정되지 않은 파일 (add가 필요 없는 파일, status 목록에 안뜸)
    • index 파일에 저장 된 폴더와 파일 경로가 같고, HashCode 또한 같은 경우
    • 최근 Commit한 파일의 HashCode와 같은 경우 (commit 파일에서 tree를 통해 확인 가능)
  • add 한 파일
    • index 파일에 저장 된 폴더와 파일의 경로 및 HashCode가 같은 경우
    • 최근 Commit한 파일의 HashCode와 다르거나 없는 경우
  • add 가능한 파일
    • index 파일에 저장 된 파일 경로는 같지만 HashCode가 다르거나 없는 경우
    • index 파일에 저장 된 파일 경로가 없는 경우

5. git branch

지금까지 index와 objects 폴더를 살펴봤다면 branch는 HEAD 파일과 refs/heads 폴더를 살펴볼 것이다.

1) refs/heads

refs/heads를 가면 브랜치들의 정보를 확인할 수 있다.

 

현재는 master 브랜치 하나 밖에 없기 때문에 master 파일만 존재하지만 새로운 브랜치를 생성한다면 해당 브랜치에 대한 파일이 생길 것이다.

 

refs/heads에 있는 브랜치 파일에는 어떤 정보가 담겨있을까? 바로 해당 브랜치의 최근 commit HashCode가 들어있다.

 

objects 경로에서 확인해보면 해당 commit 파일을 확인할 수 있다.

 

1) HEAD 파일

HEAD 파일은 현재 사용 중인 Branch를 나타내며, 아래와 같이 현재 사용 중인 branch의 경로를 갖고 있다.