그냥 블로그

[Git] VCS / SHA와 GIT / staged, modified, untraked/ Git Object 본문

CS/기타

[Git] VCS / SHA와 GIT / staged, modified, untraked/ Git Object

코딩하는 공대생 2024. 7. 31. 10:15
반응형

버전 관리 시스템 (VCS, Version Control System)

파일 변화를 시간에 따라 기록했ㄷ다가 나중에 특정 시점의 버전을 다시 불러올 수 있는 시스템. 

선택한 파일을 이전 상태로 되돌릴 수 있고, 변경 사항을 비교하고, 변경한 사람 및 변경 시기 추적 가능. 

 

로컬 버전 관리 (Local VCS)

 

로컬 데이터 베이스를 두는 느낌의 버전 관리.

대표적으로 RCS(Revision control system) : 패치 세트(즉, 파일 간 차이점)를 디스크에 특수 형식으로 보관해 작동. 모든 패치를 더해 어느 시점에서든 파일을 다시 불러올 수 있다.

 

중앙 집중형 버전 제어 시스템 (cvcs)

 

서로 협업해야할 경우를 해결하기 위해 개발됨. 

모든 버전이 있는 파일이 포함된 단일 서버와 해당 중앙 위치에서 파일을  체크아웃하는 여러 클라이언트가 있다. 

다른 사람의 작업 기록을 확인할 수 있다.

 

중앙 집중형 서버가 나타내는 단일 장애점이 존재한다. 서버에 의존한다는 단점 때문에, 서버가 다운되면 모든 사람이 아무것도 할 수 없고, 적절한 백업이 유지되지 않으면 모든 것을 잃을 수도 있다. ( 로컬에 있는 단일 스냅샷을 제외하고 전체 기록이 손실된다 )

 

분산 버전 제어 시스템 (DVCS)

 

ex) Git, Mercurial, Darcs... 

클라이언트는 파일의 최신 스냅샷을 체크아웃하는 데 그치지 않고 전체 기록을 포함해 리포지토리를 완전히 미러링한다. 따라서 서버가 죽어도 모든 클라이언트 리포지토리를 서버로 다시 복사해 복원가능하다. 

 


Git과 SHA

Git은 Content-addressable 파일 시스템으로 Git의 핵심은 아주 단순한 Key-Value 데이터 저장소다. 

 

로컬 git 저장소에 파일을 수정 / 추가하면 SHA256으로 40길이의 체크섬 해시 키가 만들어 진다. 

이 키는 단지 파일 내용을 저장했을 뿐이고, 이러한 개체를 Blob 이라 부른다.

git에선 체크섬 해시 중 맨 앞 두자리는 디렉토리 이름으로 사용하고 / 나머지 38을 파일 이름 KEY로 사용한다.

$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4

 

파일 이름은 Tree 개체로 저장된다. 

아래 예시를 보면, 파일은 blob 객체로, lib라고 하는 라이브러리는 tree 객체로 저장되었다.

$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859      README
100644 blob 8f94139338f9404f26296befa88755fc2598c289      Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0      lib

 

 

일반적으로 Staging Area(Index)의 상태대로 Tree 개체를 만들고 기록한다.

이 위에 까지, 커밋 (snapshot)을 불러오려면 키값으로 접근해야 한다.

스냅샷을 누가, 언제, 왜 저장했는지에 대한 정보는 아예 없다. 이런 정보는 커밋 개체에 저장된다.

 

커밋 개체에 대한 설명과 Tree 개체의 SHA-1 값 한 개를 가지고 커밋 개체를 만든다.

실행 시간, Author 정보에 따라 Hash 값은 다르게 나온다. 

 

 

 

*Plumbing 명령어 : Git의 저수준 명령어 cat-file, git hash-object 등..

 

 

Blob 개체 만들기
1. git 저장소를 만들고, 파일 ( 내용 )을 추가한다.
    ex) 내용 : "hi"
2. 개체 타입을 Blob으로 만들고, 이를 시작으로 헤더를 만든다 
    헤더 : "blob #{content.length}\0" ex) blob 2\0
3, 헤더와 원래 내용을 더해서 SHA 체크섬을 계산한다. -> SHA 라이브러리 -> 해시 키 나옴. 
4. zlib으로 내용(헤더 + 내용 )을 압축한다.
5. path = .git/objects/ + sha[0,2] / sha[2,38] 형식으로 만들고, zlib으로 압축한 내용을 해당 위치에 저장한다. 
// irb 명령어를 사용해 실행하고 what is up, doc을 저장하는 blob 만들기
$ irb
>> content = "what is up, doc?"
=> "what is up, doc?

// 개체 타입은 blob, 헤더를 만든다. blob 공백 내용 크기, 널문자
>> header = "blob #{content.length}\0"
=> "blob 16\u0000"

// 헤더와 내용을 합쳐서 SHA 체크섬 계산. 
>> store = header + content
=> "blob 16\u0000what is up, doc?"
>> require 'digest/sha1'
=> true
>> sha1 = Digest::SHA1.hexdigest(store)
=> "bd9dbf5aae1a3862dd1526723246b20206e5fc37"

// zlib으로 내용ㅇ을 압축
>> require 'zlib'
=> true
>> zlib_content = Zlib::Deflate.deflate(store)
=> "x\x9CK\xCA\xC9OR04c(\xCFH,Q\xC8,V(-\xD0QH\xC9O\xB6\a\x00_\x1C\a\x9D"

//zlib 압축한 내용을 개체로 저장. 
>> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
=> ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37"
>> require 'fileutils'
=> true
>> FileUtils.mkdir_p(File.dirname(path))
=> ".git/objects/bd"
>> File.open(path, 'w') { |f| f.write zlib_content }
=> 32

 

 

 

Understanding Git commit SHAs

This guide will give an overview of how Git leverages the SHA-1 hashing algorithm to organize its data internally.

graphite.dev

 

 

Git - Git 개체

여러분이 사용하는 쉘이 어떤 것인가에 따라 master^{tree} 표현식이 오류를 일으킬 수도 있다. Windows 에서 CMD는 ^ 문자는 이스케이프 기호로 사용한다. ^ 문자를 제대로 사용하려면 git cat-file -p master

git-scm.com

 

 

 


수정하고 저장소에 저장 ( staged / tracking / modified )

Working Directory의 파일은 크게 Tracked(관리 대상임) Untracked(관리 대상 아님)으로 나뉜다.

Tracked 파일은 이미 스냅샷에 포함되어 있던 파일이다. ( 간단히 말하자면 Git이 알고 있는 파일이라는 것이다. )

Tracked 파일은 또 Unmodified(수정하지 않음) Modified(수정함) Staged(커밋으로 저장소에 기록할) 상태 중 하나다.

 

나머지 모든 파일은 Untrackd 파일이다. Untracked 파일은 워킹 디렉토리에 있는 파일 중 스냅샷에도 Staging Area에도 포함되지 않은 파일이다. 처음 저장소를 Clone하면 모든 파일은 Tracked이면서 Unmodified 상태이다. 파일을 Checkout하고 아무것도 수정하지 않아 그렇다. 

 

마지막 커밋 이후 아직 아무것도 수정하지 않은 상태에서 수정하면 Git은 그 파일을 Modified 상태로 인식한다. 

커밋하기 위해서는 이 수정한 파일을 Staged 상태로 만들고, Staged 상태의 파일을 커밋한다. 

 

 

1) Git Clone -> 모든 파일은 Traked, unmodified 상태
2) 코드를 수정 -> 현재 파일을 Modified 상태
3) git add . -> staging Area에 올림 -> Staged.
4) git commit -> staged 파일을 Repository로 -> 파일 상태는 unmodified가 된다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control

 

Git - About Version Control

1.1 Getting Started - About Version Control This chapter will be about getting started with Git. We will begin by explaining some background on version control tools, then move on to how to get Git running on your system and finally how to get it set up to

git-scm.com