백엔드 JW님과 JY님이랑 단기 속성 Git 스터디를 하게 되었다. 내가 git 명령어를 복붙할 줄 안다고 해서 다룰줄 안다고 할 수 있을까! 스터디라고 해서 명령어만 배울줄 알았는데 어림없는 생각이었다. 멘토링이라고 해도될 만큼의 퀄리티.. 외쳐 갓Jw.. 스터디때 배운 내용 + 추가적으로 더 공부해볼 내용 정리겸 해보겠다.
Git
Git은 Content-addressable 파일시스템이다. 이게 무슨 말이냐 하면 Git의 핵심은 단순한 Key-Value(역주 - 예, 파일 이름과 파일 데이터) 데이터 저장소라는 것이다. 어떤 형식의 데이터라도 집어넣을 수 있고 해당 Key로 언제든지 데이터를 다시 가져올 수 있다.
.git directory

Git 저장소의 핵심! Git의 동작과 버전 관리 기능을 가능하게 하는데 필수적인 요소들을 포함한다. 이 폴더엔 Git의 내부 동작을 제어하는 파일과 폴더가 있다.
tree 구조
.git 폴더 내부에 있는 파일과 폴더들은 Git 저장소의 트리 구조를 형성하고 있다.
config
git config의 명령을 사용해서 구성 정보를 읽고 변경할 수 있다.
- Git 저장소의 구성 정보를 담고 있음.
- 주요 설정 항목, 사용자 정보, 원격 저장소 정보 등이 저장
refs 🌟
별 표시는 깃 공식 홈페이지에서 핵심이라고 말한 요소
- Git의 Reference를 저장한다.
- 참조는 브랜치, 태그, 원격 추적 브랜치 등의 이름과 커밋 해시 값을 매핑하는 역할
refs/heads 폴더에는 로컬 브랜치가, refs/tags 폴더에는 태그가 저장됩니다.
objects 🌟
- Git에서 관리되는 모든 객체(Object)를 저장한다.
- 객체는 커밋(Commit), 트리(Tree), 블롭(Blob), 태그(tag)의 데이터를 포함한다.
- 커밋 Commit
스냅샷 역할
커밋 객체는 특정 시점에서의 프로젝트의 상태를 나타냄.
각 커밋 객체는 커밋 메시지, 저자 정보, 부모 커밋 정보 등을 포함.
해당 커밋이 참조하는 트리 객체의 해시 값도 포함.
커밋 객체는 Git 저장소의 히스토리를 구성하고, 프로젝트의 변경 사항을 추적한다.
- 트리 Tree
디렉토리의 구조와 파일들의 정보를 나타냄.
각 트리 객체는 파일이나 다른 하위 트리를 가리키는 엔트리들의 목록을 포함.
트리 객체는 계층적인 구조를 가지며, 파일 시스템의 디렉토리 구조를 반영함.
- 블롭 Blob
블롭 객체는 파일의 내용을 나타낸다.
각 블롭 객체는 파일 데이터를 직접 저장하며, 파일의 SHA-1 해시 값으로 식별됨.
Git은 파일의 내용이 변경되면 새로운 블롭 객체를 생성하여 저장
- 태그 Tag
커밋이나 다른 태그를 가리키는 참조.
각 태그 객체는 태그의 이름, 태그를 생성한 사람의 정보, 태그가 가리키는 커밋의 해시 값 등을 포함
태그 객체는 주로 프로젝트의 특정 버전을 나타내는 데 사용
- 각 객체는 Git에서 파일의 스냅샷, 디렉토리의 트리 구조, 커밋 정보 등을 나타내는 역할을 한다.
- Git 내부에서 사용하는 40자 길이의
SHA-1 해시 값으로 이름이 저장된 파일들이 저장된다.
- Git은 데이터를 저장할 때 데이터와 헤더로 생성한 SHA-1 체크섬으로 파일 이름을 짓는다. 해시의 처음 두 글자를 따서 디렉토리 이름에 사용하고 나머지 38글자를 파일 이름에 사용한다.
- 객체 파일은 내부적으로 압축되어 저장되어있음.
index 파일 🌟
- Staging Area에 있는 파일들의 목록을 담고 있음.
HEAD 🌟
- 현재 작업 중인 branch를 가리킴(포인터)
- HEAD가 가리키는 커밋은 기준점으로 사용
- 보통 branch를 가리키지만 직접 커밋 해시값이나 태그를 가리킬 수도 있음.
- HEAD 파일을 통해 Git은 작업 중인 브랜치를 파악하고 새로운 커밋을 작성할 때 해당 브랜치에 연결한다.
- HEAD의 위치를 유지하고 변경하는 것은 프로젝트의 버전 관리와 작업 흐름을 올바르게 유지하는 데 매우 중요
hooks
- Git 동작의 특정 시점에서 실행되는 스크립트를 담고 있다.
- 예를 들어,
pre-commit, 커밋이 수행되기 전에 실행되는 스크립트를 포함
- 커밋 전에 자동으로 특정 작업을 수행할 수 있다.
diff 와 status 뭐가 다를까
둘다 Git에서 변경 사항을 확인하는 데에 사용되는 두 가지 명령이다. 하지만? 다른 목적과 동작을 갖고 있다!

git diff
- 현재 Working directory와 Staging area, 혹은 Commit 사이의 차이점을 보여준다.
- 변경된 파일의 내용 차이를 비교한다.
- 변경된 내용을 확인하고 수정한 파일을 Staging area에 추가하거나 Commit할 준비를 할 수 있다.
git status
- 현재 Working directory의 상태를 보여준다.
- Staging area와 Commit의 차이를 알려준다.
- 작업 디렉토리의 수정된 파일, 스테이징 영역에 있는 파일, 커밋되지 않은 변경 사항 등을 보여줌.
- 현재 작업 중인 브랜치의 상태를 파악하고 변경된 파일을 스테이징하거나 커밋할 필요성을 확인할 수 있습니다.
추적하는 값이 다르다! status는 파일의 상태가 변경되었는지 여부 체크하는 것, diff는 파일 내부 콘텐츠의 변경 여부를 체크한다.
switch와 checkout 차이점
Git 2.23에서 checkout을 대신할 switch, restore가 도입되었다.
git --help에도 checkout 명령어가 안 나온다..!
왜 checkout이 대체 되었을까?
기능이 많기 때문이다. 기능이 많으면 원하는 의도대로 시행이 안될 수 있다. 변수를 막자!
(브랜치 전환 이외에도, 커밋, 태그 등의 참조를 체크아웃하거나, 작업 디렉토리의 파일을 변경할 수 있음.)
- checkout: Switch branches or restore working tree files
- switch: Switch branches
- restore: Restore working tree files
checkout의 기능을 switch랑 restore가 나눠서 담당했다고 보면 된다.
git switch
브랜치를 변경하는 부분만 담당한다.
$ git switch develop
$ git switch -c new-branch
$ git switch -c new-branch2 515c633a
git restore
워킹 트리의 파일을 복원해 주는 역할을 한다.
$ git restore README.md
$ git restore --staged README.md
SHA-1? checksum?
- Git은 데이터를 저장하기 전에 항상 체크섬을 구하고 그 기준으로 데이터를 관리한다. 그 체크섬을 구하는데 SHA-1 해시를 사용하고, 그러면 체크섬은 160 bit가 되고, 이를 16진수로 표현하면 40자가 됨.
- 저장소에 보관하는 파일도 이 체크섬을 키로 해서 보관하고, 전체 트리(디렉터리)도 이 체크섬으로 보관하며, 커밋에 대한 데이터도 이 체크섬 기준으로 보관.
- Git은 어떤 데이터든지 데이터를 저장하기 전에 항상 체크섬을 구하고, 체크섬을 기준으로 모든 데이터를 관리한다. 이 40자는 거의 유일한 값이 나오기 때문에 고유키로 쓸 수 있다.
- 체크섬은 파일의 이름이나 작성시간이 아닌 오직 '내용content'을 기준으로 만들어진다. 그래서 만약 어떤 저장소의 A.txt, B.txt, C.txt가 모두 같은 내용 'a'를 담고 있다면, 혹은 어떤 파일의 내용이 기존의 내용에서 변한 게 없다면, Git은 여러 번 저장할 필요 없이 처음 만들었던 하나의 체크섬을 활용한다.
- Git은 파일의 변경사항만 저장하는 것이 아니라 내용 전체를 저장하는 방식으로 동작함. 이런 방식 덕분에 우리는 10번째 전에 했던 커밋이라도, 하나하나 거슬러 올라갈 필요 없이 한 번에 이동해서 찾아볼 수 있다.
SHA-1이 어떤 함수인지.. 등에 대해선 생략하겠다.
참조 ✅