ブランチ戦略の実習
한국어 원문으로 표시합니다.
목표
저장소 하나를 처음부터 만들어 병합 방식 세 가지(no-ff 머지, 빨리 감기, 체리픽)의 결과가 이력에 어떻게 다르게 남는지 눈으로 확인하고, 그 결과를 숫자로 세어 전략 비교표를 씁니다.
왜 중요한가
브랜치 전략 논쟁은 대개 취향 싸움으로 끝납니다. 그런데 결정을 내리는 진짜 질문은 하나입니다. 장애가 났을 때 이 저장소에서 원인 커밋을 어떻게 찾을 계획인가. --no-ff 머지는 "이 묶음이 언제 통합됐는지"를 남기고, 빨리 감기는 일직선 이력을 주는 대신 통합 시점을 지우며, 스쿼시 머지는 이분 탐색 해상도를 PR 크기로 고정시키고 Git 입장에서는 그 브랜치가 머지된 적이 없게 만듭니다. 이 차이는 설명을 읽어서가 아니라 git rev-list --min-parents=2 로 세어 봐야 몸에 남습니다.
단계
이 이미지에는 전역 git 신원이 설정돼 있지 않습니다. 새로 만드는 모든 저장소에서 git config user.email / git config user.name 을 로컬로 설정하지 않으면 커밋이 실패합니다.
/root/gitx1/repo에 저장소를 만듭니다. 현재 브랜치는main, 이 저장소에 로컬user.email과user.name이 설정돼 있어야 하며,README.md를 담은 커밋이 최소 1개 있어야 합니다.feature/login브랜치를 만들고 커밋 2개를 쌓습니다. 커밋 제목은 정확히login: form,login: validation이어야 하고, 브랜치에login.txt파일이 있어야 합니다.login:으로 시작하는 커밋은 정확히 2개여야 합니다.main으로 이동해feature/login을 머지 커밋이 남도록(부모가 둘인 커밋) 병합합니다. 병합 후main에login.txt가 있어야 합니다.main에서feature/quick브랜치를 만들어quick.txt를 추가하는 커밋 하나를 만듭니다. 제목은 정확히quick: typo입니다. 그리고main에서 빨리 감기로만 병합합니다. 이 커밋의 부모는 1개여야 하고,main의 머지 커밋 개수는 3단계에서 만든 1개 그대로여야 합니다.main의 현재 위치에 주석 있는 태그v1.0.0을 붙입니다. 태그 메시지는 비어 있으면 안 됩니다.v1.0.0지점에서release/1.0브랜치를 만들고hotfix.txt를 추가하는 커밋을 만듭니다. 제목은 정확히hotfix: null guard입니다. 그런 다음 같은 변경을main에도 반영합니다. 조건: 두 브랜치의hotfix.txt내용이 같을 것, 양쪽 모두hotfix: null guard커밋을 가질 것, 그러나 두 커밋의 해시는 서로 달라야 합니다.- 브랜치를 정리합니다.
feature/quick은 삭제하고,feature/login은 남기며, 새로feature/wip브랜치를 만들어main에 없는 커밋을 1개 이상 쌓아 둡니다(아직 병합하지 않은 상태여야 합니다). /root/gitx1/strategy.md를 씁니다. 반드시 포함할 것:merge_commits=—main의 머지 커밋 개수branches=— 이 저장소의 로컬 브랜치 개수tags=— 태그 개수- Git Flow / GitHub Flow / Trunk-Based 세 전략에 대한 설명
- 이 저장소가 어느 전략에 가까운지에 대한 판단 ('이 저장소', '우리', '현재' 중 한 표현이 들어가야 합니다)
참고
- 신원 설정:
git config user.email "you@lab.local"과git config user.name "Lab"을 저장소 안에서 실행합니다.--global은 쓰지 마세요. - 기본 브랜치 이름:
git init -b main을 쓰거나,git init후git symbolic-ref HEAD refs/heads/main으로 바꿉니다. - 숫자 세기: 머지 커밋은
git rev-list --min-parents=2 --count main, 브랜치는git branch --format='%(refname:short)' | grep -c ., 태그는git tag | grep -c .입니다. - 흔한 실수 1: 3단계에서 그냥
git merge를 쓰는 것. 갈라진 이력이 없으면 빨리 감기가 되어 머지 커밋이 생기지 않습니다. - 흔한 실수 2: 6단계에서
git merge release/1.0을 쓰는 것. 머지 커밋이 하나 더 생겨 4단계 채점이 깨집니다. 커밋 하나만 가져오는 명령을 쓰세요. - 커밋 제목은 대소문자와 공백까지 정확히 일치해야 합니다.
git log --format='%s'로 확인하세요.
저장소 만들고 신원 설정하기
/root/gitx1/repo 에 저장소를 만듭니다. 현재 브랜치는 main, 이 저장소에 로컬 user.email 과 user.name 이 설정돼 있어야 하며, README.md 를 담은 커밋이 최소 1개 있어야 합니다.
/root/gitx1/repo 에서 git init 을 하되 기본 브랜치 이름을 main 으로 만듭니다. 이 이미지에는 전역 git 신원이 없어서 user.email 과 user.name 을 이 저장소에 직접 설정하지 않으면 커밋 자체가 실패합니다.
기능 브랜치에 커밋 2개 쌓기
feature/login 브랜치를 만들고 커밋 2개를 쌓습니다. 커밋 제목은 정확히 login: form, login: validation 이어야 하고, 브랜치에 login.txt 파일이 있어야 합니다. login: 으로 시작하는 커밋은 정확히 2개여야 합니다.
feature/login 브랜치를 만들고 login.txt 를 두 번에 나눠 커밋합니다. 커밋 제목은 지시된 문자열과 정확히 같아야 하며, login: 으로 시작하는 커밋이 정확히 2개여야 합니다.
빨리 감기 없이 병합하기
main 으로 이동해 feature/login 을 머지 커밋이 남도록(부모가 둘인 커밋) 병합합니다. 병합 후 main 에 login.txt 가 있어야 합니다.
main 으로 옮겨 feature/login 을 병합하되, 부모가 둘인 커밋이 남도록 병합합니다. 그냥 merge 하면 빨리 감기가 되어 통합 기록이 사라집니다.
작은 수정은 빨리 감기로 올리기
main 에서 feature/quick 브랜치를 만들어 quick.txt 를 추가하는 커밋 하나를 만듭니다. 제목은 정확히 quick: typo 입니다. 그리고 main 에서 빨리 감기로만 병합합니다. 이 커밋의 부모는 1개여야 하고, main 의 머지 커밋 개수는 3단계에서 만든 1개 그대로여야 합니다.
feature/quick 을 만들어 quick.txt 를 커밋하고 main 에서 빨리 감기로만 병합합니다. 머지 커밋이 생기면 이 단계는 실패합니다. --ff-only 를 쓰면 조건이 안 맞을 때 아예 거부해 줍니다.
릴리스 태그 붙이기
main 의 현재 위치에 주석 있는 태그 v1.0.0 을 붙입니다. 태그 메시지는 비어 있으면 안 됩니다.
main 에 v1.0.0 태그를 붙입니다. 가벼운 태그는 그냥 포인터라 작성자와 메시지가 남지 않습니다. 태그 객체가 만들어지는 옵션을 쓰세요.
릴리스 브랜치 핫픽스를 main 으로 가져오기
v1.0.0 지점에서 release/1.0 브랜치를 만들고 hotfix.txt 를 추가하는 커밋을 만듭니다. 제목은 정확히 hotfix: null guard 입니다. 그런 다음 같은 변경을 main 에도 반영합니다. 조건: 두 브랜치의 hotfix.txt 내용이 같을 것, 양쪽 모두 hotfix: null guard 커밋을 가질 것, 그러나 두 커밋의 해시는 서로 달라야 합니다.
v1.0.0 에서 release/1.0 을 만들어 hotfix.txt 를 커밋한 뒤, 같은 변경을 main 에도 반영합니다. 브랜치를 통째로 병합하지 말고 그 커밋 하나만 가져오세요.
체리픽은 변경을 다시 적용해 새 커밋을 만듭니다 — 옮기는 것이 아닙니다. 다만 이 실습처럼 release/1.0 을 main 의 끝에서 바로 딴 경우에는 두 커밋의 부모가 같습니다. 그래서 git cherry-pick -x 를 쓰세요. 메시지에 (cherry picked from commit ...) 한 줄이 붙어 어디서 왔는지가 이력에 남고, 그 줄 덕분에 커밋 객체도 확실히 구분됩니다. 핫픽스를 여러 브랜치에 반영할 때 실무에서 권장되는 방식이 바로 이것입니다.
병합된 브랜치만 정리하기
브랜치를 정리합니다. feature/quick 은 삭제하고, feature/login 은 남기며, 새로 feature/wip 브랜치를 만들어 main 에 없는 커밋을 1개 이상 쌓아 둡니다(아직 병합하지 않은 상태여야 합니다).
이미 병합이 끝난 브랜치는 지우고, 아직 병합되지 않은 브랜치는 남깁니다. git branch --merged main 으로 안전하게 지울 수 있는 것을 먼저 확인하세요. -D 대신 -d 를 쓰면 실수로 미병합 브랜치를 지우는 사고를 막아 줍니다.
저장소 상태를 세어 전략 비교표 쓰기
/root/gitx1/strategy.md 를 씁니다. 반드시 포함할 것:
merge_commits=—main의 머지 커밋 개수branches=— 이 저장소의 로컬 브랜치 개수tags=— 태그 개수- Git Flow / GitHub Flow / Trunk-Based 세 전략에 대한 설명
- 이 저장소가 어느 전략에 가까운지에 대한 판단 ('이 저장소', '우리', '현재' 중 한 표현이 들어가야 합니다)
/root/gitx1/strategy.md 에 merge_commits= / branches= / tags= 세 줄을 실제 저장소에서 센 값으로 적고, 세 브랜치 전략을 비교한 뒤 이 저장소가 어디에 가까운지 판단을 씁니다. 숫자는 git 명령으로 세세요.