부끄러운 일이지만 git은 정말 간략하게만 알았던 것 같다.
깃을 대충 알면 어뜨케 되느냐,,,
급하고 안 되니까 구글링해서 쉘 커맨드 복붙,,,
충돌나면 깔끔하게 날리고 다시 받아버리기,,,
다른 사람한테 zip 파일로 코드 받아서 복붙하기,,,
--> 강의에 나온 이야기인데 놀랍게도 한 번씩 다 해봤던 일;;
이런 짓을 몇 번 하다보면 아 정말 깃을 다시 배워야겠다 라는 생각이 드는데
오늘이 바로 그날.
영상 후반부는 많이 아는 내용이었는데, 의외로 초반부가 많이 생소했다.
깃의 데이터구조에 대해서 한 번도 고민해보지 않았기 때문.
오히려 기초를 알고 나니까 헷갈리던 것들이 좀 더 명확히 이해가 되었다.
깃은 형상관리 툴 중의 하나로 내 프로젝트의 히스토리를 관리할 수 있다.
다르게 말하자면 변경될 때마다 해당 버전을 snapshot 찍듯이 저장해둘 수 있다.
파워포인트 작업을 하다보면 _최종.pptx _진짜진짜최종.pptx가 카톡을 이리저리 왔다리갔다리 하는데
git에서는 파워포인트처럼 선형적으로 스냅샷을 저장하고 관리할 수 있는 게 아니라
병렬적으로 관리가 가능하다.
그러니까 일반적인 문서작업을 할 때는 A가 수정하고 B가 수정한 버전을 우리가 시간 순서대로 받아서
일일히 복붙해서 그 자리에 끼워넣어야한다. 하지만 깃은 해당 버전의 차이를 확인하고 자동으로 합칠 수 있다.
그렇다고 완전히 새롭고 다른 두 파일의 차이까지 합치지는 못한다. 왜? 기준이 없으니까.
뭘 기준으로 변경되었는지 알아야지, A가 변경한 거랑 B가 변경한 거랑 차이를 알 거니까
그래서
깃은 이를 위한 자료구조로
DAG(Directed Acyclic Graph) 자료구조를 채택한다.
해당 자료구조는 부모와 자식이 있으면서 자기자신에게 돌아올 수 없는 비순환적 그래프(혹은 트리)이다.
자식은 여러개일 수 있다.
먼저 깃의 데이터 모델부터 배우는 게 흥미로웠다.
깃에서의 오브젝트란 blob(file), tree(folder), commit가 있다.
// a file is a bunch of bytes
type blob = array<byte>
// a directory contains named files and directories
type tree = map<string, tree | blob>
// a commit has parents, metadata, and the top-level tree
type commit = struct {
parent: array<commit>
author: string
message: string
snapshot: tree
}
type object = blob | tree | commit
오브젝트들은 모두 sha-1(hash function)으로 도출되는 id 값으로 저장/로딩된다.
-> 나는 깃오브젝트로 커밋 정도만 생각했다. 또 커밋 정도만 아이디가 있다고 생각했다! git add나 git commit 할 때 옆에 보이니까! 근데 파일이나 폴더도 다 깃 오브젝트로 관리되었고, 관리를 위한 아이디가 있었군
-> 커밋이 스냅샷으로 갖고 있는 건 바로 트리! 커밋을 조작하는 건 바로 깃의 자료구조(dag)를 조작하는 것을 말한다.
objects = map<string, object>
def store(object):
id = sha1(object) // hash function
objects[id] = object
def load(id): // object는 이 id값으로 구별된다.
return objects[id]
sha-1 해쉬값을 통해 나오는 값은 인간이 읽기 힘든 40여개의 16진수 문자열이기 때문에 references를 사용한다.
유명한 레퍼런스는 HEAD 되시겠다. 현재 위치를 가리키는 특수한 REFERENCE이다.
references = map<string, string>
def update_reference(name, id):
references[name] = id
def read_reference(name):
return references[name]
def load_reference(name_or_id):
if name_or_id in references:
return load(references[name_or_id])
else:
return load(name_or_id)
또 깃 명령어들은 모두 이 레퍼런스를 변경하거나 혹은 오브젝트의 데이터를 변경하는 일이다.
이게 큰 깨달음이었는데 예를 들어
난 git checkout <branch>가 익숙해지면 git checkout <revision>을 생각 못할 때가 있다.
branch도 reference이고 revision도 reference라는 것을 알면 덜 헷갈린다.
'CS' 카테고리의 다른 글
[오픈소스 컨트리뷰션 아카데미] Git 활용 및 DevOps / MLOps (0) | 2023.08.30 |
---|---|
서버와 클라이언트가 커넥션을 오랫동안 유지하는 방법 (0) | 2023.06.01 |
웹 브라우저에 URL을 입력하면 일어나는 일 (그림요약) (0) | 2023.05.30 |
formatting and rounding mode (0) | 2022.09.08 |
Merge & Rebase (0) | 2022.03.16 |