Insights·2026-08-27

PR と MR は何が違うのか

PR(Pull Request)と MR(Merge Request)は同じ機能で、名前が違うだけだ。GitHub・Bitbucket・Gitea・Azure DevOps は Pull Request と呼び、GitLab は Merge Request と呼ぶ。どのプラットフォームでも手順は同じで、二つのブランチの差分を見せ、レビューを受け、マージする。見落とされがちなのは、Git 自体にも pull request があるという点だ。git request-pull というコマンドは実際に存在する。ただしそれがするのは「ここからここまで取り込んでほしい」という要約を標準出力に流すことだけで、レビュー画面も承認ボタンもオープン・クローズといった状態もない。メーリングリストに貼って送るために作られたものだからだ。つまり私たちが毎日開いている PR や MR はそのテキストではなく、ホスティングサービスが Git の上に載せたウェブ上のオブジェクトである。本当の違いは名前ではなく、各サービスがそのオブジェクトに何を取り付けたかにあり、それはターミナルからそのまま読み取れる。承認は GitHub ではレビューコマンドのフラグ一つだが、GitLab では独立したコマンドで、承認できる人の一覧表示と承認の取り消しが別に用意されている。CI の状態は逆で、GitHub は PR に取り付け、GitLab はパイプラインを別の階層に分けた。したがってチームが二つのプラットフォームを移るときに書き直すべきなのは用語集ではなく、承認ルールの文書だ。

PR과 MR은 같은 물건이다 — 이름만 다르고 규칙은 플랫폼이 쥔다. 나란히 놓인 두 터미널 창에 gh pr과 glab mr 라벨이 붙어 있고, GitHub은 Pull GitLab은 Merge, git request-pull은 요약문만 출력한다, 리뷰 화면·승인·상태는 플랫폼의 몫, gh pr을 glab mr로 바꾸면 그대로 된다는 네 줄이 함께 조판된 포스터

PR と MR は何が違うのか

人と一緒にコードを書き始めると、すぐにこう言われる。「PR 出しました」あるいは「MR のレビューお願いします」。転職した先で、これまで PR と呼んでいたものを皆が MR と呼んでいると、一瞬手が止まる。自分が覚えたことはここでは通用しないのだろうか、と。

結論から言うと同じものだ。GitHub が Pull Request、GitLab が Merge Request と呼んでいるだけである。Bitbucket も、Gitea とそのフォークである Forgejo も、Azure DevOps も Pull Request の側だ。どちらであれやることは変わらない。自分のブランチとマージ先ブランチの差分を画面に出し、同僚がその差分にコメントしてレビューし、合意できたらボタンを押してマージする。

名前が分かれたのは、同じ出来事を反対側から見ているからだ。pull は受け取る側の動作で、自分のブランチを取り込んでほしいという意味になる。merge はその要求が果たされた結果で、マージしてほしいという意味だ。実際、gh pr create のヘルプには今でも対象リポジトリをフォークするかどうか尋ねる記述が残っている。他人のリポジトリに貢献するという構図が言葉に染み込んでいるわけだ。

だから実務では混ぜて使っても通じる。GitLab を使っているチームで「PR 出しました」と言っても、誰も意味を取り違えたりしない。用語そのものが問題になることはほとんどない。

プラットフォーム呼び方URL パス
GitHubPull Request (PR)/pull/123
GitLabMerge Request (MR)/-/merge_requests/123
BitbucketPull Request (PR)/pull-requests/123
Gitea · ForgejoPull Request (PR)/pulls/123
Azure DevOpsPull Request (PR)/pullrequest/123

Git にも pull request はある — git request-pull

git request-pull の存在確認と使い方を見るコマンドを並べたターミナル画面。レビュー画面も承認ボタンも状態もなく、標準出力に出るだけだという説明が下に付く。

ここで多くの人が見落としている事実がある。Git 自体にも pull request がある。比喩ではなく、本当にその名前のコマンドが存在する。

ターミナルを開いて git request-pull と打ってみてほしい。引数なしで打つと使い方が表示される。開始地点とリポジトリのアドレスを渡すと、その地点以降に自分が作ったコミットをまとめて、取り込んでほしいという要約文を作ってくれる。公式ドキュメントの表現では、上流プロジェクトに自分の変更を取り込んでもらうよう依頼する文面を生成するコマンドだ。

しかしそれで全部である。このコマンドが生み出すのは画面に出る文字だけだ。レビュー画面は出ない。承認ボタンもない。オープンやクローズといった状態もなく、コメントを書く場所もなく、誰が承認したかも記録されない。そもそもどこかに送信されすらしない。標準出力に出るだけだ。

もともとそう使うために作られたものだからだ。Linux カーネルのようなメーリングリスト中心の開発では、この出力をコピーしてメール本文に貼り、メンテナに送っていた。メンテナはそれを読んで自分で git pull を実行する。レビューはメールの返信でやり取りされた。

自分で叩いてみる
# コマンドが存在するか確認(使い方が出る)
git request-pull

# 実際の形
git request-pull <開始コミット> <リポジトリURL> [<終了コミット>]

# 例: main 以降の自分のブランチのコミットを取り込んでもらう要約
git request-pull main https://github.com/me/repo.git my-branch

# 詳しい説明
git help request-pull

では毎日使っている PR・MR とは何なのか

前の二つの節をつなげると答えが出る。私たちが毎日開いているあの画面は Git の機能ではない。ホスティングサービスが Git の上に載せたウェブ上のオブジェクトだ。

Git の仕事は二つのブランチの差分を計算するところまでである。その差分をウェブページとして描き、行ごとにコメントを付けられるようにし、誰が承認したかを記録し、自動チェックを取り付け、条件を満たしたときだけマージボタンを有効にする。これらはすべて GitHub や GitLab といった製品の担当だ。だから PR・MR には番号が付き、オープンとクローズという状態があり、担当者やラベルが付く。Git にはこうした概念が一つもない。

この区別が実務でなぜ効いてくるのか。ローカルの Git の知識だけでは、チームの協業ルールが分からないからだ。git merge をどれだけよく知っていても、自分のチームで何人の承認があればマージできるのかは Git ではなくプラットフォームの設定にある。そしてまさにその設定が、GitHub と GitLab では形が違う。

本当の違いはターミナルに出る — gh pr と glab mr

二つのプラットフォームの違いを最も早く確かめる方法は、それぞれの公式 CLI のサブコマンド一覧を並べて見ることだ。製品が何を一級の概念として扱っているかは、コマンドの構造にそのまま表れる。

GitHub CLI では承認はレビューのフラグ一つだ。gh pr review --approve と書く。承認・コメント・変更要求がすべて review という一つのコマンドのオプションになっている。一方 GitLab CLI では承認はそれ自体が独立したコマンドだ。glab mr approve があり、その隣に承認できる人を一覧表示する approvers と、すでに出した承認を取り消す revoke が別にある。

CI の状態は逆である。GitHub はパイプラインの結果を PR に取り付けた。gh pr checks と打てばその PR のチェック結果が出る。GitLab に glab mr checks に相当するものはない。代わりに glab ci という別のトップレベルの階層があり、パイプラインはそこで扱う。

ほかにも肌合いの違うコマンドがいくつか見える。GitLab にはソースブランチをマージ先の上に乗せ直す glab mr rebase があり、イシューからそのまま MR を作る glab mr for がある。GitHub にはブランチを最新に合わせる gh pr update-branch、マージ済みの PR を取り消す gh pr revert、下書きをレビュー可能と示す gh pr ready がある。

やりたいことGitHub (gh)GitLab (glab)
作るgh pr createglab mr create
一覧を見るgh pr listglab mr list
ローカルに取り込むgh pr checkoutglab mr checkout
変更を見るgh pr diffglab mr diff
承認するgh pr review --approveglab mr approve
承認を取り消す(レビューを出し直す)glab mr revoke
承認できる人を調べる(専用コマンドなし)glab mr approvers
CI の状態を見るgh pr checksglab ci(別階層)
マージするgh pr mergeglab mr merge
サブコマンド一覧を自分で比べる
# GitHub CLI
gh pr --help

# GitLab CLI
glab mr --help

# 承認がどこに付いているか確認
gh pr review --help      # --approve フラグとして出る
glab mr approve --help   # 独立したコマンドとして出る

はじめて出してみる手順 — GitHub と GitLab の両方で

GitHub に PR を出すコマンドと GitLab に MR を出すコマンドを上下のターミナルに並べ、インストール・ログイン・プッシュ・作成・マージの順序が両者で対称であることを示す図。

名前が違うだけで手順は同じ、という話は、実際にコマンドを叩けばすぐ確かめられる。次の手順は両者で完全に対称だ。コマンドの pr を mr に、gh を glab に置き換えればそのまま GitLab になる。

まず CLI をインストールしてログインする。macOS ならどちらも Homebrew で入る。ログインはそれぞれ gh auth login と glab auth login で、ブラウザが開いてアカウント認証を行う。これは一度だけでよい。

その後は普段の Git 作業と同じだ。作業用のブランチを作り、コミットし、リモートに上げる。ここまでは GitHub でも GitLab でも純粋な Git なので違いはない。

最後に PR・MR を作る。両方の CLI に --fill オプションがあり、コミットメッセージからタイトルと本文を自動で埋めてくれる。まだレビューを受ける準備ができていなければ --draft を付けて下書きとして出す。下書きはマージボタンがロックされた状態で開くので、作業中のものを先に共有したいときに使う。

出したあとはブラウザを開かなくてもターミナルから確認できる。--web を付ければブラウザで開き、view だけならタイトルと本文と状態がターミナルに出力される。

GitHub に PR を出す
# 初回のみ
brew install gh
gh auth login

# 作業
git switch -c fix-login
git commit -am "ログイン失敗時のメッセージを修正"
git push -u origin fix-login

# PR を作る(タイトル・本文をコミットから自動で埋める)
gh pr create --fill

# 下書きとして出す
gh pr create --fill --draft

# 確認してマージ
gh pr view
gh pr checks
gh pr merge --squash
GitLab に MR を出す(同じ手順)
# 初回のみ
brew install glab
glab auth login

# 作業
git switch -c fix-login
git commit -am "ログイン失敗時のメッセージを修正"
git push -u origin fix-login

# MR を作る(タイトル・本文をコミットから自動で埋める)
glab mr create --fill

# 下書きとして出す
glab mr create --fill --draft

# 確認してマージ
glab mr view
glab mr approve
glab mr merge

移行するときに本当に書き直す文書

ではチームが GitHub から GitLab へ、あるいはその逆へ移るとき、実際に手が入るのはどこか。用語集ではない。PR を MR と言い換えるのは一日あれば慣れる。

書き直すべきは承認ルールの文書だ。マージまでに何人の承認が要るのか。コード所有者の承認は必須か。新しいコミットが積まれたら既存の承認は無効になるのか。承認は取り消せるのか。これらのルールが二つのプラットフォームでは別々の名前と別々の画面に散らばっている。先に見た CLI の構造がその差の要約になっている。GitLab が承認できる人の一覧表示と承認の取り消しを独立したコマンドとして持っているということは、その概念が製品の中でそれだけ厚く扱われているという意味だ。

もう一つ、同時に決めておきたいのがマージの方式である。コミットを一つにまとめるスカッシュを既定にするのか、リベースしてからマージするのか、マージコミットを残すのか。チームごとに決めるものだが、この設定もプラットフォームごとに名前と場所が違う。移行のついでに文書に書き足しておくとよい。

まとめるとこうなる。PR と MR は同じものだ。違うのは名前ではなく、そのものに取り付けられたルールであり、そのルールは Git ではなくプラットフォームが握っている。