プルリクエストをリベースして更新する方法
紹介
オープンソースプロジェクトに貢献することは、自分のようなエンドユーザーのためにソフトウェアをより良くするために取り組む貴重な経験です。プルリクエストを提出すると、プロジェクトに貢献するプロセスでは、受け入れられる前にコードのリベースや再作業が必要になることがあり、その後はブランチの一般的なクリーンアップが必要です。
このチュートリアルは、オープンソースソフトウェアプロジェクトにプルリクエストを提出した後に必要になるかもしれない次のステップのいくつかを案内します。
前提条件
このチュートリアルでは、プルリクエストを作成した後に行う手順を説明します。したがって、すでにGitがインストールされている必要があり、プルリクエストを作成したか、作成を考えている必要があります。
2020年11月現在、GitHubはパスワードベースの認証を削除しました。このため、コマンドラインを通じてGitHubリポジトリにアクセスするには、パーソナルアクセストークンを作成するか、SSH公開鍵の情報を追加する必要があります。
オープンソースプロジェクトへの貢献についてもっと学ぶには、この紹介を読むことができます。プルリクエストの作成について学ぶには、「GitHubでプルリクエストを作成する方法」を読むことができます。
コードのリベースとコメントの整理
オープンソースに貢献している間に、あなたのブランチやプルリクエストとアップストリームコードの間に競合が生じることがあります。その場合、シェルで次のようなエラーが表示されることがあります:
CONFLICT (content): Merge conflict in your-file.py
Automatic merge failed; fix conflicts and then commit the result.
または、GitHubのウェブサイト上であなたのプルリクエストにこのように:
これは、メンテナーがしばらくあなたのプルリクエストに応答しない場合や、多くの人が同時にプロジェクトに貢献している場合に発生することがあります。このような場合にまだプルリクエストをマージしたい場合は、競合を解決し、コードをリベースする必要があります。
リベースは、基づくコミットを変更することによってブランチを移動させることができます。この方法で、最新のコミットに基づくようにコードをリベースすることができます。リベースは慎重に行うべきであり、プロセスの間ずっと正しいコミットと正しいブランチを扱っていることを確認する必要があります。また、エラーを犯した場合に備えて、以下でgit reflogコマンドの使用についても説明します。
プルリクエストのチュートリアルで行ったように、コードディレクトリに移動します:
- cd repository
次に、git checkout コマンドを使用して正しいブランチに移動していることを確認します。
- git checkout new-branch
次に、最新のアップストリーム版のコードを取得するためにgit fetchを実行します:
- git fetch origin
プロジェクトの上流バージョンを取得したら、コミットメッセージをまとめたり、言い回しを変えたりして、プロジェクトメンテナーにとって理解しやすくすることで、コメントを整理できます。もし多くの小さなコミットを行っていなければ、これは必ずしも必要ではありません。
このプロセスを始めるには、インタラクティブリベースを実行します。インタラクティブリベースは、以前のコミットメッセージを編集したり、いくつかのコミットを一つにまとめたり、もはや必要ないコミットを削除または戻したりするために使用できます。これを行うためには、私たちが行ったコミットを番号またはブランチの基盤を参照する文字列で参照できる必要があります。
私たちが行ったコミットの数を確認するために、次のコマンドを使用してプロジェクトに行われたコミットの総数を調べることができます:
- git log
これにより、次のような出力が得られます:
commit 46f196203a16b448bf86e0473246eda1d46d1273
Author: username-2 <email-2>
Date: Mon Dec 14 07:32:45 2015 -0400
Commit details
commit 66e506853b0366c87f4834bb6b39d941cd034fe3
Author: username1 <email-1>
Date: Fri Nov 27 20:24:45 2015 -0500
Commit details
ログには、指定されたプロジェクトのリポジトリに対して行われたすべてのコミットが表示されるため、あなたのコミットは他の人によるコミットと一緒に一覧表示されます。複数の著者による広範なコミット履歴があるプロジェクトの場合、コマンドで自分を著者として指定する必要があります:
- git log --author=your-username
このパラメータを指定することで、あなたが行ったコミットの数をカウントできるはずです。複数のブランチで作業している場合は、コマンドの最後に --branches[=<branch>] を追加することで、ブランチで制限できます。
もしリベースしたいブランチで行ったコミットの数がわかっているなら、次のようにgit rebaseコマンドを実行できます:
- git rebase -i HEAD~x
ここで、-iはインタラクティブなリベースを指し、HEADはメインブランチの最新コミットを指します。xは、最初に取得してからブランチに加えたコミットの数になります。
ただし、ブランチで何回コミットしたか分からない場合は、どのコミットがあなたのブランチのベースであるかを見つける必要があります。それは次のコマンドを実行することで確認できます:
- git merge-base new-branch main
このコマンドは、以下のようなコミットハッシュとして知られる長い文字列を返します:
66e506853b0366c87f4834bb6b39d341cd094fe9
このコミットハッシュをgit rebaseコマンドに渡すために使用します:
git rebase -i 66e506853b0366c87f4834bb6b39d341cd094fe9
上記のいずれかのコマンドを実行すると、コマンドラインのテキストエディタが開き、あなたのブランチ内のすべてのコミットの一覧を含むファイルが表示されます。ここで、コミットをまとめるか、再度表現するかを選択できます。
コミットをまとめる
コミットメッセージをスカッシュするとき、私たちはいくつかの小さなコミットを1つの大きなコミットにスカッシュまたは統合しています。
各コミットの前には「pick」という言葉が表示されるので、もし2つのコミットがあれば、あなたのファイルはこのように見えるでしょう:
pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature
Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))
さて、ファイルの最初の行を除く各行に対して、「pick」という単語を「squash」という単語に置き換えて、コミットを統合する必要があります:
pick a1f29a6 Adding a new feature
squash 79c0e80 Here is another new feature
この時点で、ファイルを保存して閉じることができ、すべてのコミットのコミットメッセージを統合した新しいファイルが開きます。必要に応じてコミットメッセージの言葉を変更し、ファイルを保存して閉じることができます。
ファイルを閉じたらフィードバックを受け取ります:
Successfully rebased and updated refs/heads/new-branch.
あなたは今、すべてのコミットをまとめて一つにすることで、それらを圧縮しました。
コミットを言い換える
コミットメッセージを言い換えることは、タイプミスに気づいたときや、各コミットにパラレルな言語を使用していなかったことを認識したときに素晴らしいです。
上記で説明したように git rebase -i コマンドを使用してインタラクティブリベースを実行すると、次のようなファイルが開きます:
pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature
Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))
今、再表現したい各コミットについて、「pick」という単語を「reword」に置き換えてください。
pick a1f29a6 Adding a new feature
reword 79c0e80 Adding a second new feature
Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))
ファイルを保存して閉じると、コミットメッセージの修正された内容を表示する新しいテキストファイルがターミナルエディタに表示されます。もう一度ファイルを編集したい場合は、ファイルを保存して閉じる前に行うことができます。これにより、コミットメッセージが有用で一貫性があることを確保できます。
リベースを完了させてください
コミットの数と関連するコミットメッセージに満足したら、ブランチのリベースをプロジェクトの最新のアップストリームコードの上に完了するべきです。そのためには、リポジトリのディレクトリからこのコマンドを実行する必要があります:
- git rebase origin/main
この時点で、Gitはあなたのコミットをメインの最新バージョンに再生し始めます。この間に衝突が発生した場合、Gitは続行する前に衝突を解決するように促すために一時停止します。解決する必要がない場合、出力には次のように表示されます:
Current branch new-branch is up to date.
競合を解決したら、次のコマンドを実行します:
- git rebase --continue
このコマンドは、Gitにコミットの再生を続行できることを示します。
以前に squash コマンドを使用してコミットを統合した場合、一度だけ競合を解決する必要があります。
強制プッシュでプルリクエストを更新する
リベースを実行すると、ブランチの履歴が変更され、直接のパスが変更されたため、git push コマンドを使用できなくなります。
代わりに、--force または -f フラグを使用して、変更を強制プッシュする必要があります。Gitに対して、プッシュしている内容を完全に理解していることを伝えます。
まず、Git 2.0以降のデフォルトである simple に push.default を設定していることを確認しましょう:
- git config --global push.default simple
この段階で、私たちは作業しているブランチをチェックアウトして、正しいブランチにいることを確認すべきです。
- git checkout new-branch
Already on 'new-branch'
. . .
さあ、フォースプッシュを実行できます:
- git push -f
今、あなたはアップデートのフィードバックを受け取るべきです。それには、これは強制更新であったというメッセージが含まれています。あなたのプルリクエストは現在更新されました。
失われたコミットの復元
もし途中で大きなプロジェクトに統合したいと本当に思っていたコミットを消してしまった場合、誤って消してしまったコミットをGitを使って復元できるはずです。
git reflog コマンドを使用して失われたコミットを見つけ、そこから新しいブランチを作成します。
Reflogはリファレンスログの略で、ローカルリポジトリ内のブランチの先端やその他のリファレンスが最後に更新された時刻を記録します。
私たちが作業しているコードリポジトリのローカルディレクトリから、次のコマンドを実行します:
- git reflog
このコマンドを実行すると、以下のような出力が得られます:
46f1962 HEAD@{0}: checkout: moving from branch-1 to new-branch
9370d03 HEAD@{1}: commit: code cleanups
a1f29a6 HEAD@{2}: commit: brand new feature
38f2fc2 HEAD@{3}: commit: remove testing methods
. . .
あなたのコミットメッセージは、どのコミットが後に残されたものなのかを教えてくれます。そして、関連する文字列は、ターミナルウィンドウの左側でHEAD@{x}情報の前に表示されます。
今、その情報を使って関連するコミットから新しいブランチを作成できます。
git checkout -b new-new-branch a1f29a6
上の例では、上に表示されている第三のコミットから新しいブランチを作成しました。このコミットは「全く新しい機能」を展開したもので、文字列a1f29a6で表されています。
ここから何をする必要があるかによりますが、このプルリクエストに関するチュートリアルの手順に従ってブランチを設定することもできますし、現在のチュートリアルのトップに戻って新しいブランチのリベース作業を進めることもできます。
注意: 最近、git gcコマンドを実行して不要なファイルをクリーンアップし、ローカルリポジトリを最適化した場合、失われたコミットを復元できない可能性があります。
コードレビューで期待すること
プルリクエストを提出すると、大きなプロジェクトとの対話に参加していることになります。プルリクエストを提出することは、自分の作業について他の人々と話し合うことを招いているのと同様に、自分自身がより大きなプロジェクトに関して話し合い、関与していることでもあります。成功した会話を持つためには、あなたのコミットメッセージを通じて、プルリクエストを作成している理由を伝えることが重要ですので、できるだけ正確で明確であることが最善です。
プルリクエストのレビューは、プロジェクトによって長く詳細なものになる場合があります。このプロセスは学びの経験として考えるのが最善であり、あなたがコードを改善し、プルリクエストをより良くし、ソフトウェアプロジェクトのニーズに沿ったものにする良い方法です。レビューを通じて、メンテイナーのアドバイスや指示によって自分で変更を行うことができるようにするべきです。
プルリクエストは、レビュアーからのメモや、一緒に行う更新や議論のログを記録します。このプロセスの間に、プルリクエストが受け入れられる前にいくつかの追加コミットを行う必要があるかもしれません。これは完全に普通のことで、チームの一員として改訂に取り組む良い機会を提供します。
あなたのプルリクエストはGitを通じて維持され続け、プロセス全体にわたって自動的に更新されます。これは、同じブランチにコミットを追加し、それをフォークにプッシュし続ける限りです。
あなたのコードを仲間のレビューのために大きな世界に公開しているにもかかわらず、レビューが個人的なものだと感じるべきではありません。したがって、関連するCONTRIBUTION.mdファイルや行動規範を必ず読んでください。あなたのコミットがプロジェクトによって指定されたガイドラインに従っていることを確認することは重要ですが、もし不快に感じ始めた場合、あなたが取り組んでいるプロジェクトはあなたの貢献に値しないかもしれません。オープンソースコミュニティには多くの歓迎されるスペースがあり、あなたのコードには批判的な目が向けられることを期待できますが、受け取るフィードバックはすべてプロフェッショナルで礼儀正しいものであるべきです。
プルリクエストの受け入れとブランチの削除
あなたのプルリクエストが受け入れられた場合、あなたはオープンソースソフトウェアプロジェクトに成功裏に貢献したことになります!
この時点で、ローカルリポジトリを通じて、あなたのフォークに加えた変更を取り込む必要があります。これは、フォークを同期させる過程を通ったときにすでに行ったことです。次のコマンドをターミナルウィンドウで実行することで、これを行うことができます:
- git checkout main
- git pull --rebase origin main
- git push -f origin main
さて、もう必要なくなったため、両方の場所で作成したブランチを削除して、ローカルおよびリモートブランチの両方を整理する必要があります。最初に、ローカルブランチを削除しましょう:
- git branch -d new-branch
git branch コマンドに追加された -d フラグは、コマンドに渡したブランチを削除します。上の例では、それは new-branch と呼ばれています。
次に、リモートブランチを削除します。
- git push origin --delete new-branch
ブランチが削除されたことで、リポジトリは整理され、あなたの変更はメインリポジトリに反映されました。プルリクエストを通じて行った変更がメインリポジトリの一部となったため、それらの変更が一般のユーザーが公開リリースをダウンロードする際に利用できない可能性があることを念頭に置いておくべきです。一般的に、ソフトウェアのメンテナーは、いくつかの新機能や修正をまとめて1つの公開リリースに組み込みます。
結論
このチュートリアルでは、オープンソースソフトウェアリポジトリにプルリクエストを提出した後に必要になるかもしれないいくつかの次のステップについて説明しました。
オープンソースプロジェクトに貢献すること、そしてアクティブなオープンソース開発者になることは、多くの場合、やりがいのある経験です。よく使うソフトウェアに定期的に貢献することで、そのソフトウェアがユーザーコミュニティにとって価値があり、有用であることを確保する手助けとなります。

