Git 워크플로우 완벽 가이드 | 브랜치 전략부터 협업까지
이 글의 핵심
Git 브랜치 전략, 커밋 컨벤션, PR 리뷰, 충돌 해결 등 실무 Git 워크플로우를 상세히 설명합니다. Git Flow, GitHub Flow, Trunk-Based Development를 비교하고 팀 규모별 권장 전략을 제시합니다.
들어가며: Git은 혼자 쓰기엔 쉬운데, 팀이면 냄새가 남
혼자 개발할 땐 커밋이 내 일기장이잖아요. 누가 뭐라고 하겠어요. 근데 팀이면 갑자기 main이 땅따먹기 게임이 됩니다.
이 글에서는 브랜치 전략, 커밋 습관, PR, 그리고 충돌—특히 그 지옥—을 내 기준으로 풀어볼게요. 백과사전처럼 딱딱하게 정리하려다가, 그냥 내가 터지고 나서 남는 생각 위주로 씁니다.
이런 것들 다룸:
- Git Flow / GitHub Flow / Trunk-Based (비교는 표 말고 말로)
- 커밋 메시지 (Conventional 쓰는 쪽)
- PR 습관
- merge vs rebase, 내 생각
- 머지 충돌 망해버린 썰 (필수)
1) 내가 겪은 머지 충돌 호러 스토리 (금요일 18시)
솔직히 말하면, Git 문서는 충돌이 “발생할 수 있다” 정도로만 말해줍니다. 현장은 달라요.
예전에 정산 모듈을 리팩터링하던 팀이 있었는데, 나는 feature/invoice-v2에 있었고 동료는 hotfix/tax-label이었어요. 둘 다 같은 1,800줄짜리 InvoiceMapper.ts를 만졌습니다.
금요일 저녁, 나는 “어차피 리베이스로 깔끔하게” 하겠다고 git rebase main을 때렸고, 동시에 CI는 다른 브랜치에서 merge 흐름으로 돌고 있었죠. 충돌 마커가 40군데가 넘게 박힌 거예요. <<<<<<<가 스크롤에 지배를 했어요.
제일 아찔했던 건 이거였어요. 내가 반쯤 자동 머지 믿고 ours / theirs를 파일 단위로 훑다가, 이미 release 브랜치에 박힌 금액 반올림 로직을 날려먹을 뻔한 순간. 다행히 로컬에서 테스트가 터져서 멈췄는데, 그날 한 시간 동안 “내가 누구 브랜치를 죽인 거지”라는 생각만 했습니다. Jira 댓글로는 “충돌 해결 중” 밖에 못 썼어요.
교훈만 짧게 쓰면 이렇게예요.
- 같은 거대 파일을 같은 주간에 건드리면, Git이 아니라 일정/모듈 경계가 먼저 터진 겁니다.
rebase가 마법이 아님. 리베이스 = 커밋을 다시 쌓는 작업이라, 충돌을 “없애”주지 않아요. 다시 싸웁니다.merge는 역사에 기록이 남고,rebase는 역사를 다시 쓰는 쪽. 둘 다 괜찮은데, 팀 룰이 없으면 둘 다 독이 됩니다.
2) 브랜치 전략, 표 없이 느낌으로
Git Flow
빈센트 드리센이 유명해진 그 모델. main + develop + feature + release + hotfix — 브랜치 이름만 봐도 “우리 팀 꽤 큼” 느낌 나죠.
이런 팀에 잘 맞아요. 릴리스 주기가 달력에 찍혀 있고, QA가 길고, v1.2.0이 실제로 의미가 있을 때.
답답한 점은 구조가 무거워서, 스타트업에서 이거 그대로 가져다 쓰면 둘 다 쉬는 develop 브랜치가 생기는 경우가 많아요(솔직히 봤음).
mermaid는 그대로 둡니다. 눈으로 흐름 보면 이해빠름.
gitGraph
commit
branch develop
checkout develop
commit
branch feature/login
checkout feature/login
commit
commit
checkout develop
merge feature/login
branch release/1.0
checkout release/1.0
commit
checkout main
merge release/1.0 tag: "v1.0"
checkout develop
merge release/1.0
워크플로우 자체는 예전과 비슷해요.
git checkout develop
git checkout -b feature/login
# ... 커밋 ...
git checkout develop
git merge feature/login
# release, tag, develop으로 되먹이기
내 체감: 큰 조직, 긴 주기, “언제 뭐가 나갔는지”가 돈이랑 맞물릴 때.
GitHub Flow
main에서 갈라졌다가 PR로 바로 붙이는 흐름. 작고 빠른 팀이 좋아해요. 배포가 main 머지랑 거의 같이 갈 때.
gitGraph
commit
branch feature/login
checkout feature/login
commit
commit
checkout main
merge feature/login tag: "deploy"
망하는 패턴도 알려드릴게요. “일단 main에 머지하고 나중에 배포” 팀이면, main이 반쯤 깨진 통합창고가 되기 쉬워요. 트렁크를 깨끗이 유지할 수 있을 때 이 전략이 제일 이쁩니다.
Trunk-Based
main에 아주 잠깐 갔다가 바로 PR. 브랜치가 숨쉬는 시간이 짧음. 이건 팀이 숙련돼 있고, 테스트/피쳐플래그/CI가 이미 뼈대가 있을 때 예쁘게 굴러가요.
나는 “우리 주니어 둘이서 트렁크만 닦자”는 건 비추입니다. 난이도가 은근 높아요.
세 개 비교, 표는 안 쓰고
- Git Flow — 복잡하지만 릴리스/핫픽스에 이름이 딱 붙음.
- GitHub Flow — 단순한데, CD 철학이 팀이랑 안 맞으면
main만 바쁨. - Trunk-Based — 가장 짧은 브랜치 수명, 대신 자동화·테스트가 없으면 연쇄 사고.
3) rebase vs merge, 내 생각은 이래
git merge: 공식 기록. “여기서 갈라졌다가, 여기서 합쳐졌다”가 그대로 남아요. 리뷰어가 “아 이 브랜치가 main이랑 언제 갈렸구나”보기 쉬움.
git rebase: 내 커밋 줄을 main 위에 다시 펴 바르기. 히스토리가 일자에 가깝게 보여서 읽기 좋을 때가 많아요. 대신, 이미 push한 걸 멋대로 리베이스했다가 강푸하면 팀 전체가 “어?” 합니다.
내 생각:
- 공유 브랜치(여러명이 push) — 나는 merge를 기본으로 둡니다. 다툼이 덜해요.
- 혼자 도는 feature 브랜치, PR 앞 —
rebase -i로 커밋 정리하는 건 찬성. 쓰레기 커밋(실수, wip)은 눈에 안 보이게 정리하려고. main에 rebase하고 싶다는 팀이면, 규칙이 먼저입니다. “push 전에만” 같은 걸 문서로 박아두고요.
싸우지 말고, 뭘 먼저 고를지는 이렇게 보면 돼요. 히스토리 읽는 재미(리베이스) vs 사실 기록(머지). 둘 다 틀렸다고는 안 해요. 나는 혼자 쓰는 커밋 꾸밈엔 rebase, 팀 머지 충돌 자주 나는 꼭지 땐 merge를 편애하는 편.
# main 최신 땡기고 나 혼자 정리
git fetch origin
git rebase -i origin/main
# (중간에 충돌 나면 고치고)
git rebase --continue
# 공유 브랜치, 나는 이쪽 선호
git fetch origin
git merge origin/main
4) Conventional Commits, 나는 이렇게 씀
형식은 뻔하죠.
<type>(<scope>): <subject>
feat, fix, docs… 나는 chore를 남용하지 말자는 주의예요(진짜 다 chore 됨).
예시는 똑같이 쓰는 게 나아요. 나중에 CHANGELOG 뽑을 때 살 붙어요.
git commit -m "feat: 로그인에 소셜 연동"
git commit -m "fix: 가격 표시 0원 버그"
커밋은 작게 — 나 스스로 “이 PR에 커밋 18개”면 창피해요. 스쿼시로 정리하든, rebase로 합치든, 리뷰어 시간이 내 비용이에요.
5) PR, 감정 빼고 (하지만 감정은 있음)
PR 템플릿은 팀이 싫어해도, 나는 “왜/뭘/어떻게 테스트” 세 줄은 넣는 편이에요. 나중에 장애난 걸 내 PR에서 찾는 날이 오거든요.
크기는 200~400줄 쯤? 이건 가이드일 뿐이고, 실제로는 “리뷰어가 30분 안에”가 기준이에요. 초장문 PR은 나도 미안해서 잘 쪼갬.
6) 충돌, “왜 생기냐”보다 “어떻게 덜 죽냐”
원인은 같은 파일, 같은 스팟, 다른 브랜치. mermaid 흐름은 이해하기 좋아요.
gitGraph
commit id: "A"
branch feature
checkout feature
commit id: "B (파일 수정)"
checkout main
commit id: "C (같은 파일 수정)"
checkout feature
merge main id: "충돌!"
기본은 status로 파일 보고, 마커 지우고, add하고 commit이죠.
git status
# 편집: <<<<<<< HEAD ... >>>>>>> 를 정리
git add file.txt
git commit
도구 — VS Code, JetBrains, git mergetool 쓰면 눈이 덜 아픔. 손가락으로만 하다가 한 번 지옥 가봤어요(위 호러).
덜 죽는 법 (진짜 실전)
- 자주
main이랑 맞추기 — 하루 한 번, 아침 루틴. - 작은 PR — 충돌 면적이 줄어듦.
- 파일 나누기 — 전 회사에서 “God 파일” 쪼갠 날, 충돌 티켓이 반으로 갔어요(개인적 체감).
git checkout main
git pull
git checkout my-feature
git merge main
# or rebase, 팀 룰 보고
7) 팀 규모, 내 기준 (표 아님)
1~3명 — GitHub Flow가 편해요. 말로 합의하면 되거든요.
4~10명 — GitHub Flow + 필요하면 release. 리뷰 룰, CI만 튼튼하면 됨.
10명 이상 — Git Flow 쪽으로 무게 중심이 가는 경우가 많아요(단, “형식만 Git Flow”는 오히려 독이에요).
나는 숫자보다 “릴리스를 어떤 단어로 약속하느냐”를 더 봅니다. 숫자는 대충.
8) 끝맺음, 그리고 다음에 읽을 것
핵심만 다시 말하면, Git은 기술이 반, 팀의 약속이 반이에요. 브랜치 전략도, merge/rebase도, 문서에 한 줄이 있으면 싸움이 줄어요.
팀 사이즈 요약(텍스트로):
- 작음 → GitHub Flow 느낌, 빠른 PR.
- 중간 → 리뷰+릴리스 한 스푼.
- 큼 → 엄격한 흐름, 그러나 과한 Git Flow는 삼가.
다음으로 CI 붙이고 싶을 때는 예전에 써둔 글도 같이 봐요(링크는 그대로 둡니다).
밖에서 읽을 거:
부록: 운영 느낌으로만 짚는 체크 (표 말고)
관측 — 상관 ID, p95, 타임아웃이 대시보드에 보이냐.
안전 — 권한/비밀/로그가 경로마다 끊기지 않냐.
신뢰 — 재시도는 멱등에만, 서킷/백오프는 있냐.
배포 — 롤백 룬북, 카나리, 마이그레이션이 말로 설명되냐.
증상 → 내가 하는 순서 (표 대신):
- 간헐 터짐 — 최소 재현, 트레이스로 원인 팀 쪼개기.
- 느려짐 — 프로파일 먼저, N+1·락 의심.
- 메모리 — 누수(구독, 캐시 무한) vs 스파이크.
- CI만 실패 — env, lockfile, 이미지 버전 diff.
- 설정 엇갈림 — 프로필, 시크릿, 기본값.
배포 전엔 git add → git commit → git push → npm run deploy 순으로 가는 팀도 있어요(우리 쪽 루틴일 뿐이에요).
FAQ (캐주얼 버전)
Q. 이걸 언제 써먹냐?
A. 협업 할 때, PR 할 때, 충돌 났을 때, “누가 rebase 쳤냐” 싸울 때.
Q. 먼저 뭐 읽지?
A. 머지 충돌 실전 케이스부터 가도 됨. 심정이 비슷할 거야.
Q. 더 파고들려면?
A. 고급 Git 쪽, 그리고 공식 git 문서가 제일 낫다(진짜).
같이 보면 좋은 글
검색 키워드
Git, GitHub, 브랜치전략, GitFlow, 협업, 버전관리, PR, CodeReview