가이드

Git 풀 리퀘스트란: GitHub에서 PR 만드는 방법

업데이트: · Skillaria.Top

풀 리퀘스트(PR)는 한 브랜치의 변경 사항을 다른 브랜치에 합쳐 달라고 GitHub 같은 플랫폼에서 요청하는 기능입니다. 변경 내용을 보여 주면 팀이 댓글을 달고 자동 검사를 확인한 뒤, 승인되면 병합합니다. GitLab에서는 같은 기능을 머지 리퀘스트(MR)라고 부릅니다. Git 명령이 아니며 git pull과도 관계가 없습니다.

풀 리퀘스트(PR)는 한 브랜치의 변경 사항을 다른 브랜치에 합쳐 달라고 제안하는 것으로, GitHub 같은 플랫폼에서 이루어집니다. 브랜치를 서버에 올리고 PR을 열면, 팀이 차이점(diff)을 보고 줄마다 댓글을 달고 자동 검사를 실행한 뒤에야 병합 버튼을 누릅니다. GitLab에서는 같은 방식을 머지 리퀘스트(MR)라고 부릅니다. "git pull request란?"이라는 질문에는, "코드를 작성함"과 "코드가 main에 들어감" 사이에 있는 검토 지점이라고 답할 수 있습니다.

풀 리퀘스트라는 이름의 유래

이 이름은 역사적으로 자리 잡았습니다. 변경 사항을 만든 사람이 저장소 소유자에게 자신의 브랜치를 "끌어당겨(pull)" 가 달라고 요청합니다. 여기서 pull request라는 이름이 나왔습니다. GitLab은 결과에 초점을 맞춰 머지 리퀘스트(merge request, 병합 요청)라고 이름 붙였습니다. Bitbucket과 Azure DevOps는 "pull request"라고 부릅니다. 본질은 같습니다. 출발 브랜치, 도착 브랜치, 설명, 토론, 검사, 병합 버튼으로 구성됩니다.

중요한 점은 풀 리퀘스트가 Git의 일부가 아니라는 것입니다. Git 자체에는 "PR"이라는 객체가 없으며, 커밋으로 만들 수도 없고 .git 폴더에서 찾을 수도 없습니다. 이것은 플랫폼의 기능입니다. GitHub가 설명, 댓글, 검사 상태를 저장하고, Git은 PR에 포함된 브랜치와 커밋만 관리합니다.

개발자끼리의 대화에서 "PR"은 거의 항상 풀 리퀘스트를 뜻합니다. "PR 올려 줘", "PR 리뷰 부탁해", "PR 병합했어"처럼 씁니다. GitLab에서는 "MR"이라고 말합니다.

풀 리퀘스트와 git pull의 차이

비슷한 단어 때문에 이 둘을 자주 혼동합니다. git pull은 원격 저장소의 새 커밋을 내려받아 현재 브랜치에 바로 합치는 명령입니다. 터미널에서 하는 로컬 작업입니다. 반면 풀 리퀘스트는 한 브랜치를 다른 브랜치에 병합해 달라고 요청하는, GitHub 등의 웹 페이지입니다.

git pull풀 리퀘스트
어디에 있나터미널의 Git 명령GitHub, GitLab, Bitbucket 페이지
무엇을 하나서버의 변경 사항을 내 컴퓨터로 가져옴내 브랜치를 다른(공용) 브랜치에 병합해 달라고 요청함
누가 참여하나나 혼자작성자, 리뷰어, CI
플랫폼이 필요한가아니요. remote만 있으면 됨예

Git에는 "git pull request"라는 독립된 명령이 없습니다. 오래된 도구인 git request-pull이 있긴 하지만, 이는 변경 요약을 담은 메일 문구를 만들 뿐이며 GitHub의 PR과는 관계가 없습니다.

풀 리퀘스트가 필요한 이유

프로젝트를 혼자 진행할 때는 main에 직접 커밋해도 괜찮습니다. 하지만 저장소에 두 명 이상이 참여하면, 메인 브랜치에 직접 push하는 방식은 빌드 실패와 작업 유실의 원인이 됩니다. 풀 리퀘스트는 다음 문제들을 한 번에 해결합니다.

  • 코드 리뷰: 변경 사항이 main에 들어가기 전에 다른 사람이 확인하고, 작성자가 놓친 실수를 찾아낼 수 있습니다.
  • 자동 검사: GitHub Actions 같은 CI가 PR마다 테스트와 린터를 실행하고, 빨간 상태이면 깨진 코드를 병합하지 못하게 합니다.
  • 결정의 기록: 1년 뒤에도 PR을 보면 무엇이 바뀌었는지뿐 아니라 왜 바뀌었는지도 토론과 함께 알 수 있습니다.
  • 남의 프로젝트에 기여: 오픈소스에서는 쓰기 권한이 없으므로, 포크에서 보내는 PR이 수정 사항을 제안하는 유일한 방법입니다.
  • 브랜치 보호: GitHub의 브랜치 보호 규칙으로 main에 대한 직접 push를 막고, 승인된 PR을 요구할 수 있습니다.

GitHub에서 브랜치로 풀 리퀘스트 만들기

이 방식은 모든 팀원이 저장소에 쓰기 권한을 가진 팀에서 기본이 되는 흐름입니다. 작업은 feature 브랜치에서 하고, main에는 PR을 통해서만 변경을 반영합니다.

1단계. 최신 main에서 브랜치 만들기

git switch main
git pull
git switch -c feature/login-form

브랜치 이름은 내용이 드러나도록 짓는 것이 좋습니다. feature/…, fix/…, 작업 번호 등이 흔히 쓰입니다. 리뷰어가 무슨 작업인지 바로 알 수 있습니다.

2단계. 커밋 만들기

git add src/login.js
git commit -m "로그인 폼 추가"

하나의 PR에는 하나의 작업만 담으세요. 100~300줄 정도의 작은 PR은 빠르고 꼼꼼하게 리뷰할 수 있지만, 3000줄짜리 PR은 리뷰어가 내용을 제대로 보지 않고 승인하기 쉽습니다.

3단계. 브랜치를 서버에 올리기 (PR을 위한 git push)

git push -u origin feature/login-form

-u 옵션은 로컬 브랜치와 원격 브랜치를 연결합니다. 이후에는 git push만 입력하면 됩니다. GitHub는 응답에서 PR을 만들 링크를 직접 알려 줍니다.

remote: Create a pull request for 'feature/login-form' on GitHub by visiting:
remote:      https://github.com/team/app/pull/new/feature/login-form

4단계. 웹에서 PR 열기

터미널에 나온 링크를 열거나, GitHub에서 저장소를 열어 보세요. 방금 push한 브랜치가 있으면 "Compare & pull request" 배너가 나타납니다. 다른 방법으로는 "Pull requests" 탭에서 "New pull request"를 누르면 됩니다.

  1. 브랜치 조합을 확인합니다. base는 병합 대상(보통 main), compare는 내 브랜치입니다.
  2. 제목을 씁니다. 무엇을 했는지 명령형이나 짧은 설명으로 적습니다.
  3. 설명에 이유, 확인 방법, 이번 작업에서 제외한 범위를 씁니다. 저장소에 PR 템플릿이 있으면 자동으로 채워집니다.
  4. 오른쪽에서 리뷰어(Reviewers), 담당자(Assignees), 라벨을 지정합니다. 팀에서 쓰는 경우에만 설정하면 됩니다.
  5. "Create pull request"를 누르거나, 초안(Draft)으로 만듭니다(아래 참고).

터미널에서 PR 만들기: GitHub CLI

브라우저로 이동하기 싫다면 공식 도구 gh를 쓸 수 있습니다. Git 명령은 아니고 GitHub가 제공하는 별도의 프로그램이지만, PR 작업에 편리합니다.

gh pr create --base main --title "로그인 폼 추가" --body "Closes #42"
gh pr list
gh pr checkout 57
gh pr merge 57 --squash

"git pull request 명령"에 대한 솔직한 답은 이렇습니다. Git은 브랜치, 커밋, push를 다루고, PR 자체는 플랫폼에서 만듭니다. 브라우저, gh, 또는 API를 사용합니다.

포크를 통해 남의 저장소에 풀 리퀘스트 보내기

오픈소스 프로젝트에서는 보통 쓰기 권한이 없습니다. 그래서 먼저 포크를 만듭니다. 포크는 GitHub에서 저장소의 사본을 만드는 것입니다. 그 사본에서 작업한 뒤, 원본 프로젝트에 변경을 제안합니다.

  1. 프로젝트 페이지에서 "Fork"를 누릅니다. github.com/you/project가 생성됩니다.
  2. 내 포크를 clone하고, 원본 저장소를 두 번째 remote로 추가합니다. 보통 이름은 upstream입니다.
  3. 브랜치를 만들고, 커밋한 뒤, 내 포크에 브랜치를 push합니다.
  4. GitHub에서 PR을 엽니다. base repository는 원본 프로젝트, head repository는 내 포크와 내 브랜치입니다.
git clone git@github.com:you/project.git
cd project
git remote add upstream https://github.com/owner/project.git
git switch -c fix/typo-readme
git commit -am "README 오타 수정"
git push -u origin fix/typo-readme

작업을 시작하기 전에 CONTRIBUTING.md 파일을 확인하세요. 커밋 메시지 작성 규칙, 테스트 방법, 먼저 issue를 만들어야 하는지 등이 보통 적혀 있습니다. 포크를 최신 상태로 유지하려면 git fetch upstream을 실행하고, 내 브랜치에서 git rebase upstream/main을 실행하세요. 그러면 PR이 원본보다 뒤처지지 않습니다.

GitLab의 머지 리퀘스트: 뜻과 만드는 법

GitLab의 머지 리퀘스트는 GitHub의 풀 리퀘스트에 해당하는 기능입니다. 이름과 화면 구성은 조금 다르지만 과정은 같습니다. 브랜치, push, 병합 요청, 리뷰, 병합 순서로 진행합니다.

MR은 다음 방법 중 하나로 만들 수 있습니다.

  • 새 브랜치를 git push한 뒤 터미널에 나오는 링크를 이용합니다.
  • 프로젝트의 Merge requests 메뉴에서 "New merge request"를 누르고, 출발 브랜치와 도착 브랜치를 고릅니다.
  • push할 때 GitLab의 push options를 지정해, 브라우저를 열지 않고 만듭니다.
git push -o merge_request.create -o merge_request.target=main origin feature/login-form

GitLab의 용어는 조금 다릅니다. 승인은 approve, 병합 책임자는 assignee라고 하며, GitHub Actions 대신 .gitlab-ci.yml 파일을 사용하는 GitLab CI/CD가 동작합니다. 초안 MR도 있으며 Draft라고 부릅니다.

풀 리퀘스트 리뷰하기

리뷰어는 "Files changed" 탭을 열어 차이점을 봅니다. 어느 줄에든 댓글을 달 수 있고, 작성자가 한 번의 클릭으로 적용할 수 있는 수정 제안(suggestion)도 남길 수 있습니다. 댓글은 한꺼번에 제출되며, 다음 중 하나의 판정을 함께 보냅니다.

  • Comment: 판정 없이 의견만 남깁니다.
  • Approve: 변경을 승인합니다.
  • Request changes: 수정이 필요하며, 병합하지 않기를 요청합니다.

좋은 리뷰는 로직, 가독성, 테스트, 예외 상황을 봅니다. 취향 문제로 다투지 않는 것이 좋습니다. 서식은 CI의 린터에 맡기세요. 작성자는 모든 댓글에 답하는 것이 좋습니다. 수정했는지, 논의했는지, 설명과 함께 그대로 두었는지를 적으면 됩니다.

남의 PR을 로컬에서 확인하는 방법 (git checkout pull request)

코드를 직접 실행해 보고 싶을 때가 있습니다. 브랜치가 같은 저장소에 있다면 git fetch와 git switch로 충분합니다. 포크에서 온 PR이라면, GitHub는 pull/<번호>/head라는 특별한 참조를 제공합니다.

git fetch origin pull/57/head:pr-57
git switch pr-57

GitLab에서는 같은 목적의 참조를 merge-requests/<번호>/head라고 부릅니다. GitHub CLI가 설치되어 있다면 gh pr checkout 57 한 줄이면 됩니다.

리뷰 의견을 받고 풀 리퀘스트 업데이트하기

PR은 특정 커밋이 아니라 브랜치에 연결되어 있습니다. 같은 브랜치에 새 커밋을 만들어 push하면 PR이 자동으로 업데이트됩니다. 새 PR을 만들 필요는 없습니다.

git commit -am "리뷰 의견 반영"
git push

git rebase pull request: 최신 main 가져오기

PR이 리뷰를 받는 동안 main은 계속 앞으로 나갑니다. GitHub가 브랜치가 오래되었거나 충돌이 있다고 알리면 브랜치를 업데이트하세요. rebase를 쓰면 기록이 일직선으로 유지됩니다.

git fetch origin
git rebase origin/main
# 충돌을 해결하고 git add 한 뒤 git rebase --continue
git push --force-with-lease

rebase를 하면 커밋 해시가 바뀌므로 일반 push는 거부되고, 강제 push가 필요합니다. 이때 --force-with-lease를 쓰세요. 이 옵션은 브랜치에 다른 사람의 커밋이 새로 올라와 있으면 덮어쓰기를 거부합니다. 그 브랜치에서 다른 사람도 함께 작업한다면, git merge origin/main으로 main을 가져오는 편이 기록을 고치지 않으므로 더 안전합니다.

풀 리퀘스트 병합하기: merge, squash, rebase

리뷰가 승인되고 검사가 모두 통과하면 PR을 병합할 수 있습니다. GitHub는 세 가지 방법을 제공하며, 저장소 관리자는 그중 일부만 허용하도록 설정할 수 있습니다.

방식main에 들어가는 내용적합한 경우
Create a merge commit브랜치의 모든 커밋과 병합 커밋전체 기록이 필요하고, 어떤 커밋이 함께 들어왔는지 남기고 싶을 때
Squash and mergePR의 모든 변경을 담은 커밋 하나"fix typo" 같은 작은 커밋이 많고, main 로그를 깔끔하게 유지하고 싶을 때
Rebase and merge병합 커밋 없이 브랜치의 커밋을 하나씩커밋이 잘 정리되어 있고, 각 커밋이 그 자체로 의미가 있을 때

화면에서 PR을 병합하는 것은 사실상 서버에서 실행되는 git merge와 같습니다. 병합 후 GitHub가 브랜치 삭제를 제안하는데, 더 이상 필요 없다면 삭제해도 됩니다. 로컬도 정리하세요.

git switch main
git pull
git branch -d feature/login-form

터미널에서 직접 병합할 수도 있습니다. 로컬에서 브랜치를 main에 합친 뒤 push하면 됩니다. GitHub는 브랜치의 커밋이 base에 들어간 것을 알아보고 PR을 자동으로 merged 처리합니다. 하지만 이 방법은 검사와 브랜치 보호 규칙을 건너뛰기 때문에, 보통은 버튼으로 병합합니다.

Auto-merge와 merge queue

검사가 오래 걸린다면 자동 병합을 켤 수 있습니다. 모든 조건이 충족되면 PR이 자동으로 병합됩니다. 큰 저장소에서는 병합 큐(merge queue)를 사용합니다. 큐에 있는 다른 PR을 먼저 적용한 상태에서 PR을 검증하므로, 서로 호환되지 않는 변경으로 main이 깨지는 것을 막습니다.

풀 리퀘스트 초안(Draft)

초안은 아직 리뷰할 준비가 되지 않은 PR입니다. 병합할 수 없고, 리뷰어에게는 리뷰 요청이 가지 않습니다. 초안은 방향을 일찍 공유하거나, CI를 미리 돌려 보거나, 설계에 대한 의견을 모을 때 유용합니다. GitHub에서 PR을 만들 때 생성 버튼의 드롭다운에서 초안을 고르거나, gh pr create --draft를 실행하세요. 작업이 끝나면 "Ready for review"를 누릅니다. GitLab에서는 MR 제목 앞에 Draft:를 붙여 초안으로 표시합니다.

풀 리퀘스트와 issue 연결하기

PR 설명에 키워드와 issue 번호를 적으면, 병합 후 GitHub가 해당 issue를 자동으로 닫습니다.

Closes #42
Fixes #17
Resolves #8

close, fix, resolve와 그 활용형(closes, fixed, resolves 등)이 동작합니다. 키워드 없이 #42만 적으면 링크만 걸리고 issue는 닫히지 않습니다. GitLab에서도 Closes #42 같은 비슷한 표현을 쓸 수 있습니다.

풀 리퀘스트나 머지 리퀘스트를 삭제할 수 있나요

GitHub에서 일반 사용자는 PR을 삭제할 수 없습니다. "Close pull request" 버튼으로 닫을 수만 있습니다. 닫힌 PR은 기록에 남고, 다시 열 수도 있습니다. 닫은 뒤의 브랜치는 따로 삭제하세요. PR을 완전히 지우려면 GitHub 지원팀에 요청해야 합니다. 예를 들어 비밀 정보가 실수로 포함된 경우입니다.

GitLab에서는 작성자나 권한이 있는 멤버가 MR을 닫을 수 있습니다. 삭제는 프로젝트 소유자나 관리자만 할 수 있습니다. PR에 비밀번호나 토큰이 들어갔다면 닫는 것만으로는 충분하지 않습니다. 커밋은 이미 서버에 있으므로, 해당 비밀 값을 즉시 무효화하세요.

풀 리퀘스트에서 자주 하는 실수

  • main에서 PR 만들기: 내 main에 커밋한 뒤 그 main을 기준으로 PR을 열면, 다음 PR에도 예전 변경이 함께 들어갑니다. 작업은 항상 별도의 브랜치에서 하세요.
  • 잘못된 base 브랜치: PR이 main 대신 develop을 향하거나 그 반대인 경우. PR 제목 옆의 Edit 버튼으로 base를 바꿀 수 있습니다.
  • diff에 불필요한 파일이 포함됨: 빌드 결과물, node_modules, .env 등. .gitignore에 추가하고 git rm --cached로 인덱스에서 빼세요.
  • 거대한 PR: 작업을 여러 개의 순차적인 PR로 나누세요.
  • rebase 후 일반 push: rejected (non-fast-forward) 오류가 납니다. --force가 아니라 git push --force-with-lease를 쓰세요.
  • 웹 편집기에서 충돌을 무작정 해결하기: 로컬에서 main을 가져와 해결하고, 테스트로 확인하세요.

git flow와 다른 프로세스에서의 풀 리퀘스트

풀 리퀘스트는 어떤 팀의 개발 프로세스에도 맞출 수 있습니다. GitHub Flow에서는 main에서 브랜치를 만들고, PR을 올리고, 리뷰하고, 병합하고, 배포하는 단순한 흐름입니다. git flow에서는 feature 브랜치의 PR이 develop을 향하고, 릴리스 브랜치와 hotfix 브랜치도 main으로 가는 PR을 거칩니다. trunk-based 개발에서는 PR이 짧아서 며칠이 아니라 몇 시간 안에 끝납니다. 어떤 프로세스든 규칙은 하나입니다. 공용 브랜치에 대한 변경은 반드시 풀 리퀘스트를 통해서만 합니다.

정리

풀 리퀘스트는 Git 명령이 아니라 플랫폼의 기능입니다. 서버에 올라간 브랜치에 토론, 리뷰, 검사를 위한 페이지가 더해진 것입니다. GitLab에서는 머지 리퀘스트라고 하며, 대화에서는 PR이나 MR이라고 말합니다. PR은 별도의 브랜치에서 만들고, 작게 유지하고, 같은 브랜치에 push해서 업데이트하고, 프로젝트 기록에 맞는 방식으로 병합하세요. 포크, feature 브랜치, 풀 리퀘스트의 실제 사용법은 Git 강의에서 실습으로 다룹니다.

자주 묻는 질문

풀 리퀘스트에는 리뷰어가 몇 명 필요한가요?

보통 한두 명이면 충분합니다. 필요한 최소 승인 수는 브랜치 보호 규칙에서 정하며, 그 수를 채우지 못하면 병합 버튼을 쓸 수 없습니다.

포크 없이도 풀 리퀘스트를 만들 수 있나요?

네. 저장소에 쓰기 권한이 있다면 그 저장소 안에 브랜치를 만들고, 거기서 PR을 열면 됩니다. 포크는 쓰기 권한이 없을 때만 필요합니다.

PR을 오랫동안 아무도 보지 않으면 어떻게 하나요?

댓글이나 팀 채팅으로 리뷰어에게 정중하게 다시 알려 주세요. 오픈소스 프로젝트에서는 몇 주가 걸리기도 합니다. PR이 CONTRIBUTING.md의 규칙에 맞는지도 함께 확인하세요.

내 포크 안의 두 브랜치 사이에 풀 리퀘스트를 만들 수 있나요?

네. 비교 페이지에서 base와 head를 모두 내 포크로 고르면 됩니다. 원본 프로젝트에 보내기 전에 내 변경을 리뷰하기 좋은 방법입니다.

내가 만들지 않은 커밋이 PR에 보이는 이유는 무엇인가요?

브랜치가 최신 main에서 만들어지지 않았거나, base 브랜치를 잘못 골랐을 가능성이 큽니다. 최신 main에 rebase하거나 PR 설정에서 base를 바꾸세요.

영상으로 이 주제 배우기

이 주제는 “Git 완전 정복: 초보에서 능숙한 개발자로” 강의에서 실습과 함께 자세히 다룹니다.

강의로 이동