Pro Git 읽기 (1)
회사에서 매주 금요일마다 Pro Git 책으로 스터디를 하고 있다. 입사 즈음에 CTO님이 제일 먼저 git을 공부해보면 좋겠다고 했는데, 다른 분들과 같이 공부를 해나갈 수 있어 다행이다.
사실 git은 이미 계속 사용해오고 있었다. 이력서에도 git을 사용 가능 기술 중 하나로 적어놓기까지 했다. 하지만 혼자서 commit을 저장하는 정도로만 썼기 때문에 아직 안써본 기능이 훨씬 더 많다. 또, git이라는 프로그램 그 자체에 대한 이해도 떨어지는 편이다.
그런 내게, Pro Git은 정말 재밌는 책이다. 오해하고 있던 점에 대해 새로운 사실을 알려주고 있고, 잘 몰랐던 내용까지 보여주고 있다. 인터넷에 무료로 한글 번역본이 올라와 있어서 ('Pro Git(PDF)') 나는 따로 구입하지 않고 이 PDF로 읽고 있다.
diff와 snapshot
git이 나오기 전 다른 버전관리 프로그램은 대부분 파일의 변화(diff 혹은 델타)를 시간순으로 관리한다. 말하자면, 파일이 처음 생성된 시점에서부터의 변경사항을 하나씩 추적해나가야 한다는 의미다.
git은 다르다. 데이터를 파일 시스템 스냅샷의 연속으로 취급한다. commit을 하면 그 시점의 스냅샷이 저장된다. diff는 그 커밋과 부모의 커밋을 비교해서 얻는다. 파일이 달라지지 않은 경우에는 파일을 새로 저장하는 것이 아니고 이전 상태의 파일에 대한 링크만 저장해 둔다. 이런 차이가 git을 다른 버전관리 프로그램보다 훨씬 더 빠르게 만든다.
다만 한 가지 궁금한 점은, 과연 diff만을 저장하는 방식과 스냅샷을 통째로 저장하는 방식 중 후자가 월등히 우월하다고 할 수 있는가 하는 점이었다. 가령 1kb짜리 파일의 일부를 열 번 수정한 경우, 해당 스냅샷을 열 번 저장한다면 결국 10kb가 될텐데, 그렇다면 diff를 저장하는 것보다 훨씬 낭비되는 것 아닌가 하는 점이었다. 추가적으로 찾아보니, git은 처음에는 스냅샷으로 저장하다가 적절한 시점에 garbage collection을 실행한다고 한다. 그러니까 마지막 버전의 파일을 통째로 저장하고 이전 버전은 diff만을 저장한다는 것이다.
이 내용은 Pro Git 뒷부분을 좀 더 읽으면서 공부해볼 생각. 찾아봤던 블로그는 여기다.
첫 번째 파일의 스냅샷과 이후의 변경사항을 diff로 저장하는 것과, 마지막 최근 파일의 스냅샷과 이전의 변경사항을 diff로 저장하는 것 사이에는 큰 사고방식의 전환이 필요했을 것 같다.
branch는 그저 포인터
git의 branch는 커밋과 커밋 사이를 이동할 수 있는 포인터 같은 것이다. 앞서 말한 대로 git이 가장 최신 버전의 커밋된 파일의 스냅샷을 가지고 있기 때문에 branch 또한 쉽게 만들었다가, 옮겼다가, 삭제하는 것이 가능하다.
실제로 commit을 하면, commit 객체가 생성된다. 여기에는 데이터 스냅샷을 가리키고 있는 포인터, 저자나 커밋 메시지 등 메타 데이터, 이전 커밋에 대한 포인터 등이 포함되어 있다. 사용하면서도 commit과 branch를 잘 구분하지 못했는데, 이제는 확실히 구분할 수 있을 것 같다.
fast-forward merge 와 3-way merge
branch를 생성하여 작업을 한 commit을 master 등 다른 branch로 옮겨야 하는 경우를 생각해 본다. branch 포인터가 merge 과정 없이 최신 커밋으로만 이동하면 되는 merge를 fast-forward merge라고 부른다. merge를 할 때 부모가 여러 개라 별도의 커밋이 만들어져야 하는 경우에는 merge 커밋이 생성되고, 이 과정을 3-way merge라 부른다.