무엇인가
Git 은 Linus Torvalds 가 2005년 리눅스 커널 개발을 위해 만든 분산 버전 관리 시스템이다. 이전 세대 도구(CVS·Subversion)에서 브랜치는 비싸고 무서운 것이었다 — 디렉터리를 통째로 복제하고, 다시 합치는 일은 수작업 고행이었다. Git 의 설계가 뒤집은 것이 정확히 이 지점이다: 이력 전체는 커밋들의 방향 그래프(DAG)이고, 브랜치는 그 그래프 위의 커밋 하나를 가리키는 가벼운 포인터일 뿐이다. 만드는 비용이 0에 가깝기 때문에, "일단 갈라서 그려 보고 아니면 버린다"가 일상 동작이 됐다.
핵심 동작 어휘
| 용어 | 동작 | 뜻 |
|---|---|---|
| branch | 분기 | 확정 이력의 한 지점에서 대안 세계를 연다 — 전체 복제가 아니라 포인터 하나 |
| commit | 기록 | 브랜치 위에 변경(델타)을 쌓는다 |
| diff | 대조 | 두 세계의 차이만 본다 — 브랜치의 실체는 사실상 이 델타다 |
| merge | 승격 | 대안을 본류로 합친다. 3-way 머지는 공통 조상(merge-base)을 기준으로 양쪽 델타를 판정 |
| merge commit | 결절 | 부모를 둘 가진 커밋 — 갈라졌다 합쳐진 사실이 이력에 영구히 남는다 |
| rebase | 재기준 | 낡은 분기점을 버리고 최신 본류 위에 델타를 다시 얹는다 — 대신 원래 이력은 다시 쓰인다 |
| cherry-pick | 부분 승격 | 브랜치 전체가 아니라 커밋 하나만 골라 가져온다 |
여기서 우리에게 중요한 현상이 베이스 이동(base drift)이다. 브랜치를 딴 뒤에도 본류(main)는 계속 전진하므로, 대안이 딛고 선 전제(분기점)는 시간이 갈수록 낡는다. Git 은 이것을 "behind main by N commits"라는 숫자로, 그리고 머지 시점의 충돌(conflict)로 드러낸다 — 전제 노후화가 느낌이 아니라 측정값이다.
브랜치를 어떻게 운용할지의 규약이 브랜칭 모델이다. Vincent Driessen 의 git-flow(2010, "A successful Git branching model" — main·develop·feature·release·hotfix 의 역할 분리)가 한 시대를 지배했고, 이후 GitHub Flow(main + 짧은 feature 브랜치 + 풀 리퀘스트 리뷰)와 트렁크 기반 개발(브랜치 수명을 극단적으로 줄임)이 그 복잡성에 대한 반동으로 자리 잡았다. Driessen 스스로 2010년 글에 후일 주석을 달아, 지속 배포 환경이라면 더 단순한 흐름을 권한 것도 널리 알려진 일화다 — 갈림길 관리의 규약은 하나가 아니라, 변경의 빈도와 수명에 따라 고른다는 교훈이다.
우리 모델과의 접점
이 대응은 우리가 지금 새로 발견하는 것이 아니다 — worldview(방법론 세계관)가 이미 채택한 대응이다. 정본은 버전관리에 두고(W7), 버전·시안은 전체 복제가 아니라 델타로 두며(W8 베이스라인+델타), 여러 벌을 미리 검토한 뒤 사람이 하나를 결정해 승격하는 순환(§2)은 Git 의 운용 문법 그 자체다. 개념 모델 제7장은 같은 문법을 삶의 미래에 적용한 것이다:
| Git | 우리 모델 (제7장 갈림길) | 비고 |
|---|---|---|
| main — 확정 이력 | 확정 세계 — "과거는 하나" | 기본 뷰는 언제나 확정 세계 |
| branch | 시나리오 겹(overlay) | 렌즈가 아니라 세계의 선택 — 어느 렌즈에서든 토글 |
| diff (델타) | 겹이 담는 것 — 확정 세계 대비 차이만 | W8 과 동일한 절약 원리 |
| merge | 승격 — 순환 ③ 결정, 델타만 확정 세계로 | "같은 돈, 여러 벌의 임무"의 배정도 함께 탄다 |
| merge commit (두 부모) | 결정 마일스톤 — 가지 않은 길이 결절로 남음 | 결정도 인생의 사건이다 |
| 베이스 이동 · 충돌 | 전제 노후화 — Scenario.asOf 이후 확정 세계가 갱신됨 | 시나리오 플래닝의 전제 명시와 같은 자리 |
| rebase | 순환 ⑤ 재편 — 갱신된 현재에서 다시 그림 | 생각할 거리 2 |
| PR 리뷰 | 순환 ② 겹 검토 — 여정의 가지 겹침·여비의 곡선 N벌 | worldview 중력 B(사람이 결정)와 동형 |
대응만큼 어긋남도 분명하다:
- 분기 가능 영역. Git 은 이력의 어느 지점에서든 브랜치를 딸 수 있다. 우리는 시나리오를 미래에만 그린다(원칙 5) — 과거의 반사실은 겹이 아니라 성찰의 영역이다(반사실적 사고).
- 브랜치를 타지 않는 층. Git 에는 "브랜치가 못 건드리는 데이터"라는 구분이 없지만, 우리는 인물·장소·대상 마스터를 시나리오 밖에 둔다(원칙 6). 세계가 갈라져도 등장인물은 하나다.
- 기각 브랜치의 운명. Git 에서 머지되지 않은 브랜치를 지우면 그 커밋들은 결국 가비지 컬렉션으로 소멸한다. 우리는 반대로 기각 시나리오를 이력으로 보존한다 — 후회 연구가 말하는 "안 한 것"의 무게 때문이다.
생각할 거리
- 전제 노후화를 어떻게 보여 줄 것인가. Git 은 "behind by N"과 충돌 표시로 노후화를 측정값으로 만든다. 우리의
Scenario.asOf이후 확정 세계에 쌓인 변경을 겹 검토 화면(액션 A3)에 상시 숫자로 노출할 것인가, 아니면 같은 기간·같은 돈을 두고 겹이 확정 세계와 실제로 부딪힐 때만(충돌 시) 알릴 것인가. 상시 노출은 굿하트가 경고하는 대시보드화로 흐를 수 있다. - 재편은 rebase 인가 merge 인가. 순환 ⑤에서 시나리오의 전제를 갱신할 때, 낡은 저울질의 흔적을 다시 쓰는가(rebase — 이력이 깨끗해지지만 "그때 왜 그렇게 판단했나"가 사라짐), 갱신 자체를 기록으로 남기는가. 결정 저널의 "결정의 질과 결과의 질을 분리하라"는 격언은 전제 갱신 이력이 남아야 성립한다.
- 결정 마일스톤은 두 부모를 가져야 하는가. merge commit 이 결절이 되는 것은 부모 포인터 둘을 이력에 박기 때문이다. 우리의 결정 마일스톤이 채택 시나리오뿐 아니라 기각 시나리오로의 참조(Link)까지 들어야 "가지 않은 길이 타임라인의 결절로 남는다"가 데이터로 보장된다 — 참조(문장 사이)의 문법(제4장) 안에서 가능한지 검토할 것.
- 승격의 단위 — 통째인가 체리픽인가. 순환 ③ "델타만 확정 세계로 승격"은 시나리오 전체를 하나로 고르는 그림이지만, Git 의 cherry-pick 처럼 겹 안의 사건·배정 일부만 골라 승격하고 싶은 순간이 반드시 온다. 부분 승격을 허용하면 남은 겹의 정합성(잔여 델타의 전제)이 흔들린다 — 허용 범위를 미리 정할 것.
- 용어 레지스트리의 시험대. 원칙 8(개념은 고정, 부르는 말은 사용자의 것)에서 갈림길 어휘는 가장 어려운 사례다. "승격"·"겹" 같은 내부 언어가 화면에 새어 나가지 않는지,
terms.js의 기본 낱말을 Odyssey 계열("○○의 삶", "견주기", "고르기")로 두는 안을 검증할 것.
더 찾아보기
- Scott Chacon & Ben Straub, Pro Git (2nd ed.) — 공식 무료 공개: git-scm.com/book. 3장 "Git Branching"이 브랜치=포인터·머지·리베이스의 정본 설명이다.
- Vincent Driessen, "A successful Git branching model" (2010) — 검색:
nvie git branching model. 2020년 저자 주석까지 같이 읽을 것. - 검색:
GitHub Flow·trunk based development— 브랜치 수명을 줄이는 쪽으로의 진화 계보. - 같은 장의 이웃: 시나리오 플래닝(전제 명시의 방법론 원조), Odyssey Plans(사용자 언어 쪽 선례), 반사실적 사고 · 후회 연구(기각 이력 보존의 심리학). 1장의 이벤트 소싱 / 불변 로그는 "확정 이력은 append-only"라는 같은 뿌리의 다른 가지다.
내 생각
이 메모는 지도 페이지의 같은 항목과 공유되며, 이 기기(브라우저)에 저장됩니다.