목차
- Git이란?
- Git 동작원리
- git init
- git add
- git commit
Git이란?
Git은 2005년 리누스 토르발스에 의해 개발된 분산 버전관리 시스템이다.
Git 동작원리
Git은 SHA-1 해쉬 알고리즘을 사용해 Index 파일과 Object 디렉토리에 변경사항들을 저장합니다.
이게 무슨소리일까요? 하나씩 확인해보겠습니다.
GIT INIT
git init 을 하면 .git 이란 디렉토리가 생겼습니다.
그리고 .git 디렉토리 안에는 HEAD, config, index, objects, ... 등의 파일이 있네요
index, objects 는 아직 디렉토리에 파일이 없어서 그런듯
이를 시각화해보면 아래와 같습니다.
왼쪽에 있는 폴더와 파일들은 이번 내용과 관련이 없으므로 생략합니다.
각 파일과 폴더들은 아래와 같은 역할을 합니다.
오늘은 add와 commit 까지 정리해보려고 하기 때문에, HEAD와 refs는 저런 역할을 하는 친구구나 정도로만 이해하고 넘어가겠습니다.
objects 폴더에는 모든 데이터가 담긴다고 했는데요.
이 안에는 tree, commit, blob이라는 객체들이 저장되게 됩니다.
GIT ADD
git add 명령어는 작업 디렉토리에 있는 파일들이 변경되면 git이 감지하여 Staging Area(이하 스테이징 에리어) 에 올리게 됩니다.
실제로 어떻게 동작하는지 확인해보겠습니다.
먼저 test1.txt 파일을 생성해주었습니다.
내용은 "hello" 가 들어있습니다.
그리고 add를 하게 되면, /objects 안에 b6 라는 디렉토리가 생기고, 그 안에는 fc4c620b67... 라는 파일이 생성되었습니다.
이 b6와 fc4c620... 은 test1.txt 파일의 내용인 "hello"를 SHA-1 해시 알고리즘을 사용해 만들어낸 해시값입니다.
말로만 설명하면 이해가 어려우니 이 과정을 그림으로 그려보면 아래와 같습니다.
git add test1.txt 를 하게되면 test1.txt의 내용인 hello가 SHA-1 해시 알고리즘을 통해 b6fc4c620... 이라는 해시값을 반환하게 되고, 앞 2자리는 폴더명이 되고, 뒷자리들은 파일명이 되어 objects 폴더안에 담기게 됩니다.
이때 fc4c620.. 이라는 파일안에는 hello 라는 파일 내용이 blob 객체화 되어 담기게 됩니다.
파일 내용이 클 수 있어 압축 하는 듯?
그리고 index 파일에 test1.txt과 해당 파일의 내용이 담긴 object 주소를 저장하게 됩니다.
한번 test2.txt 라는 파일을 생성하고 add하는 과정을 그려보겠습니다.
내용은 "hello2" 라고 입력해주었습니다.
이번에도 test2.txt 의 파일내용인 "hello2" 를 SHA-1 로 해시한 해시값을 잘라 23 / 294b610... 라는 파일을 만들고, 그 안에 hello2 라는 내용이 blob 객체화 되어 저장되었습니다.
마지막으로 test3.txt 를 만들고 add해보겠습니다.
내용은 "hello" 라고 입력해주었습니다.
이번엔 새로운 파일이 생성되지 않았고, index를 보니 test3.txt 가 test1.txt와 동일한 object 주소를 가리키고 있습니다.
왜 그럴까요?
이유는 해시 값에 있는데요.
해시 알고리즘도 다양한 알고리즘이 존재합니다.
그리고 git에서 사용하는 SHA-1 알고리즘은 수학의 함수처럼 같은 값을 넣으면 항상 같은 값을 방출하는 알고리즘입니다.
그렇기 때문에 test1.txt 의 파일내용과 test3.txt 의 파일내용이 같기 때문에, 같은 b6fc4c620... 이라는 해시값을 방출했고,
이 이유로 test1.txt 와 test3.txt 는 같은 object 주소를 가리키는 것입니다.
add 정리
add에 대해 정리해보겠습니다.
add 를 하게 되면, 해당 파일의 내용을 바탕으로 해시값을 만들고, 해시값을 쪼개 objects 폴더에 blob 객체를 만들게 됩니다.
그리고 index에 해당 파일이 어떤 blob 객체를 가리키는지를 저장합니다.
이 때 파일의 내용을 바탕으로 해시값을 만들기 때문에, 서로 다른 파일이지만 내용이 같다면 같은 blob 객체를 가리키게 됩니다.
GIT COMMIT
현재 index에는 아래와 같이 기록되어있습니다.
이 상태에서 커밋을 하게 되면 어떻게 될까요?
objects 폴더에 b3, 63 폴더가 추가로 생겼네요! 그림으로 확인해보겠습니다.
이 b3와 63은 각각 커밋 객체와 트리 객체입니다.
커밋 객체를 살펴보면 tree, 커밋을 작성한 사람, 커밋 메시지가 담겨있습니다.
중요한 부분은 tree인데요.
tree는 커밋 시점의 index와 동일합니다.
즉, 커밋을 하게 되면 해당 시점의 스냅샷을 tree객체에 저장하게 되고, 커밋 객체가 그 tree를 참조하는 형식입니다.
이번에는 test2.txt의 내용을 살짝 바꿔서 add, commit을 해보겠습니다.
시나리오는 아래와 같습니다.
- test2.txt 의 내용을 "hello2" -> "hello2를 수정함" 으로 변경
git add test2.txt
git commit -m "commit2"
git add test2.txt
objects 폴더에 새로운 blob 객체가 생성되었고, index의 test2.txt도 다른 blob 객체를 가리키고 있습니다.
git commit -m "commit2"
objects 폴더에 commit 객체와 tree 객체가 생성되었습니다.
첫번째 커밋과는 다른 점이 하나 있네요.
커밋 객체에 parent 라는 부분이 추가가 되었습니다.
이미 tree는 커밋 시점의 스냅샷인 tree 객체를 가리키고 있다는 것을 알고 있습니다.
그러면 parent는 뭘 가리키고 있을까요? 확인해보겠습니다.
parent의 오브젝트 주소를 따라가보니 직전 커밋객체를 가리키고 있다는 것을 알 수 있었습니다.
이런 계층 구조를 통해, 직전 커밋의 해시값과 현재 커밋의 해시값을 비교하여 변경사항이 있는지를 확인하고, 변경이 있는 blob객체를 확인해 실제 내용이 어떻게 달라졌는지를 확인할 수 있습니다.
commit 정리
마무리로 commit 에 대해 정리해보겠습니다.
커밋을 하게 되면 objects 폴더에 커밋 객체와 트리 객체가 생성됩니다.
커밋 객체는 이전 커밋 객체를 가리키는 parent와 tree객체를 가집니다.
트리 객체는 커밋 시점의 index를 스냅샷하여 저장하는 객체입니다.
이런 계층 구조를 통해, 직전 커밋과 변경사항 비교도 할 수 있고, parent를 따라 커밋들을 탐색할 수 있습니다.
참고 자료
https://www.youtube.com/watch?v=lQ0AyoCZzns&list=PLuHgQVnccGMA8iwZwrGyNXCGy2LAAsTXk
'부스트캠프' 카테고리의 다른 글
HTTP Request, Response 구조 (0) | 2024.08.05 |
---|---|
네이버 부스트캠프 웹・모바일 9기 챌린지 과정 3주차 회고 (0) | 2024.08.02 |
동시성, 병렬성, 동기(sync), 비동기(async) 개념 정리 (2) | 2024.07.29 |
네이버 부스트캠프 웹・모바일 9기 챌린지 과정 2주차 회고 (0) | 2024.07.26 |
발행-구독 패턴(Publisher-Subscriber Pattern) (0) | 2024.07.25 |