-
Git 기본 명령어 동작 원리 알아보기기타/깃(Git) 2025. 4. 29. 21:30
이번 글을 통해 2025 OSSCA 2주차 때 배운 Git 원리를 복습하고 다시 직접 실행해보면서 내용을 정리해보려고 한다.
1. Git이란?
간단하게 git 정의를 먼저 정리해보면 Git은 분산 버전 관리 시스템(DVCS)으로 소스 코드나 파일의 변경 이력을 체계적으로 관리할 수 있도록 도와주는 도구이다.
주요 특징으로는 아래와 같다.
- 버전 관리: 코드 변경 사항을 기록하고, 이전 상태로 되돌릴 수 있음
- 분산 시스템: 모든 사용자가 전체 저장소의 복사본을 가지므로, 네트워크가 없어도 작업이 가능
- 브랜치 관리: 기능 개발이나 실험을 위해 별도의 브랜치를 쉽게 만들고, 병합할 수 있음
- 협업: 여러 사람이 동시에 개발해도 충돌을 최소화하고, 변경 내역을 효과적으로 관리할 수 있음
2. git init
첫번째로 git init은 git으로 버전을 관리하기 위해서라면 필수로 처음 입력해줘야하는 명령어로 특정 폴더에 있는 파일들을 이제부터 git으로 버전관리를 하겠다는 의미이다.
git init을 실행하기 전에는 아래와 같이 해당 폴더에 아무 것도 없는 것을 볼 수 있다.
git init을 실행한 후에는 .git이라는 폴더가 생긴 것을 볼 수 있고 .git폴더가 생성되면서 이제부터 해당 폴더는 git을 통해 버전을 관리할 수 있게 된다.
3. git add
다음으로 git add 명령어이다.
git add는 git에서 정의한 state에서 untracked이거나 modified인 상태의 변경점에 대해 staged상태로 변경하여 commit을 할 수 있는 상태로 만드는 명령어이다.
test1.txt라는 파일을 새로 생성하고 git status를 통해 상태를 확인해보면 untracked상태에 text1.txt가 있는 것을 확인할 수 있다.
git add test1.txt를 실행하고 git status를 통해 상태를 확인해보면 변경된 것을 볼 수 있다.
git add를 사용하게 되면 .git폴더 내에서의 변경점은 .git폴더 내에 index라는 파일에 무언가 생긴 것을 볼 수 있고 hashing된 값이지만 test1.txt라는 문구는 볼 수 있다.
해당 파일을 parsing해서 복호화된 내용을 확인하고 싶다면 git-parser를 이용하면 되고 내용을 확인해보면 아래와 같다.
여기서 중요하게 알아야할 점은 최신버전의 test1.txt파일은 d0049~라는 hash값을 가지는 object라는 것이고 이 내용을 확인하기 위해서는 .git폴더의 objects폴더를 확인해보면 된다.
objects폴더에서 해당 hash값에 대해 관리되는 룰은 hash값의 맨 앞 2개 값(d0)이라는 하위폴더가 생기고 그 안에 맨 앞 2개 값을 제외한 값을 파일명으로 가진 파일이 생긴다.
해당 파일도 index와 마찬가지로 hashing된 내용이 저장되어있고 이를 복호화하는 작업이 필요하다.
복호화를 해보면 object의 type, size 그리고 해당 파일의 내용이 무엇인지가 저장되어있는 것을 볼 수 있다.
이를 통해 git이 어떻게 파일의 변경사항에 대한 버전을 관리할 수 있는지 감을 잡을 수 있다.
4. git commit
다음으로 git commit으로 staged상태인 것들을 commited상태로 변경함으로써 변경 사항을 로컬 저장소에 기록하는 것으로 쉽게 말해 프로젝트의 스냅샷을 찍어 저장하는 과정을 의미한다.
git commit을 실행한 뒤에 git log를 통해 commit이 정상적으로 생성된 것을 확인할 수 있다.
git commit을 통해 git 내부 변경점은 commit에 대한 내용을 저장하기 위해 hash값에 매핑되는 새로운 object가 생긴다는 것이고 이것은 위에서 본 .git/objects폴더에서 관리된다는 것으로 내용을 보면 아래와 같다.
여기서 살펴볼 점은 git add로 생긴 object 내용과 다른 것 중 하나인 tree라는 것이다.
tree 또한 object 종류 중 하나로 hash값으로 objects폴더를 검색해보면 아래와 같은 내용이 저장되어있는 것을 볼 수 있다.
해당 tree는 test1.txt파일에 대한 object를 가지고 있는 것을 볼 수 있다.
5. git checkout -b {branch_name}
다름으로는 git checkout -b {branch_name}이다.
해당 명령어는 현재 위치한 브랜치를 base branch로 하여 새로운 브랜치를 생성해주고 새로 생성된 브랜치로 이동하는 역할을 한다.
명령어를 실행한 후에 git 내부 변경사항은 첫번째로 내가 보고 있는 브랜치가 무엇인지를 저장하고 있어야하고 해당 내용은 .git폴더의 HEAD라는 파일에 저장된다.
HEAD파일에 저장된 정보는 현재 보고 있는 head에 대한 정보를 직접적으로 저정하는 것이 아닌 ref의 값에 저장된 파일을 보면 알 수 있도록 위치값을 저장해준다.
해당 위치에 있는 파일의 값을 보면 아래와 같다.
어떠한 hash값이 저장된 것을 볼 수 있고 이는 feature/test1의 최신 commit hash값과 동일한 것을 알 수 있다.
5. git merge
마지막으로 git merge 명령어이다.
git merge는 현재 바라보고 있는 브랜치에 다른 브랜치를 병합하는 동작을 하면서 다른 브랜치에 있는 내용을 현재 바라보고 있는 브랜치에 반영을 해주게 된다.
git merge를 하게되면 아래와 같이 merge commit이 생기는 것을 볼 수 있다.
그리고 해당 commit object의 내용을 살펴보면 아래와같다.
일반적으로 git commit을 통해 생성된 commit object와 다른 점은 parent가 2개라는 점이다.
git log로 보면 6e9b~ parent는 merge 전에 보고 있던 master branch의 최신 commit object값이고 2618~ parent는 merge 전에 병합하고자 했던 브랜치의 최신 commit object라는 것을 알 수 있다.
merge commit이 생성되는 이유는 히스토리 추적과 충돌 해결 내역을 남기기 위해서인데 feature/test2브랜치가 master브랜치로부터 갈라진 이후로 master브랜치에 새로운 commit이 생겼다면 merge commit이 생기게 된다.
그러면 merge commit은 왜 2개의 parent정보를 저장해야할까?
그 이유는 아래와 같다.
- 변경점 추적
두 부모 커밋 간의 차이를 계산하여 어떤 변경이 있었는지를 추적할 수 있다. - 충돌 해결 기준 제공
merge할 때 공통 조상(merge base)을 기준으로 각 부모 커밋과의 차이를 비교하고 병합하는데 merge commit에 두 부모를 명시해두면, 나중에 같은 브랜치를 다시 병합할 때 자동 충돌 해결이 가능해진다. - 커밋 그래프 유지
두 개의 부모를 가짐으로서 DAG(Directed Acyclic Graph) 형태의 커밋 그래프를 유지하면서 분기와 병합 과정을 시각화할 수 있다.
마지막으로
이번 배움을 통해 현업에서 단순히 git 명령어를 사용해왔는데 실제로 git 명령어가 어떻게 동작하는지 알 수 있는 시간이였다.
이걸 모른다고 현업에서 일의 효율화가 떨어지거나 안다고 현업에서 발생하는 에러나 버그를 빠르게 고칠 수 있다고는 생각하지 않는다.
하지만, 대부분의 회사에서 사용하는 git과 같은 툴이나 현업에서 잘 사용 중인 프레임워크, 라이브러리를 단순히 잘 사용하는 것보다는 이렇게 한번쯤은 어떻게 동작하는지 내부원리를 파악하는 습관을 들인다면 이 습관은 한 층 더 성장하는데 반드시 도움은 된다고 생각한다.
이번 배움으로 정리한 내용은 간단하고 필수적인 명령어들만 정리했는데 git cherry-pick, git reset 과 같은 명령어도 어떻게 동작하는지 시간이 되면 정리를 해보려고 한다.
지금 직접 확인을 하기 전에 이번 배움으로 예상해보면 git reset은 refs폴더에 저장된 branch가 바라보는 commit object값을 바꿈으로서 동작을 할 것으로 보이고 cherry-pick은 parent는 현재 브랜치의 최신 commit object를 가지면서 새로운 commit object가 생성될 것같다.
'기타 > 깃(Git)' 카테고리의 다른 글
[Git] 처음부터 제대로 알아보기 (0) 2022.02.02 [오류 해결] git push 멈춤 현상(무반응) (1) 2021.07.23