Github에서 레포지토리를 새로 만들면 다음과 같은 가이드가 나온다.
지금부터 init부터 branch까지 명령어에 따라 내부적으로 어떤 방식으로 작업이 이루어지는지 살펴보도록 한다.
1. git init
Local에 레포지토리를 연결 할 폴더를 하나 만들고 터미널을 통해 git init 명령어를 실행하면 .git 폴더가 생성된다.
.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개의 파일이 가리킴)
- Hash Code로 이루어진 폴더와 파일이 생성된다.
2) index 파일 생성
Blob 파일과 함께 index 파일이 .git 폴더 내에 생성된다. - .git/index
이 index 파일에는 blob 파일의 HashCode와 파일 명이 저장되어 있다.
//index
//[HashCode] [FileName]
91ed12bb... test.txt
- 파일 내용에 대한 Hash Code와 파일 이름이 생성된다.
- 폴더의 경우 파일 이름이 dir/filename 의 형식으로 저장된다.
[HashCode] [Dir/FileName]
- 폴더의 경우 파일 이름이 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의 경로를 갖고 있다.