#부캠 과정에서 정리한 글 재업
Git - Git 개체
여러분이 사용하는 쉘이 어떤 것인가에 따라 master^{tree} 표현식이 오류를 일으킬 수도 있다. Windows 에서 CMD는 ^ 문자는 이스케이프 기호로 사용한다. ^ 문자를 제대로 사용하려면 git cat-file -p master
git-scm.com
해당 글은 위 사이트를 참고하여 포스팅하였습니다.
하루만에 작성한 글이어서, 조금 더 깊이 있는 내용을 원하시면 위 사이트를 참고하세요!
Porcelain & Plumbing
Git은 사실 단순한 key-value 쌍으로 이뤄진 데이터의 저장소다.
(이를 Content-addressable 파일시스템이라고도 함)
여기서 key는 파일 이름,
value은 파일의 데이터를 의미한다.
그러나 실제로 K-V storeage로 직접 접근하지 않고,
Plumbing과 Porcelain 명령어를 활용해서 git을 관리한다.
여기서 plumbing 명령어는 저수준의 기본적인 일을 하며,
porcelain 명령어는 GUI나 IDE에서 활용하는 고수준의 일을 할 수 있다.
이번에는 git 개체를 확인하기 위해서 Plumbing 명령어를 사용해본다.
Git 개체
Git이 저장하는 객체에는 3가지 주요 요형이 있다.
- Blob: 원본 콘텐츠 저장
- Tree: 프로젝트에 있는 디렉터리 저장
- Commit: 커밋이 수행될 때마다 생성되고 해당 특정 커밋에 대한 모든 정보를 추상화
- (TAG): 중요하지 않으므로 x
- 그 외는 객체가 아니다.
Blob(binary large object) 개체
- 2글자를 디렉토리 이름/38글자를 파일 이름으로 사용
- 해당 파일에는 파일의 이름과 형식을 제외한 파일 내용의 전체, 즉 바이너리 데이터만을 가지고 있다.
직접 git 명령어를 통해 blob 개체가 생성되는 것을 확인해보자!
git init 명령어를 실행하면 프로젝트 내부에는 .git 폴더가 새롭게 생성된다.
.git 안에는 다음처럼 HEAD, config, description 파일과
hooks/, info/, objects/, refs/ 폴더가 새로 생성된다.
그리고 object 디렉토리에 들어가보면,
object/info, object/pack 폴더가 새롭게 생성되어 있다.
다음 hash-object -w --stdin 명령어를 실행해보자.
해당 명령어는 데이터를 저장하고, 접근하기 위한 key를 반환해준다.
데이터에는 echo 명령어로 'test content'를 넣어주었다.
여기서 반환된 key는 d670460b4b4aece5915caf5c68d12f560a9fe3e4로, 총 40자 길이의 체크섬 해시다.
그리고 나서 .git/object를 확인하니 앞의 두 글자 'd6'을 상위 폴더로,
뒤 38글자를 파일 이름으로 하여 생성되었음을 확인할 수 있다.
git cat-file -p 명령어에 위에서 반환된 key를 합쳐 입력하면, 저장된 데이터를 불러올 수 있다.
+ 만약, cat-file을 하지 않고 그냥 cat 명령어로 열어보면? 다음처럼 알 수 없는 글자가 적혀있다. 이는 zlib으로 압축해서 저장했기 때문이다.
cat 명령어를 이용해서 임의의 test.txt 파일을 생성하고, hash-object 명령을 실행해보았다.
text.txt 파일을 생성한 후, 중간에 파일 내용을 바꾸었다.
생성한 후 git hash-object 명령어를 실행하니 생성 전에는 .git/objects 파일에 파일이 하나 생성되었다.
그리고 파일 내용을 편집한 후 다시 확인하니 하나 더 생성됨을 볼 수 있다.
결국 objects의 내부에 있는 폴더와 파일은 파일을 추가한 후에 git hash-object 명령어를 실행했을 때만 생성되며,
그마저도 그 전과 파일의 변동이 없으면 생성하지 않는다.
git cat -file -p 명령어 뒤에 key 값을 입력하면, 해당 버전에서 파일 내용을 출력할 수 있다.
cat-file을 실행했다고 해서 파일의 내용이 변경되지는 않고, 그저 object에 있는 내용을 보여주는 역할만 하더라.
또한 원래 파일 이름도 없어서
key 값을 알고 있지 않으면 해당 버전으로 돌아가기는 어려울 것이다.
조금 더 실험해보니 이 hash-object -w 명령은 git add 시에 자동적으로 실행된다.
(즉 우리는 위에서 git add 시에 .git에서 일어나는 일을 본 거다)
add를 통해 stage area에 들어가게 되면 git이 본격적으로 파일을 관리하게 되는데
add를 할 때마다 버전을 관리하는 것처럼 보인다.
Tree 개체
- Tree object는 특정 시점의 디렉터리를 말한다.
- 객체에 대한 접근 권한, 파일 이름은 여기서 관리한다.
- 파일 이름, 기본 속성, 어느 디렉터리에 속하는 지의 정보를 기록한다.
Blob 개체에는 파일 이름이 아니라 체크섬을 저장했는데,
Tree 개체에는 파일 이름을 저장한다.
(이는 리눅스 파일 시스템에서 흔히 사용하는 inode - dentry 관계와 동일하다.)
Tree 개체는 git commit을 할 때마다 생성되며,
타입 - 객체명 - 파일명 이 같이 기록된다.
현재 새로 만든 폴더에 commit을 하기 전이라, tree를 찾으면 찾을 수 없다.
commit을 하고 cat-file 명령어로 tree를 살펴보면 다음과 같이
파일 모드(100644) / 개체명(blob) / key(40자의해시값) / 파일명(test.txt) 로 저장되어 있다.
Blob 파일에는 보통 3가지 모드로 나눠서 지정하는데,
보통의 파일은 100644, 실행 파일이라면 100755, 심볼릭 링크라면 12000으로 저장한다.
Blob 개체말고도 해당 Tree에는 Tree의 해시값도 들어있는데 이는 이전 Tree의 해시값을 말하고 있다.
+ 하나 착각할 수 있는 것은, Tree 개체는 변경한 파일의 해시값(blob 개체의 해시값)만 들어갈 수 있다고 생각할 수 있다. 하지만 이럴 경우, 삭제 등이 이루어질 때 복잡해진다. 실제로 Tree 개체에서는 변경된 파일 외에도, 변경되지 않은 파일의 해시값까지 모두 저장된다.
Commit 개체
지난 글에서 Git 구조에 대해 설명할 때,
commit이 되면 스냅샷의 형태로 데이터가 저장이 된다고 했다.
이 스냅샷을 누가, 언제, 왜 저장했는지는 이 Commit 개체에 저장이 된다.
commit을 하게 되면 commit 개체는 다른 blob, Tree 처럼 생성이 될 것이다.
$ git cat-file -p fdf4fc3
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 // tree 해시값
author Scott Chacon <schacon@gmail.com> 1243040974 -0700 // 작성자
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700 // 작성자
first commit // commit 메시지
안의 내부 형식은 위처럼 Tree 개체 하나와,
user.name과 user.email 설정에서 가져온 Author/Commiter 정보, 시간 정보,
그리고 한 라인 띄운다음 커밋 메시지가 들어간다.
'Git' 카테고리의 다른 글
[적용기] Git Hooks과 Git Actions로 Android CI 구축하기 (2) | 2023.07.01 |
---|---|
[적용기] Branch 전략 적용 후기(Git Flow, Github Flow) (0) | 2023.06.13 |
[TIL/개념] Git 기본: Git의 장점, 기본 명령어, Pull Request (0) | 2023.05.03 |