포스트

Git 스터디 노트 (1) 개념: 스냅샷, 세 영역, 브랜치

Git을 명령어가 아니라 모델부터 이해하기 위한 개념 정리입니다. 커밋이 diff가 아니라 스냅샷이라는 것, 분산 버전 관리의 의미, working/staging/repository 세 영역, 그리고 브랜치가 포인터일 뿐이라는 것까지 다룹니다.

Git 스터디 노트 (1) 개념: 스냅샷, 세 영역, 브랜치

Git을 명령어 암기가 아니라 밑에 깔린 모델로 이해하기 위한 시리즈입니다. 1편은 개념, 2편은 기본 명령어, 3편은 Pull Request, 4편은 CI/CD를 다룹니다.

왜 개념부터 잡는가

Git을 명령어 암기로 시작하면 금방 벽에 부딪힙니다. 명령어는 수십 개인데 밑에 깔린 모델을 모르면 각각이 무슨 일을 하는지 연결이 안 되기 때문입니다. resetrevert가 왜 다른지, pull을 했는데 왜 충돌이 나는지 같은 질문은 명령어 설명서를 아무리 읽어도 풀리지 않습니다. 밑에 깔린 두 개의 그림, 스냅샷과 세 영역을 잡으면 처음 보는 명령도 유추할 수 있습니다.

이 글에서는 명령어를 거의 쓰지 않고 모델만 다룹니다. 실제 명령어는 2편에서 이 모델 위에 얹습니다.

Git은 무엇을 저장하는가: diff가 아니라 스냅샷

흔한 오해와 달리 Git은 “바뀐 부분(diff)”을 저장하지 않습니다. 커밋 하나는 그 시점 프로젝트 전체의 스냅샷입니다. git log에서 보는 커밋 목록은 “변경 내역의 목록”이 아니라 “시점별 전체 사진첩”이고, diff는 두 사진을 비교해서 그때그때 계산해 보여주는 것입니다.

이 모델에서 Git의 성격이 대부분 나옵니다.

  • 어떤 커밋으로든 완전한 상태로 즉시 이동할 수 있습니다. 사진 한 장을 꺼내면 그 시점 전체가 복원됩니다.
  • 커밋은 부모 커밋을 가리키는 연결 리스트를 이룹니다. 각 커밋은 자기 부모가 누구인지 기억합니다.
  • 한 번 커밋된 내용은 사실상 사라지지 않습니다. 되돌리기가 무섭지 않은 이유이고, 자주 커밋하는 습관이 곧 백업 습관인 이유입니다.

분산 버전 관리: 이력이 통째로 내 컴퓨터에

Git은 분산(distributed) 버전 관리입니다. clone을 받는 순간 전체 이력이 내 컴퓨터에 통째로 복사됩니다. 그래서 커밋, 브랜치 생성, 이력 조회는 전부 네트워크 없이 로컬에서 일어납니다. 비행기 안에서도 커밋할 수 있고, 그 속도가 즉각적인 것도 이 때문입니다.

서버(GitHub)와 통신하는 것은 딱 세 계열뿐입니다. 내 커밋을 올리는 push, 원격의 변경을 받아만 오는 fetch, 받아서 합치는 pull입니다. 나머지는 전부 내 컴퓨터 안에서 끝납니다. “GitHub이 곧 Git”이라고 생각하면 헷갈리는데, GitHub은 여러 사람의 저장소가 만나는 중앙 약속 장소일 뿐이고 Git 자체는 각자의 로컬에서 완결됩니다.

세 영역 모델: Git 이해의 절반

Git의 거의 모든 명령은 세 영역 사이에서 파일을 옮기는 일입니다. 이 그림 하나가 Git 이해의 절반입니다.

1
2
working directory  --add-->  staging area  --commit-->  repository
   (작업 폴더)                (커밋 대기석)                (이력 보관소)
  • working directory: 내가 실제로 편집하는 파일들
  • staging area: “다음 커밋에 넣을 것”을 골라두는 대기석 (index라고도 부릅니다)
  • repository: 커밋(스냅샷)이 영구 보관되는 곳 (.git 폴더)

staging area가 왜 있는지가 처음엔 의아합니다. 답은 커밋을 편집 단위가 아니라 의미 단위로 만들기 위해서입니다. 세 파일을 고쳤어도 “버그 수정”에 해당하는 두 파일만 골라 커밋하고, “오타 수정”인 나머지 하나는 따로 커밋할 수 있습니다. 커밋 하나 = 의미 있는 변경 하나라는 원칙이 가능해지는 장치가 staging area입니다.

이 모델을 잡아두면 나중에 되돌리기 명령이 세 개인 이유도 자연스럽습니다. “어느 영역까지 되감을 것인가”의 차이일 뿐이기 때문입니다. 그 부분은 2편에서 다룹니다.

브랜치: 커밋을 가리키는 이름표 하나

브랜치는 커밋 사슬을 통째로 복사하는 게 아니라 특정 커밋을 가리키는 이름표 하나입니다. 파일 하나에 커밋 해시를 적어둔 것에 가깝습니다. 그래서 브랜치 생성은 즉각적이고 저장 공간도 거의 들지 않습니다. 새 실험, 새 기능마다 부담 없이 만들라고 있는 것입니다.

여기서 두 가지 개념이 따라옵니다.

  • HEAD: “지금 내가 어느 브랜치에 있는가”를 가리키는 포인터입니다. 브랜치를 옮긴다는 것은 HEAD를 다른 이름표로 옮기고, working directory를 그 시점 스냅샷으로 맞추는 일입니다.
  • merge와 충돌: 두 브랜치를 합칠 때 Git은 각자의 변경을 한데 모읍니다. 서로 다른 파일이나 다른 부분을 고쳤다면 자동으로 합쳐집니다. 두 브랜치가 같은 파일의 같은 부분을 다르게 고쳤을 때만 충돌(conflict)이 납니다.

충돌은 에러가 아니라 “둘 다 맞을 수 있으니 사람이 골라라”는 정상적인 질문입니다. 이 질문에 답하는 절차는 2편에서 실제로 다룹니다. 지금은 “브랜치는 포인터, 충돌은 같은 곳을 다르게 고쳤을 때만”이라는 두 문장만 기억하면 됩니다.

좋은 커밋이란 무엇인가

명령어보다 오래가는 것은 커밋을 만드는 기준입니다. 이건 도구가 아니라 습관이라 개념 편에서 짚어둡니다.

  • 하나의 커밋 = 하나의 의미. “모델 수정 + 리팩토링 + 오타”를 한 커밋에 넣으면 나중에 그중 하나만 되돌릴 수 없습니다. 스냅샷 모델에서 되돌리기의 최소 단위는 커밋이기 때문입니다.
  • 메시지는 “무엇을”이 아니라 “왜”. 무엇이 바뀌었는지는 diff가 보여줍니다. 메시지에는 diff가 말해주지 않는 의도를 남깁니다. “lr 0.001로 변경”보다 “발산 방지를 위해 lr 인하”가 좋은 메시지입니다.
  • 동작하는 상태에서 커밋. 커밋은 “언제든 돌아갈 수 있는 지점”인데, 깨진 상태의 스냅샷은 돌아갈 가치가 없습니다.

이 기준은 혼자 작업할 때는 사소해 보이지만, 3편에서 다룰 협업과 코드 리뷰로 가면 그대로 팀의 생산성이 됩니다. 리뷰어가 읽어야 하는 것이 결국 커밋이기 때문입니다.

정리

개념한 줄 요약
스냅샷 모델커밋은 diff가 아니라 그 시점 전체 사진. diff는 두 사진의 비교
분산clone하면 전체 이력이 로컬에. 서버 통신은 push/fetch/pull뿐
세 영역working, staging, repository. staging은 커밋을 의미 단위로 만드는 장치
브랜치특정 커밋을 가리키는 이름표. 생성이 즉각적이고 공짜에 가깝다
충돌같은 파일의 같은 부분을 다르게 고쳤을 때만. 에러가 아니라 질문
좋은 커밋의미 단위 하나씩, 메시지엔 “왜”, 동작하는 상태에서

명령어보다 오래가는 것은 모델입니다. 스냅샷과 세 영역, 이 두 그림만 잡혀 있으면 처음 보는 명령도 “어느 영역에서 어느 영역으로 무엇을 옮기는가”로 유추할 수 있습니다.

다음 글

개념이 잡혔으니 2편에서는 이 모델 위에 실제 명령어를 얹습니다. 기본 사이클(status, add, commit), 브랜치와 충돌 해결, 원격, 그리고 상황별 되돌리기까지 다룹니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.