본문 바로가기
기타/Git

[Git] Git 개체 - Blob

by 코딩하는 랄로 2023. 11. 21.
728x90

Git의 명령어를 보다 잘 사용하기 위해서는 해당 명렁어가 깃 내부적으로 어떻게 동작하는지에 대해 알아야 한다. 또한 동작과정을 이해하기 위해서는 깃 내부를 먼저 들여다볼 필요가 있다. 이를 위해 이번 글에서는 git 홈페이지에서 메뉴얼로 제공하고 있는 progit을 통해 git 동작 시 생성되는 매우 중요한 개체 중 하나인 Git 개체에 대해서 알아보겠다.

 

 

 

Git 개체란?

저번 깃 포스팅에서 git의 init 명령어를 통해 해당 프로젝트 폴더를 깃 프로젝트 폴더로 만들 때, 매우 중요한 .git 디렉토리 폴더가 생성이 되는 것을 볼 수 있었다. 또한, 폴더 내부에 어떤 파일과 폴더들이 생성되는지도 확인하였다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy/.git (GIT_DIR!)
$ ls -al
total 11
drwxr-xr-x 1 user 197121   0 Nov 20 23:59 ./
drwxr-xr-x 1 user 197121   0 Nov 20 23:59 ../
-rw-r--r-- 1 user 197121  23 Nov 20 23:59 HEAD
-rw-r--r-- 1 user 197121 130 Nov 20 23:59 config
-rw-r--r-- 1 user 197121  73 Nov 20 23:59 description
drwxr-xr-x 1 user 197121   0 Nov 20 23:59 hooks/
drwxr-xr-x 1 user 197121   0 Nov 20 23:59 info/
drwxr-xr-x 1 user 197121   0 Nov 21 00:02 objects/
drwxr-xr-x 1 user 197121   0 Nov 20 23:59 refs/

 

여기서 objects 폴더는 모든 데이터를 저장하는 데이터 베이스를 담당하는 폴더이다. 여기서 모든 데이터란 git이 관리하는 모든 파일들에 대한 데이터를 의미하고 이 말인즉슨 모든 버전에 해당하는 데이터들 또한 object 폴더에서 관리되어 진다는 것이다.

 

깃은 object에서 보관하고 관리하는 데이터를 git 개체라고 하는데 이러한 객체에는 blob 개체, tree 개체, 커밋 개체가 있고 이번 글을 통해 알아볼 개체는 blob 개체이다.

 

 

 

Blob 개체란?

Git은 content-addressable 파일 시스템이다. 이름을 그대로 해석하면 내용 주소 지정 가능한 파일 시스템임이다. 깃의 핵심은 단순한 Key-Value 데이터 저장소라는 점인데 이 때문에 어떤 형식의 데이터도 집어넣을 수 있고, 해당 Key로 언제든지 데이터를 다시 가져올 수 있다. 

 

Git에서는 이러한 key를 지정하는 방식이 파일의 이름이 아닌 파일의 데이터를 기반으로 key를 생성하여 사용하기  때문에 content-addressable 파일 시스템이라고 하는 것이다. 이 때에 데이터가 무엇을 담고 있느냐에 따라 blob, tree, commit 개체로 나뉘게 된다.

 

 

 

Blob 개체 생성

먼저, object 안에 저장되어 있는 개체가 있는지 해당 명령어를 통해 알아볼 수 있다. 현재 git init을 통해 초기화한 후 어떠한 것도 하지 않았기 때문에 어떠한 개체도 출력되지 않는다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ find .git/objects -type f

 

이제 새로운 개체를 하나 생성해보자. object 디렉토리에 git 개체를 생성하기 위해서는 git hash-object 명령을 사용하여 새 데이터 개체를 생성할 수 있다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4

 

-w 옵션을 사용하여야 생성한 개체를 실제로 저장한다. ( 옵션을 주지 않으면, key만 출력 후 저장하지는 않음!! ) --stdin 옵션을 통해 echo를 통해 주었던 데이터를 읽어 해당 내용에 대한 key를 생성 후 object 내에 저장한다. find 옵션을 통해 해당 개체가 object 폴더 내에 생성된 것을 볼 수 있다.

 

git은 파일 내용(헤더 + 데이터, blob 개체의 경우 파일의 내용만...)을 기반으로 40자 길이의 체크섬 해시를 키로서 사용한다. 이 해시는 SHA-1해시를 사용하여 생성한 키인데, 이에 대해서는 자세히 다루지 않겠다. 40자 해시 키 중에서 앞에 2글자는 object 폴더의 하위 폴더의 이름으로 사용되고 남은 38자는 파일이름으로 생성된다.

 

이렇게 개체를 저장하였으면, git cat-file 명령에 -p 옵션을 통해 특정 개체의 파일 내용을 출력할 수 있다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content

 

 

 

Blob 개체를 이용한 버전 관리

초반에 object 폴더는 git이 관리하는 모든 파일들의 데이터를 다룬다고 하였다. 여기에는 모든 버전에 해당하는 파일도 포함된다고 하였는데 간단한 예제를 통해 git 개체를 이용하여 git에서 버전이 관리되는 방식에 대해서 살짝 맛보자.

 

먼저, version1이라는 내용을 가지는 test.txt 파일을 생성하여 보자.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ echo 'version 1' > test.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ git hash-object -w test.txt
83baae61804e65cc73a7201a7252750c76066a30

 

이제 test.txt 파일의 내용을 version 2로 바꾼 뒤 다시 저장하자.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ echo 'version 2' > test.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a

 

test.txt의 내용이 바뀌었기 때문에 이전에 해시 키는 사라지고 새로운 해시 키로 대체되었을까? 만약 그렇다면, git 은 절대 버전관리시스템으로 불리지 못했을 것이다. object가 가지고 있는 해시 키를 다시 검색해보면 지금까지 생성한 모든 git 개체가 잘 저장되어 있는 것을 볼 수 있다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4

 

여거시 다시 test.txt 내용을 version 1로 바꾸고 싶다면 어떻게 해야 할까? 아래와 같이 원하는 버전의 개체의 내용을 다시 집어넣어주면 된다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ cat test.txt
version 1

 

만약, 실수로 test.txt 내용을 날려버렸다면 어떻게 할까? 당연히 git은 개체를 그대로 저장하고 있기 때문에 이를 이용해서 언제든지 파일도 복구 할 수 있다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ rm -rf test.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ ls -al
total 8
drwxr-xr-x 1 user 197121 0 Nov 21 00:34 ./
drwxr-xr-x 1 user 197121 0 Nov 20 21:59 ../
drwxr-xr-x 1 user 197121 0 Nov 20 23:59 .git/

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ ls -al
total 9
drwxr-xr-x 1 user 197121  0 Nov 21 00:35 ./
drwxr-xr-x 1 user 197121  0 Nov 20 21:59 ../
drwxr-xr-x 1 user 197121  0 Nov 20 23:59 .git/
-rw-r--r-- 1 user 197121 10 Nov 21 00:35 test.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ cat test.txt
version 2

 

object 내에서 관리하는 개체들을 통해 어떤 식으로 버전 관리를 할 수 있는지 살펴보았다. 이렇듯 object 폴더는 버전 관리의 핵심이기 때문에 .git directory 내에서도 정말 중요한 폴더 중 하나이니 주의하여 다루어줘야 한다. 

 

 

 

내용이 같으면 다른 개체가 생성이 될까?

마지막으로 Blob 개체에서 살펴볼 것은 git은 파일의 헤더와 내용 등 데이터를 기반으로 해시키를 생성하여 사용한다고 하였고, blob 개체의 경우에는 파일의 내용만을 저장한다고 하였다.

 

그렇다면, 서로 다른 파일이라도 내용이 같다면, 과연 git에서는 이러한 상황을 어떻게 다룰까? 이를 위해 object 폴더를 초기화해준 뒤, 같은 내용을 가지는 텍스트 파일 두개를 생성하여 보겠다.

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ echo 'same content' > file1.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ git hash-object -w file1.txt
01e6138faef088714355b81759a88101ce07a1a3

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ echo 'same content' > file2.txt

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ git hash-object -w file2.txt
01e6138faef088714355b81759a88101ce07a1a3

user@DESKTOP-UCJOAKJ MINGW64 /d/GitStudy (master)
$ find .git/objects -type f
.git/objects/01/e6138faef088714355b81759a88101ce07a1a3

 

하나의 Blob 개체만을 생성하는 것을 볼 수 있다. 즉, 기존의 같은 내용으로 생성된 키가 있으면 새로운 키를 생성하는 것이 아닌 같은 내용을 지닌 키를 공유하는 것이다. Git 은 이렇게 파일의 데이터를 기반으로 개체를 생성하고 저장하기 때문에 버전 관리에 용이하면서도 저장 공간의 낭비를 줄일 수 있는 것이다.

 

 

 

 

reference : git

728x90

'기타 > Git' 카테고리의 다른 글

[Git] Git 개체 - Commit  (2) 2023.11.22
[Git] Git 개체 - Tree  (2) 2023.11.21
[Git] init  (0) 2023.11.18
[Git] 설치 및 초기 설정  (1) 2023.11.18
[Git] Git 이란?  (0) 2023.11.18