← 홈페이지 5강 목록으로
🌳
EPISODE 01
branch · switch · HEAD · merge · GitHub Flow · 충돌 마커 · 수동 해결 · rebase vs merge · PR · 리뷰 · squash merge · PR 템플릿 · stash · reset · revert · cherry-pick · tag · reflog

브랜치 전략 · 충돌 해결 · GitHub Pull Request 리뷰 · Git 심화

독립적인 작업 흐름을 만드는 브랜치, switch/checkout, HEAD 포인터, Fast-forward와 3-way merge의 차이, 그리고 단순한 GitHub Flow 워크플로를 익힙니다. Merge conflict 발생 원리(같은 파일 같은 위치 다른 수정), 충돌 마커 읽기, 5단계 해결 절차, 그리고 rebase와 merge의 차이를 익힙니다. PR의 역할, 좋은 PR 작성 요령(제목·본문 구성), 리뷰 타입(comment/approve/request changes), squash merge vs merge commit, 그리고 PR 템플릿 자동화를 익힙니다. 임시 저장(stash), reset의 3가지 모드, 안전한 revert, 특정 커밋만 가져오는 cherry-pick, 버전 태그, 그리고 잃어버린 커밋을 복구하는 reflog까지.

GitbranchmergeGitHub FlowconflictrebaseGitHubPull Requestcode reviewstashresetreflog
소요 시간
⏱ 45분 + 45분 + 45분 + 60분
난이도
📊 중급
선수 조건
🎯 react-08
결과물
feature 브랜치 → PR → merge → 삭제 사이클 체화 / 충돌이 나도 당황하지 않고 해결 / 팀에서 통할 수 있는 깔끔한 PR 작성과 리뷰 / 고급 Git 명령으로 실수와 변경을 자유자재로 다룸

이 강의에서 배우는 것

  • 1브랜치의 개념과 사용 이유를 설명한다
  • 2switch -c / branch -d 같은 핵심 명령어를 사용한다
  • 3Fast-forward와 3-way merge의 차이를 안다
  • 4GitHub Flow의 규칙(main 항상 배포 가능)을 안다
  • 5충돌이 나는 조건(같은 파일, 같은 위치, 다른 수정)을 안다
  • 6<<<<<<< / ======= / >>>>>>> 마커를 읽는다
  • 7충돌 해결 5단계를 따른다
  • 8rebase와 merge의 차이와 공유 브랜치 rebase 금지 원칙을 안다
  • 9PR의 협업 가치(검증·공유·기록)를 안다
  • 10좋은 PR 제목·본문을 작성한다
  • 11comment / approve / request changes를 적절히 사용한다
  • 12squash merge 와 merge commit을 상황에 맞게 선택한다
  • 13PR 템플릿을 만들어 팀 표준을 만든다
  • 14stash로 작업을 임시 저장하고 복원한다
  • 15reset --soft/--mixed/--hard 의 차이를 안다
  • 16공개된 커밋은 reset 대신 revert를 사용한다
  • 17cherry-pick으로 특정 커밋만 가져온다
  • 18tag로 릴리즈 버전을 표시한다
  • 19reflog로 잃어버린 커밋을 복구한다

브랜치 전략

독립적인 작업 흐름을 만드는 브랜치, switch/checkout, HEAD 포인터, Fast-forward와 3-way merge의 차이, 그리고 단순한 GitHub Flow 워크플로를 익힙니다.

1. 브랜치란

text
main:    A --- B --- C
                      \
feature/login:         D --- E

feature/login 에서 D, E를 만들어도 main은 C에 그대로 있습니다.

2. 핵심 명령어

bash
git branch                    # 현재 브랜치 목록
git branch -a                 # 원격 포함

git branch feature/login      # 새 브랜치 생성
git switch feature/login      # 이동 (Git 2.23+)
git switch -c feature/login   # 생성 + 이동

# 구버전
git checkout feature/login
git checkout -b feature/login

git branch -d feature/login   # 병합된 것만 삭제
git branch -D feature/login   # 강제 삭제

3. HEAD

bash
cat .git/HEAD
# ref: refs/heads/main

git switch feature/login
cat .git/HEAD
# ref: refs/heads/feature/login

4. Fast-forward Merge

text
병합 전:
main:      A --- B
                  \
feature:           C --- D

병합 후 (FF — 단순히 포인터 이동):
main:      A --- B --- C --- D
bash
git switch main
git merge feature/login
git branch -d feature/login

5. 3-way Merge

text
병합 전:
main:    A --- B --- C
                \
feature:         D --- E

병합 후 (병합 커밋 M 생성):
main:    A --- B --- C ------- M
                \           /
feature:         D --- E ---

6. Feature 브랜치 워크플로

bash
git switch main
git switch -c feature/login

# 작업 + 커밋
git add login.js
git commit -m "feat: 로그인 기능 추가"

# main에 병합
git switch main
git merge feature/login
git branch -d feature/login

7. GitHub Flow

text
main (항상 배포 가능)
  ↓ switch -c
feature/기능명
  ↓ 작업 + 커밋 + push
  ↓ Pull Request
  ↓ 코드 리뷰
  ↓ merge → main
  ↓ 배포
  • main은 항상 배포 가능한 상태를 유지
  • 새 작업은 무조건 브랜치에서
  • 코드 리뷰(PR)를 거쳐야만 main에 병합
bash
git log --oneline --graph --all

충돌 해결 (Merge Conflict)

Merge conflict 발생 원리(같은 파일 같은 위치 다른 수정), 충돌 마커 읽기, 5단계 해결 절차, 그리고 rebase와 merge의 차이를 익힙니다.

1. 충돌 발생 원인

text
공통 조상(A):
  button { color: blue; }

main(B):                     feature(C):
  button { color: red; }       button { color: green; }

→ Git이 판단 불가 → 충돌!
  • 다른 파일 수정 → 자동 병합
  • 같은 파일, 다른 위치 → 자동 병합
  • 같은 파일, 같은 위치 다르게 수정 → 충돌

2. 충돌 마커

text
<<<<<<< HEAD          ← 현재 브랜치 시작
button { color: red; }
=======               ← 구분선
button { color: green; }
>>>>>>> feature/login  ← 병합하려는 브랜치

3. 해결 절차

bash
# 1. 충돌 발생 확인
git merge feature/login
# CONFLICT (content): Merge conflict in style.css

# 2. 어떤 파일이 충돌
git status
# both modified: style.css

# 3. 파일 열어서 마커 제거 + 원하는 내용으로 편집

# 4. 스테이징
git add style.css

# 5. 병합 커밋
git commit

# 중간에 병합을 취소
git merge --abort

4. rebase vs merge

merge — 병합 커밋으로

text
Before:  A---B---C (main)
               \
                D---E (feature)

After (merge):
         A---B---C---M (main, M: 병합 커밋)
               \   /
                D-E

rebase — 선형 히스토리

text
Before:  A---B---C (main)
               \
                D---E (feature)

After (rebase feature onto main):
         A---B---C---D'---E' (feature)
bash
git switch feature/login
git rebase main           # main 위에 feature 커밋들을 재적용

git switch main
git merge feature/login   # 이제 Fast-forward!
⚠️

rebase는 혼자 사용하는 로컬 브랜치에만! 팀원과 공유된 브랜치를 rebase하면 다른 팀원의 히스토리가 엉킵니다.

5. 그래프로 시각화

bash
git log --oneline --graph --all

# *   abc1234 (HEAD -> main) Merge branch 'feature/login'
# |\
# | * def5678 (feature/login) feat: 로그인 검증 추가
# | * ghi9012 feat: 로그인 페이지 추가
# * | jkl3456 feat: 소개 페이지 추가
# |/
# * mno7890 init

GitHub Pull Request 리뷰

PR의 역할, 좋은 PR 작성 요령(제목·본문 구성), 리뷰 타입(comment/approve/request changes), squash merge vs merge commit, 그리고 PR 템플릿 자동화를 익힙니다.

1. PR이란

text
1. feature 브랜치에서 작업
2. push
3. PR 생성 — "이 변경사항을 main에 병합해주세요"
4. 팀원이 코드 리뷰
5. 승인 후 병합
  • 코드 품질 검증 (버그 사전 발견)
  • 지식 공유 (다른 팀원이 변경사항 파악)
  • 히스토리 추적 (왜 이렇게 변경했는지)

2. 좋은 PR 제목

text
# ✅
feat: 로그인 페이지 UI 구현
fix: 모바일에서 네비게이션 버튼 클릭 안 되는 문제 수정
refactor: UserCard 컴포넌트 단일 책임 원칙 적용

# ❌
수정함
작업완료
fix

3. PR 본문 구성

markdown
## 변경 내용 (What)
- 로그인 페이지 HTML/CSS 추가
- 이메일 형식 검증 로직 구현

## 변경 이유 (Why)
기존에 로그인 기능이 없어 모든 사용자가 관리자 페이지에 접근 가능

## 스크린샷
![로그인 페이지](screenshot.png)

## 테스트 방법
1. `npm start`로 앱 실행
2. `/login`으로 이동
3. 잘못된 이메일 형식 입력 시 오류 메시지 확인

## 관련 이슈
Closes #42

4. 리뷰 타입

타입설명
Comment일반 의견 — 병합을 막지 않음
Approve변경사항 승인 — 병합 가능
Request Changes수정 요청 — 해결 전까지 병합 불가

좋은 / 나쁜 코멘트

text
# ✅
"이 함수가 null을 반환할 수 있는데, 호출 지점에서 처리가 없네요.
Optional chaining(user?.name)을 사용하거나 기본값을 지정하면 어떨까요?"

# ❌
"이거 왜 이렇게 했어요?"
"코드 이상함"

5. squash merge vs merge commit

text
merge commit (기본)
main: A --- B --- M
                /
feature: C - D - E

squash merge — 모든 커밋이 하나로 합쳐짐
main: A --- B --- S
bash
git merge --squash feature/login
git commit -m "feat: 로그인 기능 구현 (#PR번호)"
  • merge commit: 각 커밋이 의미 있고, 기여자별 히스토리 보존이 중요할 때
  • squash merge: WIP 커밋이 많아 main 히스토리를 깔끔하게 유지하고 싶을 때

6. PR 템플릿

저장소 루트에 .github/pull_request_template.md 파일이 있으면 PR 생성 시 자동으로 본문에 채워집니다.

markdown
## Summary
-
-

## Type of Change
- [ ] 새 기능 (feat)
- [ ] 버그 수정 (fix)
- [ ] 리팩토링 (refactor)
- [ ] 문서 수정 (docs)

## Test
- [ ] 로컬에서 빌드 성공
- [ ] 관련 기능 수동 테스트

## Screenshots

## Related Issue
<!-- Closes #42 -->

Git 심화

임시 저장(stash), reset의 3가지 모드, 안전한 revert, 특정 커밋만 가져오는 cherry-pick, 버전 태그, 그리고 잃어버린 커밋을 복구하는 reflog까지.

1. git stash

bash
git stash
git stash push -m "로그인 폼 절반 완성"

git stash list
# stash@{0}: On main: 로그인 폼 절반 완성

git stash pop                # 가장 최근 + 목록에서 제거
git stash apply stash@{1}    # 특정 stash, 목록 유지
git stash drop stash@{0}
git stash clear

2. git reset 3가지 모드

옵션커밋스테이징작업 디렉토리
--soft취소유지유지
--mixed취소취소유지
--hard취소취소취소
bash
# 커밋만 취소, 변경은 스테이징 상태로 유지
git reset --soft HEAD~1

# 커밋 취소 + 스테이징 해제 (기본값)
git reset HEAD~1

# 커밋 취소 + 변경 완전 삭제 ⚠️
git reset --hard HEAD~1
⚠️

git reset은 로컬에서만! push된 커밋을 reset하면 팀원의 히스토리와 충돌.

3. git revert — 공개 커밋 안전 되돌리기

bash
git revert abc1234        # 특정 커밋
git revert HEAD           # 최근 커밋
git revert HEAD~3..HEAD   # 여러 커밋
git revert --no-commit HEAD
resetrevert
동작커밋 삭제되돌리기 커밋 추가
히스토리변경됨보존됨
안전성로컬 전용push된 커밋도 안전
팀 작업위험권장

4. git cherry-pick

bash
git cherry-pick abc1234            # 특정 커밋
git cherry-pick abc1234 def5678    # 여러 개
git cherry-pick abc1234..def5678   # 범위

# 충돌 해결 후
git add .
git cherry-pick --continue
git cherry-pick --abort

예: feature 브랜치의 버그 수정 커밋만 main에 적용.

5. git tag

bash
git tag v1.0.0                       # 경량 태그
git tag -a v1.0.0 -m "첫 정식 릴리즈"  # 주석 태그 (권장)
git tag -a v0.9.0 abc1234 -m "베타"   # 특정 커밋

git tag                  # 목록
git tag -l "v1.*"        # 패턴
git show v1.0.0          # 상세

git push origin v1.0.0       # 태그 push
git push origin --tags       # 모든 태그

git tag -d v1.0.0            # 로컬 삭제
git push origin :v1.0.0      # 원격 삭제

6. git reflog — 위험한 상황 복구

HEAD가 이동한 모든 이력. reset --hard로 삭제한 커밋도 reflog로 복구 가능!

bash
git reflog
# abc1234 HEAD@{0}: reset: moving to HEAD~3   ← 잘못된 reset!
# def5678 HEAD@{1}: commit: feat: 중요한 기능

git reset --hard HEAD@{1}    # 방금 전 상태로
git reset --hard def5678     # 해시로 복구
💡

reflog는 로컬에만 — gc 실행 시 사라질 수 있습니다.

예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗

댓글 0

아직 댓글이 없습니다. 첫 댓글을 남겨 주세요.

댓글은 회원만 쓸 수 있습니다.

광고·욕설·비방·개인정보·불법 내용이 담긴 댓글은 숨기거나 지웁니다. 댓글은 닉네임과 함께 공개됩니다. 개인정보처리방침