こんにちは、ブログ記事を書くのが約2年ぶりのruedapです。
さっそくですが、Pull Request(プルリクエスト)機能を使ったことはありますか?
GitHubの代表的な機能で、「pull req」や「PR」とも略されたりして、名前はよく聞きますよね。
この記事は、Gitはいちおう入門済みで、GitHubも使い始めたけど、Pull Request機能はまだ使ったことがない、そんな人に向けた 簡単な方のPull Request の入門記事です。
もう1つのPull Requestについて
Pull Request機能の解説としてよくあるのは「他の人のリポジトリを自分のGitHubアカウントにFork(コピー)してきて、変更を加えて、それを元のリポジトリに取り込んでもらうようにリクエストを送信する」といった感じのものではないでしょうか。
Pull Request = 最初にForkする、と。(以降、この方式のPull Requestを「Fork式」と呼びます)
私もGitHubを使い始めてからしばらくの間はそういうものだと思っていて、自分がPull Request機能を使うのは当分先になるだろうなぁと考えていました。
ところが、このブログ元でもあるqnyp社内において、複数人での開発を行うGitHub上のプロジェクト(リポジトリ)に参加するようになって、Forkしないタイプの「同じリポジトリを共有して、その中だけで行うPull Request」というものがあることを知りました。(以降、この方式を「リポジトリ共有式」と呼びます。これらの呼称は筆者が便宜上付けたものです)
※GitHubには、Fork & Pull Model / Shared Repository Model と書かれています。
リポジトリ共有式Pull Requestを行うには、そのGitHubリポジトリにプッシュする権限を持っていることが条件になりますが、Fork式に比べると操作が簡単でわかりやすく、多くの人にとってはこちらの方が日常的に使いやすいと思います。なぜなら自分の場合がそうで、前述のプロジェクトでリポジトリ共有式の方を覚えてから1年以上経ちますが、もう数え切れないほど繰り返しています。一方、Fork式の方は未だに片手で数えるほどしか使っていません。もし、あなたがデザイナーなどの非エンジニアであれば、特にその可能性が高いと言えそうです。
GitHub Flow
また、GitHub社も社内の開発では、リポジトリ共有式Pull Requestの方をメインで使っていると言っています。
GitHubでは誰もgithub/githubのフォークを持っていません。同じレポジトリのブランチ同士でプルリクエストを行なっています。
これに関連して、同社が提唱している、このPull Requestを中心にした開発スタイルとして知られているのがGitHub Flowです。qnypでもこの開発スタイルを採用しており、Webサービスやライブラリの開発だけでなく、このブログ(記事を含む)ですら、リポジトリ共有式のPull Requestを使って執筆・校正・運用をしています。
というわけで、まずはFork式より簡単なリポジトリ共有式Pull Requestの方を覚えて、GitHubをもっと活用してみましょう。
1人2役でPull Requestの練習をしてみよう
リポジトリ共有式のPull Requestは、自分のGitHubリポジトリ内で1人で練習できる点でも入門に向いています。その手順は以下の4ステップになります。
- GitHub上で、練習用のリポジトリを作成する
- ローカルで、Pull Request用のブランチを作成してpushする
- GitHub上で、Pull Requestを作成する
- GitHub上で、Pull Requestをマージする
手順1は練習のために必要な工程なので、Pull Requestの手順は2〜4の3ステップです。一般的にPull Requestは、リクエストを送る側(手順3)と受ける側(手順4)では別の人になりますが、今回は練習なのでどちらも自分自身で行います。ですので、送る側としてのリポジトリ共有式Pull Requestの手順は2〜3の2ステップだけですね。
それでは実践してみましょう。
1. GitHub上で、練習用のリポジトリを作成する
GitHub上に練習用のリポジトリを作成します。今回の名前は「pullreq」にします。
まず、GitHubにログインした状態でリポジトリ作成ページを開きます(下記画像)。「Repository name」に「pullreq」と入力して、「Initialize this repository with a README」のチェックをオンにして、「Create repository」ボタンを押します。
すると、下記のように「pullreq」のリポジトリがGitHub上に作成されるので、矢印で指しているGitHubリポジトリのアドレス部分をコピーします。
そして、そのアドレスを使って、GitHub上に作成したpullreqのリポジトリを自分のローカルにclone
します。
$ git clone git@github.com:【あなたのGitHubアカウント名】/pullreq.git
$ cd pullreq
これでPull Requestを練習するための準備が整いました。
2. ローカルで、Pull Request用のブランチを作成してpushする
ここからがリポジトリ共有式Pull Requestの手順になります。
前述のキャプチャ画像内でも少し触れていますが、今回のPull Requestの目的は、以下のようにしてみましょう。
README.md
ファイル内の見出しの「pullreq」部分を、もっとかっこよくするために「Hello, Pull Request」という文字列に変更する
この内容のPull Requestを作って、手順1で作成したGitHubリポジトリにリクエストを送信します。そのために、Gitの「ブランチ」という機能を使います。ここではブランチ機能を理解できているものとして話を進めますが、もし自信がなければ、こちらのブランチ解説ページがわかりやすくて復習にオススメです。
それでは、Pull Request用ブランチを作成してpush
するところまで進めましょう。現在はpullreqのリポジトリをclone
しただけなので、master
ブランチにいる状態です。
$ git branch # 現在のブランチを確認
* master
ここから、Pull Request用のupdate-readme
ブランチを作成して、README.md
内の見出しをかっこよく「Hello, Pull Request」に変更し、それをコミットして、さらにリモート(GitHubリポジトリ)にpush
します。
$ git checkout -b update-readme # Pull Request用ブランチを作成
$ echo "# Hello, Pull Request" > README.md # 見出しを変更
$ git add README.md # 変更をadd
$ git commit -m "Update README.md" # 変更をcommit
$ git push origin update-readme # リモートにpush
To git@github.com:【あなたのGitHubアカウント名】/pullreq.git
* [new branch] update-readme -> update-readme
push
後に、上記のログが出ていれば大丈夫です。
3. GitHub上で、Pull Requestを作成する
もう一息です、頑張りましょう。ここからはGitHub上での操作になります。
手順1でGitHub上に作成したpullreqのリポジトリページを開くと、手順2でpush
したupdate-readme
ブランチに関する情報が表示されているはずです。そこに表示されているCompare & pull requestボタンを押すと、Pull Request作成ページに移動できます。
Pull Request作成ページでは、リクエストを送信する相手(通常はリポジトリの管理者)に、どういった変更を加えたのかを説明する内容を記入します。
説明文を記入できたら、画面下部に表示されている実際のコミット内容もチェックして、誤りがないかをチェックします。大丈夫そうなら「Send pull request」ボタンを押して、Pull Requestを送信します。
おめでとうございます! これでPull Requestが送信されました。送信後のページでは、今作成したPull RequestがOpen状態になって表示されていると思います。
これ以降は、リポジトリの管理者がこのPull Requestに対してレスポンスを返してくれるのを待つのみです。内容が良ければそのままマージされることもありますし、修正や議論が必要であれば上記のページでメッセージを書き込んだり、コードを追加・修正してやり取りすることになります。時にはマージされずにCloseされることもあります。
今回は、自分でリポジトリ管理者役も兼ねることで、マージを試してみましょう。
4. GitHub上で、Pull Requestをマージする
それではリポジトリ管理者になったつもりで、送られてきたPull Requestを確認します。
GitHub上での確認は、Pull Requestページの上部にある「Commits」タブや「Files Changed」タブに切り替えてコミット内容をチェックします。ローカルでの動作確認が必要な場合は、fetch
して該当するブランチをcheckout
して確認します。
$ git fetch # 変更を取得
$ git branch -a # ブランチを確認
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/update-readme
$ git checkout -b update-readme origin/update-readme # チェックアウト
# ここから動作確認
※今回の練習では、手順3で既にupdate-readmeブランチが存在しているので、上記のGitの手順は必要ありません。実際に他の人からPull Requestを受けた時に必要になります。
良さそうであれば、「Merge pull request」ボタンを使ってマージを実行します。
マージを実行すると、GitHub上でupdate-readme
ブランチからmaster
ブランチへのマージが行われます。また、マージ済みのブランチを削除する「Delete branch」ボタンが出現します。通常は元のブランチは不要になるので、遠慮なくボタンを押します。
マージ後に、pullreqリポジトリのトップページ(master
ブランチ)を表示すると、Pull Requestの変更をmasterブランチに取り込んだことによってREADME.md
の見出しがかっこよくなっていることを確認できます。
おつかれさまでした。以上で、リポジトリ共有式Pull Requestの練習はおわりです。
リポジトリ共有式Pull Requestの注意点
冒頭で述べたとおり、リポジトリ共有式を行えるということは、そのリポジトリのプッシュ権限を持っているということです。これはすなわち、リモートのmaster
ブランチに直接push
できる、ということです。ですので、複数人開発でリポジトリ共有式を使う際の注意点としては、誤操作や独断によるmaster
ブランチへのpush
をしないことが挙げられます。裏を返せば、リポジトリ管理者から見てそういうことをしなさそうに思ってもらえたら、プッシュ権限を与えてもらえるかも、と言えます。
今回説明しなかったFork式の方は、そのプッシュ権限が与えられていない場合のためのPull Request方法ですので、上記の注意は必要ありません。代わりに、リポジトリ共有式に比べてPull Requestの手順がやや複雑になっています。
まとめ
GitHub上で自由に閲覧できるオープンソースプロジェクトでは、実際にやり取りされているPull RequestのほとんどがFork式に見えますし、また、Pull Requestの方法についてネットで検索してもFork式の方の解説記事が多いので、前述の自分のようにオープンソース以外のプロジェクトに参加してみたりしないと、もう1つのPull Requestについて知るキッカケがないかもしれません。
ですが、Fork式に比べてリポジトリ共有式は手順がシンプルで、入門にも向いてます。 さきほど挙げた注意点だけはクリアできるようになることが重要ですが、これについては今回紹介した練習の手順をベースに、まずは自分のGitHubリポジトリで日頃からリポジトリ共有式Pull Requestを使っていくことで十分にクリアが可能だと思います。
例えば、私が個人で公開しているWebサービスのGitHubリポジトリでは、自分でPull Requestを作って自分でマージしています。自作自演ならぬ自プルリ自マージです。こういった方法で、Pull Requestを送る側・受ける側の両方に慣れておくことができる点でも、このForkしない方のPull Requestから入門してみることをオススメします。