Developer Tools

Git 워크플로우 가이드: 브랜칭, 머징, 팀 협업

Git 브랜칭 전략, 커밋 모범 사례, 리베이스 vs. 머지, 그리고 전문 엔지니어링 팀이 사용하는 워크플로우를 마스터하세요.

8분 읽기

화면의 코드를 보고 있는 개발자

Git은 모든 현대 소프트웨어 팀 워크플로우의 기반입니다. 그러나 많은 개발자들이 commit, push, pull만 사용하며, 협업을 원활하고 충돌 없이 만들어 주는 핵심 기능들을 활용하지 못하고 있습니다. 이 가이드는 전문 팀이 사용하는 브랜칭 전략, 커밋 관행, 그리고 일상적인 명령어를 다룹니다.

핵심 개념 모델

Git은 스냅샷(커밋)의 **방향성 비순환 그래프(directed acyclic graph)**입니다. 각 커밋은 부모 커밋을 가리킵니다. 브랜치는 단순히 커밋을 가리키는 이름 있는 포인터로, 가볍고 생성 비용이 거의 없습니다.

main:    A → B → C → D
feature:         C → E → F

브랜칭은 파일을 복사하지 않습니다 — 새로운 포인터를 만들 뿐입니다. 그래서 저장소 크기에 상관없이 브랜치 생성은 밀리초 단위로 완료됩니다.

브랜칭 전략

GitHub Flow (단순, 지속적 배포)

배포를 자주 하는 팀에 적합합니다:

  1. main은 항상 배포 가능한 상태 유지
  2. 모든 변경 사항에 대해 피처 브랜치 생성
  3. 리뷰 준비가 되면 pull request 오픈
  4. 승인 후 main에 머지
  5. 즉시 배포
git checkout -b feature/add-user-auth
# ... 변경 작업 ...
git push origin feature/add-user-auth
# PR 오픈 → 리뷰 → 머지 → 배포

Git Flow (구조적 릴리스)

버전 릴리스가 있는 제품(앱, 라이브러리)에 적합합니다:

  • main — 프로덕션 코드만
  • develop — 통합 브랜치
  • feature/* — 새 기능 (develop에서 분기)
  • release/* — 릴리스 준비 (develop에서 분기)
  • hotfix/* — 긴급 프로덕션 수정 (main에서 분기)

구조적이지만 오버헤드가 있습니다. 병렬 릴리스 관리가 실제로 필요한 경우가 아니라면 GitHub Flow를 사용하세요.

트렁크 기반 개발 (Trunk-Based Development)

개발자가 main에 직접 커밋하거나 하루 미만의 단기 브랜치를 사용합니다. 피처 플래그로 사용자에게 노출될 기능을 제어합니다. 강력한 CI/CD와 테스트 커버리지가 필요합니다. Google, Facebook 및 빠른 속도의 팀이 사용합니다.

좋은 커밋 메시지 작성하기

커밋 메시지는 미래의 자신(과 팀원들)에게 보내는 편지입니다. Conventional Commits 형식을 따르세요:

<type>(<scope>): <짧은 요약>

<선택적 본문 — 무엇을, 왜 했는지 (어떻게는 불필요)>

<선택적 푸터 — 브레이킹 체인지, 이슈 참조>

타입:

  • feat — 새 기능
  • fix — 버그 수정
  • docs — 문서만 변경
  • refactor — 버그 수정도 기능 추가도 아닌 코드 변경
  • test — 테스트 추가 또는 수정
  • chore — 빌드 프로세스, 의존성, 툴링

예시:

feat(auth): add JWT refresh token rotation

Implements sliding session windows using refresh token rotation.
Previous tokens are invalidated on use to detect theft.

Closes #142
fix(api): return 404 instead of 500 for missing user

The /users/:id endpoint was throwing an unhandled exception when
the user didn't exist. Now returns a proper 404 with error message.

경험 법칙: 커밋 메시지가 fix stuffWIP라면 팀원들에게 민폐입니다. 명확하게 작성하세요.

Merge vs. Rebase

Merge

git checkout main
git merge feature/my-feature

두 브랜치를 합치는 머지 커밋을 생성합니다. 전체 히스토리를 보존하며, 브랜치가 언제 분기되고 합쳐졌는지 정확히 확인할 수 있습니다.

A → B → C → M (머지 커밋)
         ↑   ↑
         E → F (feature)

머지 사용 시기: 장기 브랜치 통합, 히스토리에서 컨텍스트 보존.

Rebase

git checkout feature/my-feature
git rebase main

커밋을 대상 브랜치 위에 다시 적용합니다. 선형 히스토리를 생성하며, 마치 피처가 최신 main 위에서 개발된 것처럼 보입니다.

Before: A → B → C (main)
                 ↑
            D → E (feature, B에서 분기)

After:  A → B → C → D' → E' (C 위로 리베이스된 feature)

리베이스 사용 시기: PR 전 로컬 커밋 정리, 피처 브랜치를 최신 상태로 유지.

황금 규칙: 공유 브랜치에 이미 푸시된 커밋은 절대 리베이스하지 마세요. 리베이스는 히스토리를 다시 작성하므로 다른 사람의 로컬 브랜치가 깨집니다.

인터랙티브 리베이스: 히스토리 정리

PR을 열기 전에, 지저분한 작업 중 커밋들을 스쿼시하고 정리하세요:

git rebase -i HEAD~4   # 마지막 4개의 커밋을 인터랙티브하게 편집

인터랙티브 에디터의 옵션:

  • pick — 커밋 유지
  • squash — 이전 커밋과 합치고 메시지 결합
  • fixup — 이전 커밋과 합치고 메시지는 삭제
  • reword — 변경 사항은 유지하고 메시지만 편집
  • drop — 커밋 완전히 삭제

충돌 해결하기

두 브랜치가 같은 줄을 수정하면 충돌이 발생합니다. Git이 다음과 같이 표시합니다:

<<<<<<< HEAD (현재 브랜치)
const timeout = 5000;
=======
const timeout = 3000;
>>>>>>> feature/update-timeouts

파일을 올바른 상태로 편집(마커 제거)한 후 다음을 실행하세요:

git add src/config.ts
git merge --continue   # 또는 git rebase --continue

예방이 치료보다 낫습니다:

  • main에서 자주 풀하여 브랜치를 단기간으로 유지
  • 같은 파일 작업 시 팀원과 소통
  • PR을 작게 유지 — 큰 PR일수록 충돌이 많고 리뷰가 어려움

매일 사용하는 필수 명령어

# 새 피처 시작
git checkout -b feature/my-feature

# 특정 변경 사항만 스테이징 (파일 전체 아님)
git add -p

# 스테이징되지 않은 변경 사항 확인
git diff

# 스테이징된 변경 사항 확인
git diff --staged

# 마지막 커밋 수정 (푸시 전)
git commit --amend --no-edit

# 커밋되지 않은 작업 임시 저장
git stash
git stash pop

# 버그를 도입한 커밋 찾기 (이진 탐색)
git bisect start
git bisect bad              # 현재 커밋이 나쁨
git bisect good v1.2.0      # 마지막으로 알려진 정상 커밋

# 삭제된 브랜치 또는 잃어버린 커밋 복구
git reflog

# 브랜치의 시각적 그래프 보기
git log --oneline --graph --all

Pull request 모범 사례

좋은 PR의 조건:

  • 한 가지만 수행 — 리뷰어가 전체 변경 사항을 파악할 수 있음
  • 명확한 설명 — 무엇이 변경되었는지, 왜, 어떻게 테스트할지
  • 작은 크기 — 대략적인 기준으로 diff 400줄 미만
  • CI 통과 — 빌드가 깨진 상태에서 리뷰 요청 금지
  • 이슈 연결Closes #42는 머지 시 이슈 자동 닫기

코드 변경과 함께 문서를 작성할 때는 README Generator를 활용해 보세요.

.gitignore 필수 항목

.gitignore에 항상 추가하세요:

# 환경 변수
.env
.env.local
.env.*.local

# 의존성
node_modules/
vendor/

# 빌드 출력
dist/
build/
.next/

# OS 파일
.DS_Store
Thumbs.db

# 에디터 파일
.vscode/settings.json
.idea/
*.swp

프로젝트별 .gitignoregitignore.io에서 생성하세요 — 수백 가지 언어와 도구를 지원합니다.

Git 숙련도는 시간이 지날수록 쌓입니다. 개념 모델을 이해하고 좋은 커밋 습관을 기르면, 팀의 협업이 눈에 띄게 원활해질 것입니다.