한 줄 요약
Pro Git 2판에서 브랜치(3.1·3.2·3.6)·리모트(2.5)·스태시(7.3)·리셋(7.7)·내부구조(10.2·10.3) 여덟 개 장을 한 파일로 묶은 자료로, 이번 Git 흡수분의 본체에 해당한다.
핵심 내용
- 커밋 객체의 정체(3.1) — 커밋은 스테이징한 내용의 스냅샷을 가리키는 포인터에 작성자·메시지, 그리고 바로 앞 커밋(부모)에 대한 포인터를 담은 객체다. 최초 커밋은 부모가 0개, 보통 커밋은 1개, 머지로 생긴 커밋은 2개 이상이다.
- 브랜치는 41바이트다(3.1) — 브랜치는 커밋 하나를 가리키는 가벼운 이동식 포인터이고, 실제로는 40자 SHA-1과 줄바꿈 하나가 든 파일이다. 그래서 만들고 지우는 비용이 사실상 없다. HEAD는 "지금 어느 브랜치에 있는지"를 가리키는 특별한 포인터다.
- fast-forward vs 3-way merge(3.2) — 합치려는 커밋이 현재 커밋의 역사를 따라가면 닿는 자리에 있으면 포인터만 앞으로 옮긴다(fast-forward). 역사가 갈라졌으면 두 브랜치 끝과 공통 조상 셋을 써서 3-way merge를 하고, 부모가 둘인 머지 커밋을 새로 만든다.
- 충돌(3.2) — 같은 파일의 같은 부분을 양쪽에서 다르게 고치면 Git은 머지 커밋을 만들지 않고 멈춘다. 충돌 표식(
<<<<<<<,=======,>>>>>>>)을 파일에 넣어 두고, 사람이 고친 뒤git add로 해결 표시를 하면 그때 커밋한다. - rebase가 하는 일(3.6) — 두 브랜치의 공통 조상으로 가서, 현재 브랜치 각 커밋이 만든 diff를 뽑아 임시 파일에 저장하고, 대상 브랜치와 같은 커밋으로 리셋한 뒤, 그 변경들을 차례로 다시 적용한다. 결과 스냅샷은 머지와 같고 역사 모양만 다르다.
- rebase의 황금률(3.6) — "저장소 밖에 나가 있고 남이 그 위에 작업했을 수 있는 커밋은 rebase 하지 않는다." 이미 push 한 커밋을 고쳐 다시 올리면 협업자들이 같은 작업을 다시 머지해야 한다.
- 리모트와 원격 추적 브랜치(2.5) — clone 하면 그 서버가
origin이라는 이름으로 자동 등록된다.git fetch는 데이터를 내려받기만 하고 내 작업에 자동으로 합치거나 지금 보고 있는 것을 바꾸지 않는다. push는 내가 clone 한 뒤 남이 먼저 올렸으면 거절된다. - 세 트리(7.7) — Git은 HEAD(마지막 커밋 스냅샷, 다음 커밋의 부모)·인덱스(다음 커밋 후보 스냅샷)·작업 디렉터리(모래밭) 세 묶음을 다룬다.
reset은 이 셋을 정해진 순서로 덮는다. - 객체 4종과 참조(10.2·10.3) — Git은 content-addressable 키-값 저장소다. 블롭(파일 내용)·트리(디렉터리)·커밋·태그 객체가 있고,
refs/heads/·refs/tags/·refs/remotes/아래 파일이 각각 브랜치·태그·원격 추적 브랜치다..git/HEAD는 보통ref: refs/heads/master처럼 다른 참조를 가리키는 심볼릭 참조다.
주요 주장 / 데이터
reset의 3단계 — ① HEAD가 가리키는 브랜치를 옮긴다(--soft면 여기서 멈춤) → ② 인덱스를 새 HEAD와 같게 만든다(--mixed, 기본값) → ③ 작업 디렉터리를 인덱스와 같게 만든다(--hard). 문서는--hard를 "reset을 위험하게 만드는 유일한 플래그이자 Git이 실제로 데이터를 파괴하는 몇 안 되는 경우"라고 못 박는다.- checkout과 reset의 두 가지 차이 — checkout은 작업 디렉터리에 대해 안전하다(덮어써서 날릴 파일이 있는지 확인한다). 그리고 reset은 HEAD가 가리키는 브랜치를 옮기지만 checkout은 HEAD 자체를 옮긴다.
- 객체 저장 방식 —
blob <바이트수>\0헤더를 내용 앞에 붙이고 그 전체의 SHA-1을 계산한 뒤 zlib으로 압축해.git/objects/앞2자/나머지38자에 쓴다. 문서가 Ruby로 손수 재현해git hash-object결과와 같음을 보여 준다. - 태그 객체는 네 번째 객체 유형이다 — lightweight 태그는 움직이지 않는 참조일 뿐이지만, annotated 태그는 태거·날짜·메시지·포인터를 담은 진짜 객체가 하나 더 생긴다. 커밋이 아닌 객체에도 태그를 달 수 있다.
- 원격 추적 브랜치는 읽기 전용이다 —
refs/remotes/아래 참조는 "마지막으로 통신했을 때 그 서버의 브랜치가 어디였는지"를 적어 둔 책갈피다. checkout 할 수는 있어도 커밋으로 갱신되지는 않는다. - stash(7.3) — 작업 디렉터리의 지저분한 상태(수정된 추적 파일과 스테이징된 변경)를 스택에 얹어 두고 작업 디렉터리를 깨끗하게 되돌린다. 다른 브랜치에서도 다시 꺼내 적용할 수 있고,
apply는 스택에 남기고pop은 적용 후 바로 버린다. - 역사를 보는 두 관점(3.6) — 문서는 rebase 논쟁에서 한쪽 편을 들지 않는다. "역사는 실제로 일어난 일의 기록"이라는 입장과 "역사는 프로젝트가 만들어진 이야기이므로 초고를 그대로 출판할 필요는 없다"는 입장을 나란히 적고, 결정은 팀과 프로젝트마다 다르다고 맺는다.
외부 검증 (2026-09-22, 웹)
- "Git의 기본 브랜치 이름은 master다"(3.1)는 지금도 반만 맞다. Git 2.28(2020-07)이
init.defaultBranch설정을 도입해 새 저장소의 첫 브랜치 이름을 바꿀 수 있게 했고, 설정을 비워 두면 하위 호환을 위해 여전히 master가 된다 — https://changelog.com/news/git-228-brings-initdefaultbranch-1O3p . 위키 본문에는 이 절의 다른 사실(브랜치는 커밋을 가리키는 포인터)만 옮기고 기본 이름은 인용하지 않았다.
출처 정보
- 저자/발행처: Scott Chacon, Ben Straub — Pro Git 2nd ed. (Apress, CC BY-NC-SA 3.0)
- 수집일: 2026-09-22
- URL: https://git-scm.com/book/en/v2 (3.1 Branches in a Nutshell / 3.2 Basic Branching and Merging / 3.6 Rebasing / 2.5 Working with Remotes / 7.3 Stashing and Cleaning / 7.7 Reset Demystified / 10.2 Git Objects / 10.3 Git References)
- 범위: 위 8개 장의 본문 전체를 한 파일로 묶었다. 원문 그림은 캡션만 남고 이미지 자체는 수집되지 않아, 그림에만 담긴 정보는 인용하지 않았다.