DUICUO

GitHub でプル リクエストをエレガントに送信する方法を段階的に説明する 10,000 語のガイドです。

I. 概要

通常の PR マージ プロセスに加えて、競合、コミットの追加の必要性、PR 送信後のコミットのマージの必要性など、比較的複雑な問題を解決する方法についても詳しく説明する予定です。

この記事は、主に以下の 4 つの部分に分かれて構成されています。

  1. なぜオープンソース プロジェクトに参加する必要があるのか​​、また PR (Public Retrieval) リクエストの送信方法を紹介します。
  2. オープンソース プロジェクトを始める方法、つまり、適切なオープンソース プロジェクトを見つける方法と、貢献する方法を見つける方法について説明します。
  3. このガイドでは、フォークからプッシュまでの PR プロセスを開始する方法について説明します。
  4. このセクションでは、PR の送信後に発生するさまざまな一般的な問題を解決する方法を紹介します。

さあ、始めましょう!

II. オープンソース プロジェクトに参加する理由

「なぜオープンソースに参加するのか」という点や、オープンソースプロジェクトに参加するメリットについて長々と議論するつもりはありません。その代わりに、「コーディングスキルの向上」という観点から「なぜオープンソースプロジェクトに参加するのか」についてお話ししたいと思います。

面接中、私は履歴書に特定の言語の熟練度について記載している応募者に、次のような質問をする習慣があります。

オープンソースプロジェクトのソースコードを読んだことがありますか?あるいは、オープンソースコミュニティに参加したり、オープンソースプロジェクトにPRを送信したりしたことがありますか?

答えが「はい」の場合、たとえば、候補者が Kubernetes モジュールのソースコードの一部を読んだと述べ、私がさらに候補者が実際にそれを読んで理解したこと、またはタイプがバグ修正/機能の PR を実際に送信したことを確認した場合、成熟したオープンソース プロジェクトのソースコードの一部を理解できること、またはタイプがバグ修正/機能の PR を送信できることで、すでにすべてが語られていると考えるため、プログラミング言語に関する質問はもう行いません。

私自身の Golang の学習は、大きく分けて 2 つの段階に分けられます。

  1. 基本的な構文を学習し、プロジェクトの作成を開始し、さまざまなビジネス機能の開発に習熟するまで継続します。
  2. いくつかのオープンソース プロジェクトのソースコードを確認した後、大きな恩恵を受け、コーディング スキルが大幅に向上したと感じました。

Kubernetesプロジェクトのソースコードを眺めていた頃、典型的な社内プロジェクトと、世界最高峰のプログラマーの英知を結集したオープンソースプロジェクトとの間には、大きな隔たりがあることを痛感しました。そして、優れたオープンソースプロジェクトのソースコードを研究することが、プログラマーのコーディングスキル向上に重要であることも痛感しました(もちろん、Google社内にもオープンソースではない優れたコードが存在することは間違いありませんが、今日は特別なケースについて議論する必要はないでしょう)。

オープンソースプロジェクトのソースコードを注意深く読むと、必ず小さな欠陥が見つかります。そんな時、PR(プルリクエスト)を送信して自分のコードをオープンソースプロジェクトにマージし、「世界の隅々まで」実行してもらうことは、実に魅力的な体験です。最初のPRを無事にマージできた時は、まるでパンドラの箱を開けたような気分です。まるで別世界に入り、オープンソースコミュニティとの繋がりを築き始め、オープンソースの魅力を体験できるのです!

III. PRのやり方を紹介したい理由

当社では以下の 2 つのプロジェクトをオープンソース化しています。

1. CNCFプロジェクトDevStream[1]

CNCF プロジェクト DevStream

2. Apache DevLake[2]

DevStreamプロジェクトとDevLakeプロジェクトは、新しいコントリビューターから定期的にPRを受け取ります。しかし、多くのコントリビューターは、最初のPRを送信する際に、競合、コミットレコードの過多または乱雑さ、署名されていないコミット、非標準のコミットメッセージ、さまざまなCIプロセスチェックにおけるエラーなど、1つ以上の問題に遭遇することがよくあります。

新しいコントリビューターがPRを提出するのを見ると、私たちは当然のことながら大変嬉しく、温かく迎え入れ、様々な問題の解決方法を伝えます。しかし、コントリビューターの数が増えるにつれて、オープンソースコミュニティはほぼ毎日、「PRを適切に提出するにはどうすればいいか?」という質問に答える必要に迫られています。必要なドキュメントを提供していないのではないかと疑問に思う方もいるかもしれません。実はそうではありません。詳細なドキュメントは用意していますが、人は本質的に怠け者です。新しいコントリビューターの多くは、PRを提出する前にドキュメントを注意深く読む意欲がありません。オープンソースプロジェクトに不慣れで、プロジェクトの構造やドキュメントの構成に馴染みのない多くの新しいコントリビューターは、これらのドキュメントの存在すら知らないかもしれません。つまり、様々な理由から、ほとんどの新しいコントリビューターは「まずPRを提出して、結果は後で考える」という選択をしてしまうのです。

今回は、GitHubにおけるPRの送信プロセス全体、そして様々な問題点とその解決策を解説しながら、「正しいPRの送信方法」を徹底的に解説したいと思います。オープンソースプロジェクトに初めて参加する初心者の方々の参考になれば幸いです。また、DevStreamやDevLakeコミュニティの参入障壁をさらに下げることができれば幸いです。

IV. オープンソース プロジェクトに参加したいのですが、どうすればよいですか?

オープンソース プロジェクトに参加しようと決めた理由が何であれ、学習のため、興味のため、達成感のため、あるいはオープンソース プロジェクトに必要な機能を組み込むためなど、今日オープンソース プロジェクトに PR を送信することに決めたのであれば、始めましょう。

4.1 適切なオープンソースプロジェクトを見つける

すでにオープンソース コミュニティに参加することを決めている場合は、このセクションをスキップしてください。

オープンソースを始めたいけれど、どのコミュニティに参加すればいいかまだわからないという方には、いくつか提案があります。

  1. 成熟しすぎたプロジェクトから始めないようにしましょう。例えば、今Kubernetesコミュニティに参加すると、一方では貢献者が多すぎるため、最初のPRを始めるためのエントリーレベルの問題を見つけるのが難しくなります。他方では、貢献者が多すぎるため、あなたの声はかき消されてしまい、コミュニティのメンテナーはあなたが1人増えようが1人減ろうが気にしません(もちろん、誰も認めないでしょうが、あなたはそう信じるしかありません)。PRの提出時に様々な問題に遭遇し、自力で解決できない場合、PRはタイムアウトしてクローズされる可能性が高く、参加体験が良好かどうかは誰も気にしません。
  2. 非常に小さなプロジェクトから始めないでください。これは説明するまでもありませんよね?初期のオープンソースプロジェクトは、コードスタイルの悪さ、一貫性のないコラボレーションプロセス、問題解決に重点を置かない頻繁なリファクタリングなど、多くの問題に直面することがよくあります。外部のステークホルダーを混乱させ、混乱させる可能性があります。
  3. 著名なオープンソースソフトウェア財団のインキュベーションプロジェクトを選択するのも良い選択肢です。これらのプロジェクトはそれほど成熟していないため、新規の貢献者にとってより親しみやすい一方で、ユーザーエクスペリエンスが低下するほど未熟でもありません。例としては、Apache Foundation、Linux Foundation、CNCFなどが挙げられます。

たとえば、興味のあるオープンソース プロジェクトは次の場所で見つけることができます。

  • CNCFサンドボックスプロジェクト[3]
  • CNCFインキュベーションプロジェクト(卒業プロジェクトを含むリスト)[4]
  • Apacheプロジェクト(プロジェクト名に「Incubating」とあるインキュベーション段階のプロジェクト)[5]

もちろん、CNCFサンドボックスプロジェクトDevStream[6]やApacheインキュベータプロジェクトApache DevLake[7]からオープンソースの世界に直接アクセスすることもできます。

4.2 貢献ポイントの特定

オープンソースプロジェクトへの参加方法は様々です。最も一般的な方法は、機能開発やバグ修正に関するPRを提出することです。しかし、ドキュメントの改善、テストケースの改善、バグのフィードバックなども非常に価値のある貢献となります。しかし、この記事ではPRとして提出する必要がある貢献ポイントから始めます。DevStreamプロジェクトを例に挙げると(他のプロジェクトでも同様ですが)、プロジェクトのGitHubリポジトリ[8]のホームページにはIssuesというエントリがあります。このエントリには、下図に示すように、既知のバグ、提案(新しい要件とも言えます)、予定されている補足ドキュメント、緊急に改善が必要な単体テストなどが記録されます。

DevStreamの問題

問題セクションでは、通常「good first issue」というラベルの付いた問題が表示されます。このラベルをクリックすると、さらに絞り込み、すべてのgood first issueを直接表示できます。これらは、コミュニティが新規貢献者向けに特別に用意した、比較的シンプルな入門レベルの問題です。

DevStream の最初の問題

そうです、ここから始めましょう。これらの最初の課題をざっと見て、興味があるのにまだ割り当てられていない課題がないか確認しましょう。そして、下記にコメントを残し、プロジェクト管理者がタスクを割り当てるのを待ってからコーディングを始めましょう。例えば、以下のような感じです。

DevStreamで問題を報告

画像に示すように、問題がまだ申請されていない場合は、メッセージを残して管理者がタスクを割り当てるのを待ち、その後開発を開始できます。

5. PR を送信するにはどうすればよいですか?

一般的に、オープンソース プロジェクトのコードベースには、貢献を開始する方法を説明する CONTRIBUTING.md ファイルまたは同様の名前のドキュメントがルート ディレクトリに存在します。以下に例を示します。

DevStream 貢献

DevStream Contributing[9]ドキュメントには開発ワークフロー[10]が掲載されていますが、これは実際にはPRワークフローの紹介です。しかし、今日はPRワークフローについてより詳しくお話ししたいと思います。

5.1 ステップ1: プロジェクトリポジトリをフォークする

GitHub上のプロジェクトにはすべて「フォーク」ボタンがあります。まずはオープンソースプロジェクトを自分のアカウントにフォークする必要があります。DevStreamを例に挙げましょう。

フォークDevStream

「フォーク」ボタンをクリックし、アカウントに戻ってフォークされたプロジェクトを見つけます。

DevStreamフォーク

このプロジェクトはあなた自身のアカウントで管理されているため、自由に変更する権限があります。次に行う必要があるのは、コードの変更をフォークしたリポジトリに移動し、プルリクエストを介してコミットをアップストリームプロジェクトにマージすることです。

5.2 ステップ2: プロジェクトリポジトリをローカルマシンにクローンする

プロセスはどのオープンソースプロジェクトでもほぼ同じです。いくつかのコマンドを直接記述したので、コピー&ペーストして実行できます。もちろん、コマンド内の一部の変数は実際のニーズに合わせて変更する必要があります。例えば、DevStreamプロジェクトでは、次のようにいくつかの環境変数を設定できます。

  • 環境変数
 WORKING_PATH"~/gocode" エクスポートします
エクスポートUSER = "daniel-hutao"
エクスポートPROJECT = "devstream"
エクスポートORG = "devstream-io"

同様に、DevLake の場合、コマンドは次のようになります。

 WORKING_PATH"~/gocode" エクスポートします
エクスポートUSER = "daniel-hutao"
エクスポートPROJECT = "incubator-devlake"
エクスポートORG = "apache"

USER を GitHub ユーザー名に置き換えることを忘れないでください。WORKING_PATH も柔軟に設定できます。コードを配置するパスを記述するだけです。

次に、いくつかの一般的なコマンド行を使用してクローン操作を完了します。

  • クローンなど
 mkdir -p ${WORKING_PATH}
cd ${WORKING_PATH}
# 次の URL も使用できます: [email protected]:${USER}/${PROJECT}.git
# SSH設定が適切であれば
gitクローン https://github.com/ ${USER} / ${PROJECT} .git
${プロジェクト} をcd
gitリモートでアップストリームを追加 https://github.com/ ${ORG} / ${PROJECT} .git
# ローカルでアップストリームにプッシュしない
gitリモート set-url --pushアップストリーム no_push

コードをクローンするために SSH を設定している場合は、`git clone` コマンドで使用される URL を `[email protected]:${USER}/${PROJECT}.git` に変更できます。

この手順を完了すると、ローカルに表示されるリモート情報は次のようになります。

  • git リモート -v
 origin git @github.com:daniel-hutao/devstream.git (フェッチ)
origin git @github.com:daniel-hutao/devstream.git (プッシュ)
アップストリーム https://github.com/devstream-io/devstream (フェッチ)
アップストリーム no_push (プッシュ)

ローカル コードの変更は origin にのみコミットし、その後 origin からアップストリームにプル リクエストを送信する必要があることに注意してください。

5.3 ステップ3: ローカル支店コードを更新する

フォークとクローン操作を完了したばかりであれば、ローカルコードは間違いなく新しい状態です。しかし、この「今」の状態は一度きりです。コードを書き始めるたびに、ローカルブランチのコードが新しいことを確認する必要があります。古いコードに基づいて開発を行うと、競合の無限のサイクルに陥ってしまうからです。

  • ローカルのメイン ブランチ コードを更新します。
 gitフェッチ アップストリーム
gitチェックアウト メイン
Gitでアップストリーム/メインをリベースする

もちろん、メインブランチに直接コードを書くのはお勧めしません。最初のPRをメインブランチから送信するのは全く問題ありませんが、同時に2つのPRを送信する必要がある場合はどうでしょうか?つまり、開発作業を完了するには、feat-xxxやfix-xxxなど、より読みやすいブランチを追加することをお勧めします。

  • ブランチを作成する
 gitチェックアウト-b feat-xxx

こうして、上流のメインブランチのコードと同一の機能ブランチ feat-xxx ができました。これで、安心してコードを書き始めることができます!

5.4 ステップ4: コードを書く

言うことはあまりないので、ただ書いてください。

5.5 ステップ5: コミットとプッシュ

  • 一般的なプロセス:
 git add <ファイル>
git commit -s -m "ここに説明を記入してください"
gitプッシュ origin feat-xxx

もちろん、これらのコマンドとパラメータの意味を理解し、柔軟に調整する必要があります。例えば、`git add --all` を使って追加ステップを完了したり、プッシュ時に `-f` パラメータを追加してリモートブランチを強制的に上書きしたりできます(リモートブランチが既に存在するものの、コミット履歴が期待どおりでない場合)。ただし、`git commit` には `-s` パラメータを追加する必要があることに注意してください。

コミットに IDE を使用することに慣れている場合は、次のようにしてもまったく問題ありません。

GolandとのDevStreamコミット

ここでコミットメッセージの仕様に注意することが重要です。要件はプロジェクトごとに異なる可能性があるためです。例えば、DevStreamの仕様[11]は次のような形式になっています。

 <type>[オプションのスコープ]: <description>
[オプションの本文]
[オプションのフッター]

以下にいくつかの例を挙げます。

  • ドキュメント: ここに説明があります
  • 修正: ここに説明があります
  • 修正(コア): ここに説明があります
  • 雑用:ここに説明を記入
  • ...

コミットとプッシュのステップは、IDE内で1つのステップで実行することも、別々に実行することもできます。私は柔軟性を高めるために、別々に実行することを好みます。また、コマンドライン操作も好みます。

  • git プッシュ origin feat-1
オブジェクトをカウントしています: 80完了
最大10 個のスレッドを使用したデルタ圧縮。
オブジェクトの圧縮: 100 % (74/74)、 完了
オブジェクトの書き込み: 100 % (80/80)、 13.78 KiB | 4.59 MiB/s、 完了
合計80 (デルタ55 )、再利用0 (デルタ0 )
リモート: デルタの解決: 100 % (55/55)、 31 個のローカル オブジェクトで完了しました。
リモート:
リモート: 次の URL にアクセスして、GitHub で'feat-1' プル リクエストを作成します。
リモート: https://github.com/daniel-hutao/devstream/pull/new/feat-1
リモート:
github.com:daniel-hutao/devstream.git へ
* [新しいブランチ] feat-1 - > feat-1

この時点で、ローカルコミットはリモートリポジトリにプッシュされています。

5.6. ステップ6: PR(広報ファイル)を開く

プッシュ操作が完了すると、GitHub を開くと、プル リクエストを開くことができることを知らせる黄色の通知ボックスが表示されます。

比較とプルリクエスト

このボックスが表示されない場合は、feat-1 ブランチに直接切り替えて、下の「貢献」ボタンをクリックして PR を開始するか、「問題」の横にある「プル リクエスト」をクリックして対応するページに移動できます。

  • プル リクエストのデフォルトの形式は次のとおりです。

DevStream プルリクエスト

ここでは適切なタイトル(デフォルトはコミットメッセージと同じ)を入力し、テンプレートに従ってPRの説明を入力します。PRテンプレートはオープンソースプロジェクトごとに若干異なるため、基本的な間違いを避けるために上記の内容を注意深く読む必要があります。

たとえば、DevStream テンプレートは現在 4 つの部分に分かれています。

  1. 事前チェックリスト: このリストには、PR 送信者に、まず貢献ドキュメントを読み、コードに完全なコメントまたはドキュメントが含まれていることを確認し、可能な限りテスト ケースを追加するよう促す 3 つの事前チェック項目が含まれています。
  2. 説明: PRの内容を紹介する説明を記入します。このPRがどのような問題を解決したかなど、詳細を記載できます。
  3. 関連する問題: 覚えておいてください。コードを書き始める前に、問題を申請する必要があります。ここでは、関連する問題IDを入力してください。例えば、申請した問題へのリンクが https://github.com/devstream-io/devstream/issues/796 で、このPRを通じて変更を加えた後にこの問題がクローズされた場合、「関連する問題」に「close #796」と記入できます。
  4. 新しい動作:多くの場合、コードの変更にはテストが必要です。この場合、テスト結果のスクリーンショットをここに貼り付けることで、レビュー担当者はコードがテストに合格し、機能が期待どおりであることを確認できます。これにより、レビューの作業負荷が軽減され、迅速なマージが可能になります。

このテンプレートは複雑ではないので、直接入力するだけです。

  • 例えば:

DevStream プルリクエストテンプレート

次に、右下にある「プルリクエストを作成」をクリックして、PRの作成を完了します。ただし、ここではこのボタンをクリックできません。これは、デモに使用している変更が意味をなさず、アップストリームのコードベースにマージできないためです。それでも、PR作成後の効果をお見せしたいと思います。pr655[12]を例に挙げましょう。

DevStream プルリクエスト 655

これは先月提出したPRで、基本的にテンプレートと同じ形式です。テンプレートの内容に加えて、「テスト」セクションが追加されていることに気づいたかもしれません。そうです、テンプレートは静的なものではなく、コミュニケーションコストを削減するためのものです。「より明確な方向性」を示している限り、適宜調整していただいて構いません。今回は、レビュー担当者にローカルで徹底的にテストしたことを伝え、自信を持ってマージできるようにするために、「テスト」セクションに詳細なローカルテスト結果記録を追加しました。

PRを送信すると、PRリストに表示されます。この時点で、すべてのCIチェックがパスしているかどうかを確認する必要があります。もしパスしなかった場合は、速やかに修正する必要があります。DevStreamを例に挙げると、CIチェックはおおよそ以下のようになります。

DevStream CI チェック

5.7 ステップ7: PRのマージ

PR が完璧で議論の余地がない場合は、プロジェクト管理者が短時間で PR を直接マージし、PR のライフサイクルが終了します。

しかし、確かに「しかし」があります。最初のPRは必ずしもスムーズに進むとは限りません。次に、よくある問題とその解決策について詳しくご紹介します。

6. PR を送信した後、問題 A、B、C、D、E、F、G が発生しました...😭

多くの場合、PRは提出後すぐにはマージされません。レビュアーから様々な修正提案があったり、PR自体にフォーマット上の問題があったり、CIチェックで直接エラーが報告されたりすることがあります。どうすれば解決できるでしょうか?続きをお読みください。

6.1. レビュアーから修正案がいくつか提示されました。PRを更新するにはどうすればよいですか?

PRを送信した後、コミットを追加する必要があることがよくあります。例えば、送信後にコードにまだ問題が残っていることがわかり、変更を加えたい場合や、レビュアーから改善の提案があり、コードを更新する必要がある場合などです。

私たちは通常、次のような慣例に従っています。レビュー開始前は、コードを更新する際に新しいコミットレコードを作成しないようにします。つまり、コミットレコードが明確で意味のあるものになるように、可能な限りマージします。レビュー開始後は、レビュアーのコメントに応じて生成された新しいコミットはマージする必要がなくなり、2回目のレビュー作業をより的確に行うことができます。

ただし、コミュニティによって要件は異なります。オープンソースプロジェクトによっては、PRに含めることができるコミットを1つだけに制限している場合もあります。実際の状況に応じて柔軟に判断してください。

PR の更新方法に戻ると、ローカルでコードの変更を続け、最初のコミットと同じ手順に従って、次のコマンドを実行するだけです。

 git add <ファイル>
git commit -s -m "ここに説明を記入してください"
gitプッシュ origin feat-xxx

この時点では、`origin` の `feat-xxx` ブランチにプッシュしているにもかかわらず、GitHub は実際にはすべての新しいコミットをマージされていない PR に追加します。そうです、プッシュを続けるだけで PR は自動的に更新されます。

コミットをマージする方法については、次のサブセクションで詳しく説明します。

6.2 コミットが多すぎる場合やレコードが整理されていない場合にコミットをマージするにはどうすればよいでしょうか?

多くの場合、コミットをマージする必要があります。例えば、最初のコミットで100行のコードを変更した後、1行変更し忘れたことに気づき、別のコミットをコミットした場合、2番目のコミットは「面白みに欠ける」ものになってしまうため、マージする必要があります。

6.2.1 Gitコマンドラインによるコミットのマージ

例えば、ここに同じ名前のコミットが2つあります。2つ目のコミットでは句読点が1つだけ変更されています。

マージされるコミット

この時点で、 rebase コマンドを使用して 2 つのコミットをマージできます。

 git rebase -i HEAD~2

このコマンドを実行すると、デフォルトでVim編集モードの編集ページが開きます。内容は以下のようになります。

 3114c0f ドキュメントを選択: ちょうど fortest
9b7d63b ドキュメントを選択: just fortest
# d640931..9b7d63b を d640931 にリベースする (2 コマンド)
#
# コマンド:
# p, pick = コミットを使用する
# r、言い換えるとコミットを使用するが、コミットメッセージを編集する
# e、編集 = コミットを使用するが、修正のために停止する
# s、squash = コミットを使用するが、前のコミットにマージする
# f, fixup = "squash" と同様ですが、このコミットのログメッセージを破棄します
# x, exec = シェルを使用してコマンド(行の残り)を実行します
# d、drop = コミットを削除
#
# これらの行は順序を変更できます。上から下の順に実行されます。
#
# ここで行を削除すると、そのコミットは失われます。
#
# ただし、すべてを削除すると、リベースは中止されます。

2 番目の選択肢を 's' に変更し、保存して終了する必要があります (Vim の `wq` コマンドを使用)。

 3114c0f ドキュメントを選択: ちょうど fortest
s 9b7d63b ドキュメント: ちょうどテスト

次に、2 番目の編集ページに入ります。

 # これは 2 つのコミットの組み合わせです。
# これは最初のコミットメッセージです:
ドキュメント: ちょうどテスト
署名者: Daniel Hu <[email protected]>
# これはコミットメッセージ #2​​ です:
ドキュメント: ちょうどテスト
署名者: Daniel Hu <[email protected]>
# 変更のコミットメッセージを入力してください。
'#' を含む # は無視され、空のメッセージはコミットを中止します。
# ...

このセクションでは、マージされたコミットメッセージを編集します。冗長な部分を削除し、以下の数行のみを残します。

ドキュメント: ちょうどテスト
署名者: Daniel Hu <[email protected]>

次に、Vimで保存して終了します。この時点で、ログが表示されます。

 [分離したHEAD 80f5e57] ドキュメント: just fortest
日付: 2022年7月6 (水) 10:28:37 + 0800
1 つのファイルが変更され、 2 つの挿入( + )
refs/heads/feat-1 のリベースと更新に成功しました。

この時点で、`git log` コマンドを使用して、コミット履歴が期待どおりかどうかを確認できます。

リベース

さて、コミットがマージされたことをローカルで確認できたので、リモート リポジトリにプッシュして PR も更新できます。

 git push -f origin feat-xxx

ここでは、強制的に更新するために -f パラメータが必要です。コミットのマージは本質的に競合であり、リモートリポジトリの古いコミットレコードを上書きする必要があります。

6.2.2 IDEでのコミットのマージ

もちろん、コミットをマージするためにグラフィカルな方法を使用することもできます。

  • スクリーンショットを撮ろう!
  1. 右下隅にある Git アイコンをクリックします。
  2. マージするコミットを選択します。
  3. 右クリックして、「Squash Commits」をクリックし、静かに「Let's go!」と言うことを忘れないでください。

すると、次のページが表示されます。

ゴランドとのスカッシュ

これはコミットメッセージを編集するためのグラフィカルインターフェースです。お好みに合わせて変更し、右下の「OK」ボタンをクリックすれば完了です。

ゴランドとのスカッシュ

ご覧のとおり、 2 つのコミットが「マージ」され、「完全に作り変えられた」新しいコミットになりました。

6.3. PR 中に発生した競合をどうやって解決するか?

競合はオンラインでもローカルでも解決できます。1 つずつ見ていきましょう。

6.3.1 オンライン紛争解決

競合はできる限り避け、コードを書く前にローカルコードを更新する習慣を身につけるべきです。しかし、競合を完全に避けることはできません。PRが数日間ブロックされ、誰かが同じコード行を修正して先にマージしてしまうこともあります。この場合、PRには以下のような競合が発生します(繰り返しますが、現時点では上流プロジェクトで競合を発生させることはできないため、以下のデモで使用した競合は私のリポジトリで作成したものです)。

紛争が起こった

このページを見るといつも背筋が凍ります。「競合を解決」ボタンをクリックすると、競合の詳細が表示されます。

競合ファイル

これで、競合している行が具体的に確認できました。次のステップは、競合を解決することです。`<<<<<<<`、`>>>>>>>`、`=======` タグをすべて削除し、必要なコンテンツだけを残します。手順は以下のとおりです。

紛争解決

次に、右上隅の「解決済みとしてマーク」をクリックします。

解決済みとしてマーク

最後に、「マージをコミット」をクリックします。

これにより競合が解決され、新しいコミットが生成されたことがわかります。

紛争解決

紛争は解決されました。

6.3.2 ローカル紛争解決

多くの場合、競合が多すぎる場合や複雑すぎる場合は特に、競合をローカルで解決する必要があります。

同様に、競合を構築し、今回はローカルで解決を試みます。

  • まず、オンラインで紛争の内容を見てみましょう。

紛争が起こった

  • 次に、ローカルで実行します。
 # まず、メインブランチに戻ります
gitチェックアウト メイン
# アップストリーム コードをプルします (実際のシナリオでは、これは間違いなくアップストリーム コードと競合します。ここでのデモ環境は実際には Origin です)。
gitフェッチ アップストリーム
# ローカルのメインを更新します (ここでも rebase を使用できますが、競合の有無にかかわらず reset は常に成功します)
gitリセット--hardアップストリーム/メイン

この時点で、ローカルのメインブランチはリモート(または上流)のメインブランチと完全に整合性が取れています。次に必要なのは、メインブランチのコードを独自のフィーチャーブランチにマージし、競合を解決することです。

 gitチェックアウト feat-1
gitリベース main
  • この時点で、次のようなログが表示されます。
まず、ヘッドを巻き戻してそので作業を再生します...
適用中: ドキュメント: 競合テスト1
インデックス情報を使用してベースツリーを再構築しています...
M README.md
パッチベースと3 方向マージにフォールバックします...
README.md の自動マージ
CONFLICT (コンテンツ): README.md マージ競合
エラー: 変更マージできませんでした。
0001ドキュメントでパッチが失敗しました: 競合テスト1
失敗したパッチのコピーは次の場所にあります: .git/rebase-apply/patch
すべての競合を手動で解決し、解決済みとしてマークします
「git add/rm <conflicted_files>」を実行し次に「git rebase --continue」を実行します。
代わりにこのコミットをスキップすることもできます: "git rebase --skip"を実行します。
中止して「git rebase」前の状態に戻すには、 「git rebase --abort」を実行します。

競合を解決する必要があります。README.md を開き、競合しているセクションを見つけて修正するだけです。ここでの方法は、前のセクションで紹介したオンライン競合解決方法と全く同じなので、詳細は省略します。

コードには最終的な内容のみが保持され、その後 git コマンドが実行されます。

紛争解決

まだ完全に確信が持てない場合は、`git log` コマンドを使用してコミット履歴を確認してください。

コミット履歴

ここで、「conflict test 2」はメインブランチへのコミット記録です。「conflict test 1」より少し遅い時間ですが、こちらが先にマージされています。リベース操作後、この記録が最初に表示され、その次にフィーチャーブランチの「conflict test 1」が続きます。これは一見調和が取れているように見えます。この変更をリモートリポジトリにプッシュし続けます。このコマンドは既に何度も使用されています。

 git push -f origin feat-xxx

GitHubに戻ってPRを確認すると、競合が解決され、追加のコミットレコードが生成されていないことがわかります。つまり、このPRのコミット履歴は非常にクリーンで、競合が発生しなかったかのようになっています。

オンラインで競合を解決するのが適切か、ローカルで解決するのが適切かは、競合解決の記録を保持する必要性に対する人々の考え方によって異なります。コミュニティによって理解は異なります。確立されたオープンソースコミュニティでは、オンラインでの競合解決で生成されるマージ記録は実質的に「役に立たない」ため、ローカルでの競合解決を好む場合があります。DevStreamとDevLakeのコミュニティに関しては、後者のアプローチを推奨しますが、必須ではありません。

6.4 CI チェックが失敗します: コミット メッセージ関連の問題を修正するにはどうすればよいですか?

コミットメッセージのガイドラインについては以前説明しましたが、初めてPRを送信する際には間違いを犯しやすいものです。例えば、「feat: xxx」はCIチェックを通過する可能性がありますが、「feat: Xxx」は通過しません。誤って間違ったコミットメッセージでPRを送信してしまったとしたら、どうすれば修正できるでしょうか?

  • 非常に単純なので、実行するだけです。
 gitコミット--amend

このコマンドを実行すると編集ページに入り、コミットメッセージを自由に更新できます。変更を加えたら、プッシュを続けます。

 git push -f origin feat-xxx

これにより、PR 内のコミット メッセージが更新されます。

6.5 CI チェックが失敗しました: DCO(sign) の問題を修正するにはどうすればよいでしょうか?

多くのオープンソース プロジェクトでは、すべてのマージされたコミットに次のような行が含まれている必要があります。

ダニエル・フー <[email protected]>

したがって、コミット メッセージは次のようになります。

特技: ここで説明
署名者: Daniel Hu <[email protected]>

この行の情報は、基本的に対応するコミットの作成者の署名です。このような署名を追加するのは非常に簡単で、`git commit` コマンドの後に `-s` パラメータを追加するだけです。例えば、`git commit -s -m "some description here"` と実行すれば、コミットに署名が追加されます。

しかし、最初のPRのコミットにSigned-off-byを追加するのを忘れた場合はどうなるでしょうか?この場合、対応するオープンソースプロジェクトにDCOチェックが設定されている場合[13]、PRはCIチェックで適切に署名されていないことが「検出」されます。

まず、署名されていないコミットを作成します。

画像の説明を追加してください。

署名なしでコミット

DCO にエラーをスローさせる方法を示すためにこれを DevStream プロジェクトのコードベースに直接プッシュすることはできませんが、PR を送信すると、結果は次のようになります。

DCO エラーでコミット

これをどうやって解決するか見てみましょう:

  • git コミット --amend -s

このシンプルなコマンドは、Signed-off-by メッセージを最新のコミットに直接追加します。このコマンドを実行すると、以下のデフォルト画像に示すように、コミットメッセージの編集ページに直接移動します。

ドキュメント: dco テスト
署名者: Daniel Hu <[email protected]>

この時点でコミットメッセージを変更できます。変更しない場合は、保存して終了するだけで、署名情報は自動的に追加されます。

署名後、何が起こるでしょうか?もちろん、強制的に押し進める段階です。

 git push -f origin feat-xxx

これにより、PR 内の DCO エラーが自然に修正されます。

VII. 最後に

おっと、ちょっと長くなっちゃったね。さて、今回はここまで!

  • 私の他の記事を閲覧するには、私の個人ウェブサイト[14]またはWeChatパブリックアカウント「Hushuo Cloud Native」にアクセスしてください。
  • DevStreamコミュニティ[15]をフォローして、私と一緒にオープンソースを探索しましょう。
  • DevStreamチームが公開したその他の記事を閲覧するには、DevStream公式ブログ[16]へようこそ。