홈 › GitHub › 03 / 5

코드 리뷰와 병합 방식

섹션 7진행 0 / 5

2. 핵심 원리

2.1 리뷰는 병합 전 마지막 관문

리뷰(review)는 PR 의 변경 내용을 다른 사람이 확인하는 절차입니다. GitHub 화면에서는 코드 줄마다 코멘트를 달고, PR 전체에 대해 하나의 리뷰를 제출합니다. 제출한 리뷰는 Comment·Approve·Request changes 셋 중 하나입니다.

2.2 리뷰 종류 세 가지

종류 의미 병합 가능 여부
Comment 의견만 남김, 찬반 없음 규칙에 안 걸리면 가능
Approve 승인, 병합해도 좋음 가능
Request changes 변경 요구, 반려 재승인 전까지 불가

Request changes 를 받으면 보호 규칙이 걸린 저장소는 그 리뷰어가 다시 승인하기 전까지 병합 버튼이 막힙니다. 지적을 반영한 커밋을 올리면 리뷰어에게 재검토 요청이 갑니다.

2.3 suggestion 블록으로 바로 반영

리뷰 코멘트 안에 ```suggestion 블록을 쓰면 GitHub 화면에 "Commit suggestion" 버튼이 뜹니다. 작성자가 그 버튼을 누르면 리뷰어가 제안한 코드가 그대로 새 커밋으로 브랜치에 올라갑니다.

로컬 재현에서는 이 화면을 텍스트로 보여주고, 실제로는 리뷰어의 제안 내용을 손으로 적용해 커밋합니다. 결과는 GitHub 에서 버튼을 눌렀을 때와 같은 diff 입니다.

2.4 리뷰어 지정과 CODEOWNERS

PR 화면에서 리뷰어를 직접 지정할 수도 있지만, 파일 경로별로 자동 지정하려면 CODEOWNERS 파일을 씁니다. 저장소 루트나 .github/, docs/ 중 한 곳에 두면 GitHub 가 인식합니다.

2.5 CODEOWNERS 패턴 규칙

패턴은 .gitignore 와 비슷한 글로브(glob)이며, 파일 안에서 더 아래(뒤)에 있는 규칙이 우선합니다. 한 파일에 여러 패턴이 맞으면 마지막으로 맞은 규칙의 소유자가 적용됩니다.

패턴 뜻
* 모든 파일의 기본 소유자
*.java 확장자 java 파일
docs/* docs 폴더 바로 아래 파일

2.6 브랜치 보호 규칙 개요

브랜치 보호(branch protection)는 main 같은 핵심 브랜치에 거는 서버 쪽 규칙입니다. 필수 리뷰 수, 필수 검사 통과, force push 금지, 직접 push 금지 등을 조합해서 켭니다.

2.7 필수 리뷰와 필수 검사

"필수 리뷰 1인" 을 켜면 Approve 가 하나도 없으면 병합 버튼이 비활성화됩니다. "필수 검사(Required status checks)" 는 CI 결과가 초록색이어야 병합을 허용합니다. 검사가 빨간색이면 리뷰가 다 끝나도 막힙니다.

2.8 force push 금지와 서버 훅

GitHub 는 브랜치 보호 화면에서 "Do not allow force pushes" 로 이 규칙을 켭니다. 로컬 재현에서는 같은 역할을 bare 저장소의 pre-receive 훅으로 만듭니다. 밀어넣은 커밋이 기존 커밋의 후손(fast-forward)이 아니면 거절합니다.

2.9 병합 방식 세 가지

방식 결과 이력 원본 커밋
merge commit 병합 커밋 1개 + 원본 그대로 보존
squash 새 커밋 1개 사라짐(메시지에만 요약)
rebase 원본 커밋이 새 해시로 이어짐 개수 보존, 해시 변경

2.10 언제 어떤 방식을 쓰나

merge commit 은 "이 PR 이 언제 합쳐졌는지" 를 그래프로 남기고 싶을 때 씁니다. squash 는 커밋을 정리하지 않고 올린 브랜치를 깔끔한 한 줄로 만들고 싶을 때 씁니다. rebase 는 커밋 단위를 살리면서도 병합 커밋 없이 선형 이력을 원할 때 씁니다.

2.11 PR 이 뒤처졌을 때

다른 PR 이 먼저 병합되면 내 브랜치의 base 가 낡습니다. git rebase main 으로 최신 커밋 위에 옮겨 붙이거나, git merge main 으로 병합 커밋을 하나 추가해 따라잡습니다. 이미 GitHub 에 올린 브랜치를 rebase 하면 커밋 해시가 바뀝니다.

2.12 충돌 해결과 force-with-lease

rebase 도중 같은 파일을 건드린 커밋이 만나면 충돌(conflict)이 납니다. <<<<<<<·=======·>>>>>>> 표시를 보고 고친 뒤 git add, git rebase --continue 로 이어갑니다.

해시가 바뀐 브랜치는 git push --force-with-lease 로 다시 올립니다. 원격이 내가 마지막으로 받은 상태 그대로일 때만 덮어써서, 동료 커밋을 실수로 지우지 않습니다.