プルリクエストをリベースおよび更新する方法

前書き

オープンソースプロジェクトへの貢献は、あなたのようなエンドユーザーにとってソフトウェアをより良くするために努力するときのやりがいのある経験です。 プルリクエストを送信すると、プロジェクトに貢献するプロセスでは、承認前にコードのリベースとリワークが必要になる場合があります。その後、ブランチの一般的なクリーンアップが行われます。

このチュートリアルでは、pull requestをオープンソースソフトウェアプロジェクトに送信した後に実行する必要のある次の手順のいくつかについて説明します。

前提条件

このチュートリアルでは、プルリクエストを行った後に実行する手順を説明します。したがって、すでにGitがインストールされており、プルリクエストを作成したか、作成を検討している必要があります。

オープンソースプロジェクトへの貢献について詳しくは、this introductionをご覧ください。 プルリクエストの作成については、「https://www.digitalocean.com/community/tutorials/how-to-create-a-pull-request-on-github[GitHubでプルリクエストを作成する方法]」を参照してください。 」

オープンソースに貢献している間、ブランチまたはプルリクエストとアップストリームコードとの間に矛盾があることがわかります。 シェルで次のようなエラーが表示される場合があります。

OutputCONFLICT (content): Merge conflict in your-file.py
Automatic merge failed; fix conflicts and then commit the result.

または、GitHubのWebサイトからのプルリクエストで次のようになります。

GitHub pull request conflicts

これは、メンテナーがしばらくの間プル要求に応答しない場合、または多くの人が一度にプロジェクトに貢献している場合に発生する可能性があります。 これが発生し、プルリクエストをマージしたい場合は、競合を解決してコードをリベースする必要があります。

rebaseを使用すると、ブランチの基になっているコミットを変更することで、ブランチを移動できます。 このようにして、masterブランチの最近のコミットに基づいてコードをリベースできます。 リベースは慎重に行う必要があり、プロセス全体を通して適切なコミットと適切なブランチで作業していることを確認する必要があります。 エラーが発生した場合に備えて、git reflogコマンドbelowの使用についても説明します。

pull request tutorialで行ったように、コードディレクトリに移動して、コードの最新のアップストリームバージョンをフェッチします。

cd repository
git fetch upstream

プロジェクトのアップストリームバージョンを取得したら、コミットメッセージを押しつぶすか言い直してコメントをクリーンアップし、プロジェクトメンテナがより理解しやすいようにします。 多くの小さなコミットを行わなかった場合、これは必要ないかもしれません。

このプロセスを開始するには、インタラクティブなリベースを実行します。 interactive rebaseを使用して、以前のコミットメッセージを編集したり、複数のコミットを1つに結合したり、不要になったコミットを削除または元に戻したりできます。 これを行うには、番号またはブランチのベースを参照する文字列で行ったコミットを参照できる必要があります。

行ったコミットの数を調べるには、次のコマンドを使用して、プロジェクトに対して行われたコミットの総数を調べることができます。

git log

これにより、次のような出力が得られます。

Outputcommit 46f196203a16b448bf86e0473246eda1d46d1273
Author: username-2 
Date:   Mon Dec 14 07:32:45 2015 -0400

    Commit details

commit 66e506853b0366c87f4834bb6b39d941cd034fe3
Author: username1 
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 master

このコマンドは、コミットハッシュと呼ばれる次のような長い文字列を返します。

Output66e506853b0366c87f4834bb6b39d341cd094fe9

このコミットハッシュを使用して、git rebaseコマンドに渡します。

git rebase -i 66e506853b0366c87f4834bb6b39d341cd094fe9

上記のコマンドのいずれについても、ブランチ内のすべてのコミットのリストを含むファイルを使用してコマンドラインテキストエディターが開き、コミットを圧縮するか、または書き直すかを選択できるようになりました。

スカッシュコミット

コミットメッセージを押しつぶすときは、いくつかの小さなコミットを1つの大きなコミットに押しつぶすか結合します。

各コミットの前に「ピック」という単語が表示されるため、2つのコミットがある場合、ファイルは次のようになります。

GNU nano 2.0.6ファイル:…username / repository / .git / rebase-merge / git-rebase-todo

pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

ここで、最初の行を除くファイルの各行について、「pick」という単語を「squash」という単語に置き換えて、コミットを結合する必要があります。

GNU nano 2.0.6ファイル:…username / repository / .git / rebase-merge / git-rebase-todo

pick a1f29a6 Adding a new feature
squash 79c0e80 Here is another new feature

この時点で、ファイルを保存して閉じることができます。これにより、すべてのコミットのすべてのコミットメッセージを結合する新しいファイルが開きます。 コミットメッセージを適切に書き換えて、ファイルを保存して閉じることができます。

ファイルを閉じると、フィードバックを受け取ります。

OutputSuccessfully rebased and updated refs/heads/new-branch.

これで、すべてのコミットをまとめて1つにまとめました。

コミットの書き換え

タイプミスに気づいたとき、またはコミットのそれぞれに並列言語を使用していないことに気付いたときに、コミットメッセージを言い換えることは素晴らしいことです。

上記のようにgit rebase -iコマンドを使用してインタラクティブなリベースを実行すると、次のようなファイルが開きます。

GNU nano 2.0.6ファイル:…username / repository / .git / rebase-merge / git-rebase-todo

pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

ここで、言い換える各コミットについて、「pick」という単語を「reword」に置き換えます。

GNU nano 2.0.6ファイル:…username / repository / .git / rebase-merge / git-rebase-todo

pick a1f29a6 Adding a new feature
reword 79c0e80 Adding a second new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

ファイルを保存して閉じると、ターミナルエディタに新しいテキストファイルが表示され、コミットメッセージの修正された文言が表示されます。 ファイルを再度編集する場合は、ファイルを保存して閉じる前に編集できます。 これにより、コミットメッセージが有用で統一されたものになります。

リベースを完了する

作成するコミットの数と関連するコミットメッセージに満足したら、プロジェクトのアップストリームコードの最新バージョンの上にブランチのリベースを完了する必要があります。 これを行うには、リポジトリのディレクトリから次のコマンドを実行する必要があります。

git rebase upstream/master

この時点で、Gitはコミットを最新バージョンのマスターにリプレイし始めます。 これが発生している間に競合が発生した場合、Gitは一時停止して続行する前に競合を解決するように促します。

競合を修正したら、次を実行します。

git rebase --continue

このコマンドは、コミットの再生を継続できることをGitに示します。

以前にsquashコマンドを使用してコミットを結合した場合、競合を解決する必要があるのは1回だけです。

強制プッシュを使用したプル要求の更新

リベースを実行すると、ブランチの履歴が変更され、ダイレクトパスが変更されたため、git pushコマンドを使用できなくなります。

代わりに、--forceまたは-fフラグを使用して変更を強制的にプッシュし、プッシュしている内容を完全に認識していることをGitに通知する必要があります。

まず、push.defaultsimpleであることを確認しましょう。これは、Git 2.0以降のデフォルトです。

git config --global push.default simple

この時点で、作業中のブランチをチェックアウトして、正しいブランチにいることを確認する必要があります。

git checkout new-branch
OutputAlready on 'new-branch'
. . .

これで、強制プッシュを実行できます。

git push -f

これで、これがforced updateであるというメッセージとともに、更新のフィードバックを受け取るはずです。 これで、プルリクエストが更新されました。

失われたコミットの回復

ある時点で、より大きなプロジェクトに統合したいコミットを破棄した場合、Gitを使用して、誤って破棄した可能性のあるコミットを復元できるはずです。

git reflogコマンドを使用して、欠落しているコミットを見つけ、そのコミットから新しいブランチを作成します。

Reflogは、ブランチのヒントやその他の参照がローカルリポジトリ内で最後に更新された日時を記録するreference logsの略です。

作業中のコードリポジトリのローカルディレクトリから、次のコマンドを実行します。

git reflog

このコマンドを実行すると、次のような出力が表示されます。

Output46f1962 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

上記の例では、上記の3番目のコミットから新しいブランチを作成しました。これは、文字列a1f29a6で表される「まったく新しい機能」をロールアウトしたものです。

ここから何をする必要があるかに応じて、this tutorial on pull requestsでブランチを設定する手順に従うか、top of the current tutorialに戻って新しいブランチのリベースを行うことができます。

[.note]#Note:最近git gcコマンドを実行して不要なファイルをクリーンアップし、ローカルリポジトリを最適化した場合、失われたコミットを復元できない可能性があります。

コードレビューで何を期待するか

プルリクエストを送信すると、より大きなプロジェクトと対話します。 プルリクエストを送信することは、あなた自身がより大きなプロジェクトについて話し、関与しているのと同じように、他の人にあなたの仕事について話すように誘います。 会話を成功させるには、プルリクエストを行っているwhyをコミットメッセージで伝達できることが重要です。そのため、できるだけ正確で明確にすることが最善です。

プロジェクトによっては、プルリクエストのレビューに時間がかかり、詳細になる場合があります。 このプロセスを学習体験と考え、コードを改善し、プルリクエストをソフトウェアプロジェクトのニーズに合わせて改善するための良い方法と考えるのが最善です。 このレビューでは、メンテナーのアドバイスと指示により、自分で変更を加えることができるはずです。

プルリクエストは、レビュアーからのメモのログと、一緒に行った更新やディスカッションを保持します。 プルリクエストが受け入れられる前に、このプロセス全体でいくつかの追加のコミットが必要になる場合があります。 これは完全に正常な動作であり、チームの一員として改訂作業を行う良い機会となります。

プルリクエストはGitを通じて維持され、同じブランチにコミットを追加し、それらをフォークにプッシュし続ける限り、プロセス全体で自動更新されます。

同僚によるレビューのためにコードをより広い世界に公開していますが、レビューが個人的なものになっていると感じさせてはいけません。関連するCONTRIBUTION.mdファイルまたは行動規範を必ず読んでください。 コミットがプロジェクトで指定されたガイドラインに沿っていることを確認することが重要ですが、不快に感じ始めた場合、作業中のプロジェクトは貢献に値しないかもしれません。 オープンソースコミュニティには多くの歓迎スペースがあり、批判的な目でコードを見ることが期待できますが、受け取るフィードバックはすべて専門的で礼儀正しいものでなければなりません。

プルリクエストの受け入れとブランチの削除

おめでとうございます。 プルリクエストが受け入れられた場合、オープンソースソフトウェアプロジェクトへの貢献が成功しました!

この時点で、ローカルリポジトリを介して、行った変更をフォークに戻す必要があります。 これは、sync your forkへのプロセスを実行したときにすでに行ったことです。 これは、ターミナルウィンドウで次のコマンドを使用して実行できます。

git checkout master
git pull --rebase upstream master
git push -f origin master

ここで、ローカルとリモートの両方のブランチが不要になったため、両方の場所で作成したブランチを削除して、クリーンアップする必要があります。 まず、ローカルブランチを削除しましょう。

git branch -d new-branch

git branchコマンドに追加された-dフラグは、コマンドに渡したブランチを削除します。 上記の例では、new-branchと呼ばれています。

次に、リモートブランチを削除します。

git push origin --delete new-branch

ブランチを削除すると、リポジトリがクリーンアップされ、変更がメインリポジトリに反映されます。 プルリクエストで行った変更がメインリポジトリの一部になったからといって、パブリックリリースをダウンロードしている平均的なエ​​ンドユーザーが利用できない場合があることに留意してください。 一般的に、ソフトウェアメンテナーはいくつかの新しい機能と修正プログラムを1つのパブリックリリースにまとめます。

結論

このチュートリアルでは、pull requestをオープンソースソフトウェアリポジトリに送信した後に完了する必要のある次の手順のいくつかについて説明しました。

オープンソースプロジェクトに貢献すること、そしてアクティブなオープンソース開発者になることは、しばしばやりがいのある経験です。 頻繁に使用するソフトウェアに定期的に貢献することは、ユーザーのコミュニティにとって価値があり、有用であることを保証するのに役立ちます。