티스토리 뷰
해당 내용은 2025 오픈소스 아카데미 체험형-1차, Redis (강대명 멘토님) 교육을 통해 나온 과제를 정리 및 학습용으로 작성되었습니다.
Redis #1 과제
1차 과제는 openup-2025-valkey 레포 내에 자신의 이름 및 연락처를 PR로 올리는 과제였습니다.
수행한 내역은 아래와 같습니다.
https://github.com/charsyam/openup-2025-valkey
GitHub - charsyam/openup-2025-valkey
Contribute to charsyam/openup-2025-valkey development by creating an account on GitHub.
github.com
Redis #2 과제
2차 과제는 아래의 명령을 수행했을 때, 내부적으로 어떻게 변경되는지에 대해서 정리하는 과제였습니다.
- git init
- git add
- git commit
- git checkout -b feature/test1
- git merge
Git?
Git은 소스 코드와 파일의 변경 이력을 시간순으로 기록하고, 필요할 때 특정 시점으로 버전으로 되돌릴 수 있게 해주는 분산형 버전 관리 시스템(DVCS, Distributed Version Control System)이라고 합니다.
이러한 Git의 주요 특징으로는 분산 구조(전체 저장소의 복사본 및 히스토리 내용을 본인 PC에 보유), 스냅샷 방식 (변경된 파일만 새로 저장 및 변경되지 않은 파일의 경우, 이전 상태 참조), 브랜치 & 병합 기능(여러 작업을 독립적으로 진행한 이후, 필요할 때 합칠 수 있음), 데이터 무결성(데이터, 해시 SHA-1으로 식별하여 변조 방지)와 같은 특징들이 존재합니다.
이번 포스팅에서는 Git의 명령어보다는, 실제 Git 명령어를 입력하면서 .git 폴더 내 파일들이 어떻게 변경되는지, Git의 내부 구조에 중점을 두고 설명하고자 합니다.
Git init
실습을 진행하기 위해, “git_work”이라는 테스트 폴더를 하나 제작하였습니다. 그 후, 해당 폴더 내에서 git init 명령어를 통해, 새로운 Git 저장소로 초기화를 진행하였습니다.
git init를 통해, 저장소를 초기화한 결과, .git 폴더가 생성된 것을 확인할 수 있었으며, 해당 폴더 내에 여러가지 디렉토리 및 파일이 생성된 것을 확인할 수 있었습니다.
해당 폴더 내 디렉토리 및 파일과 관련하여, 구성된 요소들을 설명하면 아래와 같습니다.
.git 폴더 내 요소 설명
- objects/
- 커밋 및 파일(blob), 트리(tree) 등 Git의 모든 데이터 객체가 저장되는 곳
- 실제 파일 내용, 폴더 구조, 커밋 정보 등이 해시값을 기반으로 관리
- refs/
- 브랜치, 태그 등 참조 정보가 저장
- refs/heads/
- 로컬 브랜치 정보
- refs/remotes/
- 원격 브랜치 정보
- refs/tags/
- 태그 정보
- info/
- 저장소에 대한 추가적인 설정 정보 저장 및 예외 처리를 위한 용도
- EX) exclude
- .gitifnore와 비슷하게 특정 파일이나 디렉토리를 추적 대상에서 제외 설정 가능
- 이는 로컬 저장소에만 적용, 다른 사람에게 공유 x
- hooks/
- 커밋, 푸시 등 특정 이벤트에 자동 실행되는 스크립트 파일 저장
- HEAD
- 현재 체크아웃된 브랜치(혹은 커밋)을 가리키는 포인터 파일
- description
- Git 저장소의 설명을 담는 텍스트 파일
- config
- 저장소별 Git 설정 (사용자 정보 및 원격 저장소 등)을 담고 있는 파일
git status
뒷 내용을 더 설명하기 전에, status에 대해 간략하게 살펴보고 가겠습니다.
- Working Directory / Untracked & Modified
작업 디렉토리 내에는 Untracked, Modified 상태가 존재합니다.
Modified의 경우, 파일은 수정되었으나, git add로 스테이징하지 않은 상태를 의미하며, Untracked는 새로 생성된 파일을 뜻합니다.
- Staging Area / Staged Changes
Staging Area 상태는 앞 상태에서 git add를 통해 스테이징 영역으로 넘어온 상태를 뜻하며, git commit을 통해 Repositroy에 커밋을 진행할 수 있습니다.
- Repository / Committed
git commit을 통해 변경사항이 저장소에 커밋된 상태를 의미하며, 이 상태 이후에는 git status는 working tree clen을 표시합니다.
git add & commit
add 및 commit을 진행하는 과정에서 .git 폴더 내 어떤 변화가 발생하게 되는지에 대해 확인해보겠습니다.
먼저, git_work 폴더 내에 test1.txt를 제작한 후, 테스트를 진행하였습니다.
생성 이후, status를 확인한 결과, test1.txt 파일이 Untracked 상태임을 확인할 수 있었으며,
git add를 통해 test1.txt를 추가하였습니다.
그 후, status를 다시 확인한 결과, test1.txt 파일이 Staging Area에 진입한 것을 확인할 수 있었습니다.
이후, .git 폴더로 들어간 결과, index 파일이 생성된 것을 확인할 수 있었습니다.
해당 파일을 parse-idx.py (레퍼런스 참고) 도구를 활용하여, 확인한 결과 test1.txt 파일에 대한 정보를 확인할 수 있었습니다.
해당 결과의 경우 test1.txt의 파일 권한, Blob 파일의 SHA-1 값, 파일크기 (바이트), 파일명을 뜻하고 있습니다.
상단 결과를 확인하기 위해, .git/objects/da/ 폴더 내에 존재하는 blob 파일의 SHA-1 값을 확인한 결과, 동일함을 확인할 수 있었습니다.
또한, 해당 blob 파일을 parse-object.py를 통해 분석한 결과, 상단과 같이 test1.txt 파일 내용을 확인할 수 있었습니다.
[git add 이후 .git 폴더 변화]
- add 이후 변화
- .git/index 파일 생성
- .git/objects/da/98c0210f43645aea47e5f7a030bb1722c9a7d7
- 오브젝트 파일 생성 확인
이제 git add를 통해 나온 결과를 확인하였으니, commit을 통해 .git 폴더 내에 어떤 변화가 발생하는지에 대해 확인해보겠습니다.
.git 폴더 내에서 확인한 결과, logs 폴더가 생김과 동시에, objects 폴더 및 index,
COMMIT_EDITMSG가 생긴 것을 확인할 수 있었습니다.
여기서 COMMIT_EDITMSG의 경우, 커밋 시에 작성한 커밋 메시지가 저장되는 파일이며,
해당 파일을 통해 커밋 메시지를 확인할 수 있습니다.
또한, logs 폴더의 경우, Git의 HEAD 및 브랜치 이동, 변경 기록을 추적하기 위한 내부 로그이며, git reflog 명령과 연계됩니다.
해당 내용을 기반으로 커밋 및 리베이스, 체크아웃 등과 같은 모든 참조(ref) 변화 내용들이 기록되게 됩니다.
index 파일의 경우, 별도의 변동사항은 없습니다.
단, objects 폴더 내를 확인한 결과, 새로운 디렉토리가 2개 더 생성된 것을 확인할 수 있었습니다.
해당 폴더 내 파일들을 parse-object.py를 통해 분석해본 결과,
c1 폴더 내 파일은 tree / da 폴더 내 파일은 blob / eb 폴더 내 파일은 commit이라는 것을 확인할 수 있었습니다.
여기서 확인할 수 있는 내용은 Git의 객체(object)입니다.
객체는 Blob, Tree, Commit 이라는 3가지 핵심 유형으로 구성되어 있습니다.
Blob 객체는 파일의 내용을 저장하는 Git 객체이며, 별도로 파일 이름이나 경로 정보는 저장하지 않으며, 오직 내용만 저장하는 형태로 구성되어 있습니다.
Tree 객체는 디렉토리 구조 및 각 파일의 blob/tree 해시, 권한, 이름을 저장하는 객체입니다. 해당 객체를 통해 Blob와 연결하여, 파일의 디렉토리 상태 및 권한, 해시 값을 기록하는 방식으로 활용되고 있습니다.
Commit 객체는 하나의 커밋을 구성하는 스냅샷 메타데이터이며, 이를 통해 어떤 tree를 기준으로 커밋을 했는지와 작성자 및 메시지(커밋 메시지), 부모(이전 커밋 해시)에 대한 내용을 담고 있습니다.
또한, 새롭게 생성된 logs 폴더 내 파일을 cat 명령를을 통해 확인한 결과, HEAD 및 refs/heads/main의 커밋 이력을 확인할 수 있었습니다. (커밋 객체 해시 값 확인 가능)
또한, git cat-file -p HEAD / git ls-tree HEAD를 통해, tree에 대한 해시값 및 test1.txt 해시값을 동일하게 확인할 수 있었습니다.
git checkout -b feature/test1
이후, branch 테스트를 위해 git checkout -b feature/test1을 통해, 브랜치를 변경하였습니다.
그 결과, HEAD 파일이 변경되면서, refs/heads/feature/test1을 가리키는 상태로 변경되었으며,
refs/heads/feature/test1을 확인한 결과, 앞 과정의 커밋 해시 값을 확인할 수 있었습니다.
git merge (성공시)
위 과정 이후, test2.txt 하나를 제작한 이후, add 과정을 진행하였습니다.
앞에서 설명한 것과 같이, test2.txt 파일과 관련된 정보가 index 파일 내에 추가된 것을 확인할 수 있었으며,
blob 파일이 생성된 것을 확인할 수 있었습니다.
이후, commit을 통해 test2.txt을 커밋한 후 확인할 수 있는 정보는 다음과 같았습니다.
ORIG_HEAD라는 파일이 생성됨을 확인할 수 있었습니다.
해당 파일의 경우, HEAD가 비정상적으로 바뀔 가능성이 존재하는 경우, Git이 보호 차원에서 저장하는 스냅샷입니다.
logs 폴더 내 HEAD 파일에 test2.txt의 commit 내용을 확인할 수 있었으며,
그에 따라, 커밋에 따라 발생한 트리 및 커밋 객체를 확인할 수 있었습니다.
이후, test2.txt가 담긴 feature/test1을 main 측과 병합하는 형태로 실습을 진행하였습니다.
병합 이후, 확인된 내용은 아래와 같습니다.
ORIG_HEAD 값이 변경되었음을 확인하였으며,
git log 그래프를 확인한 결과, test1 브랜치가 병합된 것을 확인할 수 있었습니다.
또한 현재 refs 값이 main에 적용된 것을 확인할 수 있었습니다.
해당 내용을 구체적으로 좀 더 테스트하고자, test2.txt를 변경한 브랜치 2개를 제작한 후, 커밋을 진행하였습니다.
- 각각, feature/test2 및 feature/test3입니다.
그 결과, test2 및 test3 브랜치가 refs에 반영된 것을 확인할 수 있었으며,
test2 브랜치가 변경한 파일 및 test3 브랜치가 변경한 파일을 별도의 blob 파일을 통해 관리하는 것을 확인할 수 있었습니다.
그 후, 현재 git log 그래프를 확인한 이후,
2개의 branch를 병합한 결과는 아래와 같습니다.
main 브랜치에 test2.txt 파일의 blob 파일이 test3에서 변경한 파일의 blob 값으로 변경되었음을 확인할 수 있었으며, tree 값 또한 변경된 것을 확인할 수 있었습니다.
git merge (충돌시)
이번엔 merge 과정에서 충돌을 발생시키기 위해, main 브랜치 내에서 conflict.txt 파일을 하나 제작해준 후, add 및 commit 과정을 진행하였습니다.
그 후, checkout을 통해, feature-branch로 변경 후, conflict.txt 파일을 다른 값으로 변경해준 이후, 커밋을 진행하였습니다.
이후, main 브랜치로 돌아온 후, conflict.txt를 변경 및 커밋을 진행한 후 merge를 진행하였습니다.
그 결과, 충돌이 발생함을 확인할 수 있었습니다.
그 후, .git 폴더를 확인한 결과, MERGE_HEAD, MERGE_MSG, MERGE_MODE와 같은 파일이 생성되었음을 확인할 수 있었습니다.
HEAD 파일의 경우, 아직 병합이 완료되지 않은 상태였기에 HEAD는 별도로 변경되지 않았습니다.
이후, 충돌이 발생한 부분을 수정하고, 이를 commit 해줌으로써, 충돌을 해결하였습니다.
그 결과, 상단과 같은 git log 그래프를 확인할 수 있었으며,
충돌로 인해 발생했던 파일들이 다시 정리된 것을 확인할 수 있었습니다.
refs/heads 측의 경우, 다음과 같이 확인할 수 있었습니다.
2주차 과제 결론
평소에 git을 사용하는 과정에서 .git 폴더 내 파일들이 어떻게 동작하고, 이를 관리하는지에 대해서는 깊게 생각해본 적이 없었는데, 이번 과제를 통해 좋은 경험을 할 수 있었던 것 같습니다.
실습을 정리하는 과정에서 다소 아쉬움이 있어, 향후 시간을 내어 다시 한번 .git 폴더를 분석해보고자 하며, 다양한 커밋 및 브랜치를 제작해둔 상태에서 이를 분석해보는 형태로도 다시 한번 진행해보고자 합니다.
레퍼런스
- 참고 레퍼런스
#git index를 좀 더 자세히 - ‘Why Should I Care about the Index?’를 보고
[Git] 버전 관리 시스템(Version Control System)의 역사?
- 도구
'#TIL & 대외활동 > 오픈소스아카데미' 카테고리의 다른 글
2025 오픈소스 아카데미 체험형-1차 / Redis (#5 과제) (0) | 2025.05.25 |
---|---|
2025 오픈소스 아카데미 체험형-1차 / Redis (#4 과제) (0) | 2025.05.25 |
2025 오픈소스 아카데미 체험형-1차 / Redis (#3 과제) (0) | 2025.05.25 |