GitHub の画面との対応 — プルリクエスト

GitHub のリポジトリの画面に並んでいるもの(ファイルの一覧、main ▼ のボタン、「3 Commits」の数、コミットの短い ID)は、どれも GitHub 側のグラフの一部を見せています。この回では、画面の部品がグラフのどこに当たるかを確かめてから、プルリクエストを「ブランチ同士のマージの依頼」として読み解きます。GitHub の画面で Merge pull request を押すと GitHub 側のグラフだけが変わること、手元を追いつかせるには 2-3 の fetch と pull --ff-only を使うことを、1コマンドずつ見ていきます。

画面の見方
  • 左の上のターミナルは、実際に打ったときと同じ出力です(Git は英語で答えます)
  • その下に、グラフが2つ並びます。上が GitHub 側、下が手元です。同じコミットは、上と下で同じ横の位置に来ます
  • 手元のグラフの点線の札 origin/main は、手元に貼ってある GitHub 側の付箋の写しです。fetch や push をしたときにだけ、GitHub 側に合わせて貼り直されます
  • GitHub の画面で起きたこと(ボタンを押したなど)は、ターミナルには何も出ず、上の GitHub 側のグラフだけが変わります
  • 右の説明をスクロールして読み進めると、左のターミナルでコマンドが1つずつ打たれます。→ キーでも1つずつ進みます(← で1つ戻ります。スマホでは「次へ」ボタン)。黄色く光っているのが、そのコマンドで変わった場所です

1. リポジトリの画面は、GitHub 側のグラフのどこか

ここまでの3回で、GitHub 側にもグラフ(コミットと付箋)があり、手元はその写しを origin/main として持っている、という形を見てきました。GitHub のリポジトリの画面は、その GitHub 側のグラフを、1つのブランチから見た姿です。

リポジトリの画面は、GitHub 側のグラフを1つのブランチから見たもの どの部品も、いま選んでいるブランチ(ここでは main)の付箋から辿って表示している you / memo-app Code Pull requests 1 main ▼ 3 3 Commits 4 パンを追加 e5c0a62 2 todo.txt GitHub 側のグラフ memo 2 4 e5c0a62 1 main 3 main から親を辿れるコミット3つ
図1: 左がリポジトリの画面の部品、右が GitHub 側のグラフ。同じ番号どうしが対応している
番号画面の部品GitHub 側のグラフでは手元で同じものを見るなら
1ブランチの切り替え(main ▼)GitHub 側の付箋の一覧。選んだ付箋が、ほかの部品すべての起点になるgit branch -r(写しの一覧)
2Code タブのファイルの一覧選んだブランチの先頭のコミットの中身。最初は既定のブランチ(main)そのブランチに switch して ls
3「3 Commits」の数そのブランチの付箋から親を辿れるコミットの数git log --oneline origin/main の行数
4最新コミットの行の英数字先頭のコミットの短い ID(本物は40桁で、頭の7桁を見せている)git log --oneline -1 の先頭

「3 Commits」のような表示の言葉や置き場所は、GitHub の画面が変わるたびに少しずつ動きます。それでも、数えているものは変わりません。どの部品も、選んでいる付箋から辿った結果なので、main ▼ を memo に切り替えると、ファイルの一覧も数も ID も一斉に memo のものに変わります。

手元のコマンドで、この対応を確かめます。2-2 で作った作業用ブランチ memo(notes.txt を足した2つのコミット)を push するところから始めます。

GitHub のリポジトリの画面と、GitHub 側のグラフ

  1. 2-2 の続きです。作業用ブランチ memo を送ると、GitHub が remote: の行で、プルリクエストを作るための URL を返してきました。ブラウザでリポジトリを開くと、同じ案内が Compare & pull request のボタンになって出ます。

    $ git push -u origin memo
    remote: 
    remote: Create a pull request for 'memo' on GitHub by visiting:
    remote:      https://github.com/you/memo-app/pull/new/memo
    remote: 
    To https://github.com/you/memo-app.git
     * [new branch]      memo -> memo
    branch 'memo' set up to track 'origin/memo'.
  2. 手元に貼ってある、GitHub 側の付箋の写しの一覧です。GitHub の画面の ブランチの切り替え(main ▼) を開くと出る一覧と、同じ付箋を指しています。origin/HEAD -> origin/main は、既定のブランチが main だという印です。

    $ git branch -r
      origin/HEAD -> origin/main
      origin/main
      origin/memo
  3. origin/main から親を辿れるコミットは3つです。GitHub の画面で main を選んだときに出る 3 Commits は、この数です。

    $ git log --oneline origin/main
    e5c0a62 (origin/main, origin/HEAD, main) パンを追加
    8b41d07 卵を追加
    3f2a9c1 牛乳を追加
  4. memo から辿ると5つになります。親を辿ると main のコミットも含まれるので、GitHub の画面で memo を選ぶと 5 Commits と出ます。

    $ git log --oneline origin/memo
    6a1f3c8 (HEAD -> memo, origin/memo) 卵のメモを追加
    4d7b2e9 メモを追加
    e5c0a62 (origin/main, origin/HEAD, main) パンを追加
    8b41d07 卵を追加
    3f2a9c1 牛乳を追加
  5. いま乗っている memo の先頭のコミットには、notes.txt と todo.txt があります。GitHub の Code タブで memo を選んだときに並ぶファイルと同じです。

    $ ls
    notes.txt  todo.txt
  6. main に乗り換えて、作業ツリーを main の先頭のコミットの中身にします。

    $ git switch main
    Switched to branch 'main'
    Your branch is up to date with 'origin/main'.
  7. main の先頭には todo.txt しかありません。リポジトリを開いたときの Code タブは、既定のブランチ main のこの中身を見せています。

    $ ls
    todo.txt
  8. memo に戻ります。notes.txt は memo にしか無いので、リポジトリを開いただけでは見えません。これを main に入れてほしいと頼むのが、プルリクエストです。

    $ git switch memo
    Switched to branch 'memo'
    Your branch is up to date with 'origin/memo'.

notes.txt は GitHub に届いているのに、リポジトリを開いただけでは見えません。Code タブが既定のブランチ main を見せているからです。「届いたはずのファイルが GitHub に無い」と感じたら、まず main ▼ がどのブランチになっているかを見てください。

2. push -u のあとに出る「Compare & pull request」

1 のシーンの最初の git push -u origin memo では、ターミナルに remote: で始まる行が出ていました。この行は Git ではなく、GitHub が書いて送り返してきた案内です。

remote: Create a pull request for 'memo' on GitHub by visiting:
remote:      https://github.com/you/memo-app/pull/new/memo

「memo のプルリクエストを作るなら、この URL へ」という意味です。ブラウザでリポジトリを開くと、同じ案内が「memo had recent pushes」という帯と、Compare & pull request のボタンになって出ます。どちらも、「付箋 memo が新しく届いたので、main に取り込む依頼を出しますか」という誘いです。押さなければ何も起きません。帯はしばらくすると消えますが、Pull requests タブの New pull request からいつでも同じ画面に行けます。

3. プルリクエスト — 「このブランチを、あのブランチにマージしてほしい」

Compare & pull request を押すと、プルリクエストを作る画面が開きます。上の方に、こう並んでいます。

base: main  ←  compare: memo

これがプルリクエストの中身のすべてです。compare(memo)を、base(main)にマージしてほしいという依頼で、矢印の向きは「memo の変更が main に流れ込む」方向です。タイトルと説明を書いて Create pull request を押すと、依頼が GitHub に登録されて #1 のような番号が付きます。

ここで大事なのは、プルリクエストは Git のコマンドではなく、GitHub の機能だということです。git のどのコマンドにも pull request はありません(名前の似た git pull は、2-3 で見た fetch と取り込みのコマンドで、まったく別物です)。プルリクエストを作っても、GitHub 側のグラフにはコミットも付箋も増えません。増えるのは「依頼」と、それについての会話の記録だけです。

プルリクエストの画面には、タブがいくつか並びます。

タブ見せているもの手元で近いもの
Conversation依頼の説明・コメント・レビューのやりとり(Git には無い。GitHub だけの記録)
Commitsmemo にあって main に無いコミットgit log --oneline main..memo
Files changedマージしたら main がどう変わるかの差分git diff main...memo

Files changed は、main と memo の差分です。正確には「main と memo が分かれた地点から、memo の先頭までの差分」で、memo の側で何を変えたかだけが並びます。プルリクエストを出したあとに memo へコミットを足して push すると、同じプルリクエストの Commits と Files changed に自動で加わります。依頼の対象は「付箋 memo」なので、付箋が進めば依頼の中身も進むわけです。

Merge pull request は、GitHub 側にだけマージコミットを足す 押すと GitHub 側の main が進む。手元のグラフは、fetch するまで「押す前」のまま メモを追加 #1 base: main ← compare: memo Conversation Commits Files changed notes.txt + 牛乳は低脂肪 + 卵は10個入り Merge pull request ▼ ▼ でマージの方式を選べる 押す前(GitHub 側) memo main 押した後(GitHub 側) memo main
図2: 左がプルリクエストの画面の部品。右は、Merge pull request を押す前と後の GitHub 側のグラフ。マゼンタの丸が、押したときにできるマージコミット

4. Merge pull request を押すと — GitHub 側だけが変わる

依頼を受けた人(一人で開発しているなら自分)が Merge pull request を押すと、GitHub が GitHub 側のグラフの中でマージをします。既定の方式(Create a merge commit)では、次の2つが起きます。

  1. 親が2つのマージコミットを1つ作る。1つ目の親は main の先頭、2つ目の親は memo の先頭で、メッセージは Merge pull request #1 from you/memo になる
  2. GitHub 側の付箋 main を、そのマージコミットへ進める

手元のパソコンには、何も届きません。マージは GitHub の中で起きたことで、手元の main も、写しの origin/main も、押す前のコミットを指したままです。2-3 で「もう1台の PC から push された」場面を見ましたが、それと同じことが GitHub の画面から起きた、と考えると分かりやすくなります。

プルリクエストをマージしたあと、手元を追いつかせる

  1. プルリクエストを出した直後の状態です。GitHub 側も手元も、memo は main より2つ先に進んでいます。

    $ git log --oneline --all
    6a1f3c8 (HEAD -> memo, origin/memo) 卵のメモを追加
    4d7b2e9 メモを追加
    e5c0a62 (origin/main, origin/HEAD, main) パンを追加
    8b41d07 卵を追加
    3f2a9c1 牛乳を追加
  2. GitHub の画面で Merge pull request を押しました。GitHub 側に親が2つのマージコミット b7e40d2 ができて、GitHub 側の main がそこへ進みます。ターミナルには何も出ません。

  3. 手元のグラフは何も変わっていません。マージは GitHub の中で起きたことで、手元の origin/main はまだ古い写しのままです。

    $ git log --oneline --all
    6a1f3c8 (HEAD -> memo, origin/memo) 卵のメモを追加
    4d7b2e9 メモを追加
    e5c0a62 (origin/main, origin/HEAD, main) パンを追加
    8b41d07 卵を追加
    3f2a9c1 牛乳を追加
  4. git status も up to date と答えます。比べている相手は最後に写した origin/memo で、GitHub に問い合わせてはいないからです。

    $ git status
    On branch memo
    Your branch is up to date with 'origin/memo'.
    
    nothing to commit, working tree clean
  5. git fetch で写しを取り直すと、origin/main が e5c0a62 から b7e40d2 へ進みました。手元の main はまだ動きません。

    $ git fetch
    From https://github.com/you/memo-app
       e5c0a62..b7e40d2  main       -> origin/main
  6. マージコミットが手元のグラフにも出ました。origin/HEAD は、GitHub 側の既定のブランチ(ここでは main)を指す写しです。

    $ git log --oneline --all
    b7e40d2 (origin/main, origin/HEAD) Merge pull request #1 from you/memo
    6a1f3c8 (HEAD -> memo, origin/memo) 卵のメモを追加
    4d7b2e9 メモを追加
    e5c0a62 (main) パンを追加
    8b41d07 卵を追加
    3f2a9c1 牛乳を追加
  7. main に乗り換えると behind 'origin/main' by 3 commits と出ます。マージコミットと memo の2つのコミット、合わせて3つ遅れています。

    $ git switch main
    Switched to branch 'main'
    Your branch is behind 'origin/main' by 3 commits, and can be fast-forwarded.
      (use "git pull" to update your local branch)
  8. 手元の main の付箋を b7e40d2 まで進めます(Fast-forward)。notes.txt が main にも入りました。

    $ git pull --ff-only
    Updating e5c0a62..b7e40d2
    Fast-forward
     notes.txt | 2 ++
     1 file changed, 2 insertions(+)
     create mode 100644 notes.txt
  9. 手元の main の先頭が、GitHub で作られたマージコミットになりました。GitHub 側の main と手元の main が、同じコミットを指しています。残っている memo の片づけは、次の節で扱います。

    $ git log --oneline -3
    b7e40d2 (HEAD -> main, origin/main, origin/HEAD) Merge pull request #1 from you/memo
    6a1f3c8 (origin/memo, memo) 卵のメモを追加
    4d7b2e9 メモを追加

マージのあとに手元でやることは、2-3 の手順そのままです。fetch で写しを取り直し、main に乗り換えて git pull --ff-only で付箋を進める。手元の main は GitHub 側の main の後ろにまっすぐ並んでいるので、枝分かれは起きず、Fast-forward(付箋をそのまま前へずらすだけ)で追いつきます。

もう1つ気づいてほしいのは、この場面では GitHub 側の main がプルリクエストを出したあとに1つも進んでいなかったのに、マージコミットが作られたことです。手元で同じ形のマージをすると、Git は付箋をずらすだけで済ませ(Fast-forward)、マージコミットを作りません。GitHub の既定の方式は、いつでもマージコミットを作るようになっています。「いつ、どのプルリクエストを取り込んだか」がグラフに残るようにするためです。手元のマージがいつ Fast-forward になり、いつマージコミットになるかは、第3部の merge の回で扱います。

マージの方式はボタンの横で選べる

Merge pull request のボタンの横の ▼ を開くと、マージの方式を選べます。どれを選べるかはリポジトリの設定で決まり、この回で扱ったのは既定の1つ目だけです。

方式GitHub 側のグラフで起きることmemo の元のコミット
Create a merge commit親が2つのマージコミットを作り、main を進める(この回の動き)main から辿れる
Squash and mergememo の変更を1つにまとめた新しいコミットを作り、main を進める(親は1つ)main からは辿れない
Rebase and mergememo のコミットを main の先頭の上に作り直して並べる(ID が変わる)main からは辿れない

Squash と Rebase のときは、中身は同じでも ID の違うコミットが main に入ります。memo の元のコミットは main から辿れないので、手元の memo を git branch -d で消そうとすると、Git に「まだ取り込まれていない」と判断されて止まることがあります。どちらも第3部の rebase の回の内容とつながっているので、そこで改めて見ます。

5. Delete branch — GitHub 側の付箋を剥がすだけ

マージが終わると、プルリクエストの画面に Delete branch のボタンが出ます。押すと消えるのは、GitHub 側の付箋 memo だけです。memo のコミットは、マージコミットの2つ目の親として main から辿れるので、1つも消えません。グラフから付箋が1枚なくなるだけです。消した付箋は、同じ画面の Restore branch で貼り直せます。

手元はここでも何も変わりません。memo という名前は、3か所に別々に貼ってあるからです。

付箋Delete branch を押すと消すには
GitHub 側の memo消える(このボタンで消えた)
手元の写し origin/memo残るgit fetch --prune(GitHub 側に無くなった付箋の写しを剥がす)
手元の memo残るgit branch -d memo(取り込み済みのときだけ消える)

ふつうの git fetch は、GitHub 側で消えた付箋の写しを残したままにします。写しを片づけるのが git fetch --prune(-p とも書く。prune は「刈り込む」)です。4 のシーンの続きで、Delete branch を押してから3か所の memo を片づけるまでを見ます。

Delete branch のあと — fetch --prune で写しを片づける

  1. プルリクエストをマージして、手元の main も追いついたあとの状態です。手元の memo は、上流の origin/memo を追跡したままです。

    $ git branch -vv
    * main b7e40d2 [origin/main] Merge pull request #1 from you/memo
      memo 6a1f3c8 [origin/memo] 卵のメモを追加
  2. GitHub の画面で Delete branch を押しました。GitHub 側の付箋 memo が剥がれます。コミットはマージコミットの親として main から辿れるので、1つも消えません。

  3. git fetch を打っても、ここでは何も出ません。GitHub 側で消えた付箋の写し origin/memo は、手元に残ったままです。

    $ git fetch
  4. 手元の memo と remotes/origin/memo が残っています。Delete branch で消えたのは、GitHub 側の付箋だけです。

    $ git branch -a
    * main
      memo
      remotes/origin/HEAD -> origin/main
      remotes/origin/main
      remotes/origin/memo
  5. --prune(刈り込む)を付けると、GitHub 側に無くなった付箋の写しを剥がします。[deleted] の行が、origin/memo を剥がした印です。

    $ git fetch --prune
    From https://github.com/you/memo-app
     - [deleted]         (none)     -> origin/memo
  6. 手元の memo の上流が [origin/memo: gone] になりました。追跡していた写しが無くなった、という意味です。

    $ git branch -vv
    * main b7e40d2 [origin/main] Merge pull request #1 from you/memo
      memo 6a1f3c8 [origin/memo: gone] 卵のメモを追加
  7. -d は、まだ取り込まれていないコミットを持つブランチなら止まります。memo のコミットは main から辿れるので、剥がれたのは付箋だけです。

    $ git branch -d memo
    Deleted branch memo (was 6a1f3c8).
  8. 3か所に貼ってあった memo が、すべて片づきました。手元に残っているのは main と、その写しだけです。

    $ git branch -a
    * main
      remotes/origin/HEAD -> origin/main
      remotes/origin/main

写しが剥がれたあとの git branch -vv に出た [origin/memo: gone] は、「上流として追跡していた写しが無くなった」という印です。gone と出ているブランチは、GitHub 側ではもう片づいたブランチなので、手元でも消してよい候補になります。古い写しが残っていても害はありませんが、git branch -a の一覧が長くなっていきます。

6. Claude Code と gh pr create

Claude Code に「プルリクエストを作って」と頼むと、gh pr create というコマンドを打つことがあります。gh は GitHub CLI(GitHub の画面の操作をターミナルから行うための、GitHub 製の道具)で、git とは別のプログラムです。流れはだいたい次のとおりです。

  1. git switch -c ブランチ名 で作業用ブランチを作り、コミットを積む
  2. git push -u origin ブランチ名 で GitHub に送る(2-2 の内容)
  3. gh pr create --title "…" --body "…" で、そのブランチを main にマージする依頼を出す

3つ目は、ブラウザで Compare & pull request を押してタイトルを書くのと同じことです。GitHub にお願いを出しているだけで、手元のグラフも GitHub 側のグラフも変わりません。ただし、作ったプルリクエストはリポジトリを見られる人全員から見えます。公開リポジトリなら、世界中から見えます。

同じ gh でも、gh pr merge は Merge pull request のボタンを押すのと同じで、GitHub 側の main を進めます。--squash や --rebase を付けると方式が変わり、--delete-branch を付けると、GitHub 側と手元の両方のブランチを消します。gh pr view・gh pr list・gh pr diff は見るだけのコマンドです。

Windows のノート PC と Mac の2台で作業しているなら、片方でプルリクエストをマージしたあと、もう片方では手元の main が古いままです。作業を始める前に git fetch -q と git pull --ff-only を打つ習慣(2-3 で見たもの)が、ここでも効きます。

7. Claude Code の許可画面で見かけたら

この回で見たコマンドを、「何が変わるか・何が消えうるか」で並べるとこうなります。

コマンド何が起きるか消えうるもの
git fetch / git fetch -q手元の写し(origin/main など)を GitHub 側に合わせて貼り直す。手元のブランチと作業ツリーは動かないなし
git fetch --prune / git fetch -p上に加えて、GitHub 側で消えた付箋の写し(origin/memo など)を剥がす。手元のブランチは消えないなし
git pull --ff-only手元のブランチの付箋を、写しの位置までまっすぐ進める。枝分かれしていれば止まるなし(作業ツリーの書きかけが上書きされるなら止まる)
gh pr view / gh pr list / gh pr diffGitHub のプルリクエストを見るだけなし
gh pr createGitHub にプルリクエスト(マージの依頼)を出す。手元も GitHub 側のグラフも変わらないなし(ただし、リポジトリを見られる人全員から見える)
git branch -d ブランチ名手元の付箋を剥がす。まだ取り込まれていないコミットがあれば止まるなし
gh pr mergeGitHub 側でマージして、GitHub 側の main を進める注意 取り消すには、打ち消すコミットを足す(GitHub の Revert ボタンなど)後始末が要る
gh pr merge --delete-branchマージしたうえで、GitHub 側と手元のブランチを消す注意 手元のブランチに、まだ push していないコミットが残っていないかを先に確かめる

見分け方は、GitHub 側の main が動くかどうかです。gh pr create は依頼を出すだけなので、手元のグラフと同じく GitHub 側のグラフも動きません。gh pr merge は、そのリポジトリを使うすべての人の main を進めます。許可する前に、どのプルリクエストをどの方式でマージするのかを確かめてください。

まとめ

  • GitHub のリポジトリの画面は、GitHub 側のグラフを1つのブランチから見たもの。main ▼ は付箋の一覧、ファイルの一覧は先頭のコミットの中身、「N Commits」は親を辿れるコミットの数
  • プルリクエストは「compare のブランチを base のブランチにマージしてほしい」という依頼。Git のコマンドではなく GitHub の機能で、作ってもグラフは変わらない
  • Merge pull request を押すと、GitHub 側にだけ親が2つのマージコミットができて、GitHub 側の main が進む。手元は git fetch → git switch main → git pull --ff-only で追いつく
  • Delete branch は GitHub 側の付箋を剥がすだけ。手元の memo は git branch -d、写しの origin/memo は git fetch --prune で片づける
  • gh pr create は依頼を出すだけ。gh pr merge は GitHub 側の main を動かす

第2部では、手元のグラフの上に GitHub 側のグラフをもう1つ置いて、両者の間の行き来を見てきました。clone で GitHub 側のグラフを丸ごと写し(2-1)、push で手元のコミットを GitHub 側へ送り(2-2)、fetch で写しを取り直して pull で手元の付箋を進め(2-3)、プルリクエストで GitHub 側のブランチ同士をつなぐ(2-4)。どの操作も、どちらのグラフの、どの付箋が動くかを見れば読めます。

ここまでは、付箋がまっすぐ前に進めるときだけを扱ってきました。2台で別々にコミットして枝分かれしたとき、pull --ff-only は止まります。第3部では、枝分かれした歴史を1つにつなぐ git merge と、歴史を作り直して並べ替える git rebase を、同じグラフで1コマンドずつ見ていきます。