Guidelines

これは、 このプロジェクトに貢献するためのガイドラインです。 同じ内容の多くをカバーした step-by-step tutorial も用意されています。

A typical life cycle of a patch series

このドキュメントの後半で示されるさまざまなガイドラインの背後にある理由を理解するために、 まず、 このプロジェクトの典型的なパッチ・シリーズのライフ・サイクルがどのように進むかを理解しましょう。

  1. あなたが、痒いところを見つけたら、 ご自身でコードを実装してください。 その作業に対して本プロジェクトからの事前承認は不要です。

    あなたが送信したパッチはメーリングリストにて他の貢献者達によりレビューされます。 レビューでは、 パッチの基本思想(「そもそも解決すべき問題と言えるか」も含む)や、 設計意図や、 実装の品質やなどが評価対象となります。 本ガイドラインは、 レビューする側(reviewers)がパッチの内容を迅速かつ正確に把握できるよう支援することを目的として定められています。

  2. あなたはパッチをメーリングリストに送り、 変更を知っておく必要がある人をCCに入れます。 あなたの目的は、必ずしも「自分が作っているものが優れている」と他人を説得することではありません。 あなたの目的は、 自分一人で作るよりもっと良い解決策を、 その「かゆいところ(itch)」に関して、 みんなの力を合わせて見つけることです。

    あなたがいじっているコードに取り組んでいる人たちが、 これを知っておくべき人たちです。 この人たちこそが、 あなたを助けるのに十分な知識を持っている可能性が最も高い人たちですが、 彼らにはあなたを助ける義務は一切ありません(つまり、 あなたは助けを頼むのであって、 要求するのではありません)。 git log -p -- _$area_you_are_modifying_ (area_you_are_modifying;あなたが修正している領域) を実行すれば、 あなたは誰がその部分をいじっていたかが分かります。

  3. パッチの更新セットを準備する際には、それらの内容を考慮しながら、メーリング リストで「全員に返信」して返信することが期待されます。 あなたは、 改善のためのコメントや提案を受け取ります。 ときには「あなたの変更にさらに修正を加えた」パッチ形式で返ってくることもあります。 あなたは、 それらに対しては、 指摘を反映した更新版パッチを用意して、 必ずメーリングリストで「全員に返信(Reply-All)」として返信することが期待されます。

  4. あなたはパッチを磨き上げて、 レビューに時間を割いてくれた人たちとメーリングリスト全体に再度送り直してください。 そして作業はステップ (2) に戻ります。

  5. 上記のようなやり取りであなたのパッチが改善されていく間に、 メンテナーがメーリングリストからパッチを拾って seen ブランチに入れることがあります。 これは「他の人が自分でパッチを取ってきて当てなくても試せるように」という配慮にすぎません。 seen に入ったこと自体には他に意味はなく、 特に「受理された」ことを意味するものではありません。

  6. 議論の結果「最新版のパッチが十分に良い状態になった」と全員が納得したら、 メンテナーは数日に一度送られる「What’s cooking」レポートにそのトピックを掲載し、「Will merge to next.」とマークします。 この判断は主にメンテナーが下しますが、 レビューに参加した人たちの意見も参考にします。

  7. 「next」ブランチにマージされた後も、 さらに改善するための追加パッチを送ることは可能ですが、 「next」に乗った時点で「この変更の範囲と方向性は適切だ」と全員が合意したとみなされるため、 その後の更新は小さな修正や仕上げに限定されます。 トピックが「next」で(たとえば7日間程度)さらに手直しが必要なく安定したら、 「master」ブランチにマージされ、 次のメジャー・リリースの一部となるのを待ちます。

以降のセクションでは、 上記のようなパッチのライフ・サイクルの中で、 効果的にレビューしてもらえるためのさまざまなテクニックや慣習を紹介します。

Choose a starting point.

事前の準備として、 まず作業の起点となる場所を選ぶ必要があります。 これは通常はブランチを選ぶことを意味しますが、 厳密に言えばそれは実際には特定のコミットを選ぶことです(たいていはそのブランチの HEAD、 つまり先端を選びます)。

注意すべき重要なブランチいくつかあります。 gitworkflows(7) で説明されているとおり、 以下の 4 つの統合ブランチがあります:

  • maint

  • master

  • next

  • seen

このリストの下の方にあるブランチは通常、 その上にあるブランチの子孫です。 たとえば、 maint は、 master よりも「古い」ブランチです。 これは、 master には通常、maint の更にその上にパッチ(コミット)があるためです。

また、 トピック・ブランチ(topic branches)と呼ばれるものもあります。 これらは他の貢献者達からの作業を含むブランチです。 トピック・ブランチは、 Gitのメンテナーが(メンテナー自身のフォーク内に)、 メールリストに届いている現在の貢献パッチを整理・管理するために作成し、 定期的に配信される "What’s cooking in git.git" 案内メールの中で個別に紹介されます。 あるトピック・ブランチの先端(tip)を調べるには、 git log --first-parent master..seen というコマンドを実行してマージ・コミットを探してください。 このマージ・コミットの 2番目の親(second parent)が、 そのトピック・ブランチの最新コミット(tip)になります。

適切な起点を選択するための原則はひとつだけです: それは、 「あなたの変更が関係する一番古い統合ブランチを常にベースにせよ」ということです(詳細は gitworkflows(7) の「Merge upwards」のセクションを参)。 この原則の意味は、ほとんどの場合、新しい作業の起点は以下のルールに従って maint または master の最新コミット(HEAD)にすべきだということです:

  • すでにリリースされたバージョンに存在するバグを修正する場合は、 maint を起点にしてください(その場合、 master に最近追加された新しいAPIや機能は使えません。 なぜなら、 それらはリリース済みのバージョンにはまだ入っていないからです)。

  • それ以外の場合(たとえば新機能を追加する場合など)は、 master を起点にしてください。

Note
例外的なケースとして、 古いバージョンで導入されたバグを、 現在よりもはるかに古いリリースを使っているユーザー向けに修正しなければならないことがあります。 git describe --contains X を実行すると、バグを導入したコミット X がたとえば v2.30.0-rc2-gXXXXXX のように表示されることがあり、 そのバグの影響が非常に大きいために、 現在のリリースが Git 2.41.0 であっても、 Git 2.30.x シリーズ向けに新しいメンテナンス・リリースを出す必要がある場合があります。 このような場合、 あなたは 2.30.x シリーズ用のメンテナンス・ブランチの先端(tip)で作業してください。 それは the maintainer’s "broken out" repo (メンテナーの「切り出し」リポジトリー) に maint-2.30 という名前で存在しています。

これが意味するのは、 あなたの作業を現実的に master に取り込んでもらいたいのであれば、 nextseen を起点にするのは不適切だということです。 それらは新しい作業のベースとして設計されているわけではなく、 ただ現在進行中のトピック同士がうまく共存できるかを確認するためだけに存在しています。 そのため、 nextseen はメーリングリストに届く新しいパッチを頻繁に取り込んで再統合され、 以前の自分自身を上書きする形で強制プッシュされます。 文字通り next の上に構築されたトピックは、 next に入っている他のまだ準備ができていないトピックすべてを引きずり込むことになるため、 master にマージすることはできません。

たとえば、 あなたがツリー全体にわたる変更を行っているときに、 別の人もまた別のツリー全体にわたる変更を行っているとします。 この場合、 あなたの作業と他人の作業が大きく重複する可能性があり、 next を起点にしたくなる誘惑に駆られるかもしれません(なぜなら next にはすでに他人の作業が取り込まれているからです)。 しかしそうしてしまうと、 あなたは他人の作業だけでなく、 next にすでに統合されている他の貢献者達によるさまざまなものすべてに依存することになります。 そして next が新しいバージョンで更新された瞬間に、 あなたの作業すべてを再ベースしないとメンテナーがきれいに適用できなくなります。

本当にごく例外的な状況で、 next には入っているが master にはまだ入っていないごく少数のトピック・ブランチにどうしても依存しなければならない場合は、 master をフォークして必要なトピック・ブランチだけをそこにマージすることで、 自分専用のベース・ブランチを作成してもかまいません。 そしてその上で作業を進めます。 ただし、 このベース・ブランチはあなただけが知っているプライベートなものになります。 したがって、 パッチをメーリングリストに送るときは、 カバー・レターで「どのようにしてこのベース・ブランチを作ったか」を必ず明記してください。 この情報がないと、 他の人があなたの作業を試すために同じベースを再現できなくなります。

最後になりますが、 システムの一部には専任のメンテナーがいて、 別リポジトリーでソース・コードを管理しているサブ・システムもあります(下記「Subsystems」セクション参照)。

Make separate commits for logically separate changes(論理的に別個の変更は別個のコミットに)

あなたの修正が本当に些細なものでない限り、 作業ツリーとコミット・ヘッドの間で生成されたパッチを送ってはいけません。 その代わりに、 必ず完全なコミット・メッセージ付きでコミットを作成し、 あなたのリポジトリーから一連のパッチを生成してください。 それが良い習慣です。

変更内容は、 実際にパッチのコードを読まなくても「この変更は正しいか」「やるべきことか」を判断できるくらい十分に詳しい説明を書いてください。 説明を読んだだけで「このコードが約束していることを本当にちゃんと実現しているか」を評価できるレベルにしてください。

あなたの説明が長くなりすぎるようでしたら、 それはおそらくコミットをさらに細かく分割すべきサインです。 とはいえ、 レビュアーがパッチをチェックしやすくなり、 将来のメンテナーがコードを理解しやすくなるような、 わかりやすい説明が一番美しいパッチです。 メールの件名欄で要点をうまくまとめ、 そして、 変更の動機や、 この変更が取ったアプローチや、 必要に応じて以前のバージョンとどう大きく違うかを記述している説明は、 どれも素晴らしいものです。

あなたが修正しようとしているバグに対して、 必ずテストを用意してください。 やり方については t/README を参照してください。

新しい機能を追加するときは、 その機能が、 あるべきときに新しい振る舞いを引き起こすこと、 そしてあるべきで無いときには引き起こさ無いこと、 を確認できる新しいテストを必ず用意してください。 コードを変更した後は、 全体のテスト・スイートが通ることを確認してください。 バグを修正するときは、 誰かが誤ってあなたの修正を壊した場合に失敗するような新しいテストを追加し、 再発(regression)を防いでください。 また、 自分の作業を next および seen にマージしてみて、 テストがまだ通ることを確認してください。 他の人が進行中のトピックが、 あなたのトピックと予期しない相互作用を起こす可能性があります。

https://github.com/git/git のフォークにプッシュすると、 github の CI 統合を使用して Linux や Mac や Windows での変更をテストします。 詳細については、 GitHub CI セクションを参照してください。

更新された振る舞いを説明するために、 ドキュメントも必ず更新してください。 そして、 ドキュメント全体が正しくフォーマットされることを確認してください(Documentation/doc-diff スクリプトを試してください)。

現在、 スペルや文法については米国英語(US)と英国英語(UK)がかなり混在しており、 これは残念な状況です。 ただし、 こうした不統一のためだけに、 ありとあらゆるファイルを触るような巨大なパッチは歓迎されません。 そういうパッチは他の変更との衝突を引き起こしやすく、 コストに見合いません。 我々は、米国英語(US)を優先しつつ、 不統一を徐々に解消していく方針です。 その際は「他の実質的な作業(たとえば文章をわかりやすく書き直すなど)」のついでに、 近くの箇所を小規模で飲み込みやすいパッチとして修正していくのが望ましい形です(たとえば、 段落を明確化しながら en_UK 表記を en_US に直すなど)。 一方で、 明らかなタイポ修正("teh" → "the" など)は大歓迎です。 タイポ修正はドキュメントの他の変更とは別に、 独立したパッチとして提出していただけると助かります。

ああそれと、 もう一つ大事なこととして、 我々は空白文字(whitespaces)に対して非常に厳しいです。 あなたの変更が、 templates/hooks--pre-commit に同梱されているサンプルの pre-commit フックでエラーにならないようにしてください。 それを防ぐために、 コミットする前に必ず git diff --check を実行して、 あなたの変更に問題がないか確認してください。

Describe your changes well(変更内容をより良く説明せよ)

変更内容を説明するログ・メッセージは、 変更そのものと同じくらい重要です。 あなたのコードがとてもきれいに書かれていて、 インライン・コメントで周囲のコードとの関係が十分に説明できていたとしても、 将来あなたのコードを修正したり強化したりする人は、 「なぜ」そのコードがそのような動作をするのか、 を知る必要があります。 その理由は以下の通りです:

  1. あなたのコードが、 実はあなたが意図した通りに動いていない可能性があります。 ログ・メッセージに「自分が本当に何を達成したかったのか」を書くことで、 将来の人がそのコードを正しく修正し、 本来やるべき動作に直す手助けになります(それに、 ログ・メッセージを書きながら自分の考えをまとめているうちに、 意外と自分でバグに気づくことも多いです)。

  2. あなたのコードが、 今のあなたの為のニーズを満たすためだけに何かを行っている可能性があります(たとえば、 ディレクトリに対しては何かをを行うが、 ファイルに対しては何も実装・設計していない、 など)。 ログ・メッセージに「なぜそのコードがやらないことをやらないのか」を書いておくと、 将来の開発者を正しく導くことができます。 たとえば「ディレクトリに対しては X を行う。なぜならディレクトリには特性 Y があるから」と書いておけば、 後から読んだ人は「なるほど、 ファイルにも同じ特性 Y があるから、ファイルにも X を適用したほうがいいかもしれない」と推測できます。 逆に「ファイルに対しては同じ X を行わない。なぜなら……」と理由を明記しておけば、 読んだ人はその理由が妥当かどうか判断できます。 理由が正しければ「じゃあファイルにまで対象広げる必要はないな」と無駄な作業をせず、 理由に無理があれば「いや、実はこうだからファイルにも適用すべきだ」と説得力のある形で拡張してくれるでしょう。

ログメッセージの目的は、あなたの変更の「なぜか」(why)を伝え、将来の開発者を助けることです。 レビュアーも、 あなたが提案したログ・メッセージがこの目的をしっかり果たせているかを確認します。

コミット・メッセージの1行目は短い要約で、 50文字分が目安(詳細は git-commit(1) の DISCUSSION 参照)。 文末にピリオドは付けません。 また、 ほとんどの場合、1行目の先頭に "area: " という形でプレフィックスを付けるのが慣例です。 ここで area とは、 変更しているコードの一般的な領域を示すファイル名や識別子のことです。 例えば以下のようなのです

  • doc: clarify distinction between sign-off and pgp-signing

  • githooks.txt: improve the intro section

どの識別子(identifier)を使えばいいか迷ったら、 変更しているファイルに対して git log --no-merges を実行してみてください。 現在の慣例がどうなっているかがすぐにわかります。

"area:" プレフィックスの後のタイトル文は、 文末にピリオドを付けず、 またその最初の単語は("area:" プレフィックスの直後の単語に限り)大文字にせず、 (文の先頭だからという理由ではなく、 それ以外の理由で大文字にする場合を除いて)小文字で始めます。 たとえば、 例: "doc: Clarify…" ではなく "doc: clarify…" とか "githooks.txt: Improve…" ではなく "githooks.txt: improve…" です。 ただし "refs: HEAD is also treated as a ref" は正しいです。 これは、 文の途中でも HEAD は常に大文字で綴るためです。

本文には、 以下のような意味のあるコミット・メッセージを提供する必要があります:

  1. 変更によって解決しようとしている問題、 つまり、 変更を加えていない現在のコードの何が問題なのかを説明します。

  2. 変更が問題をどのように解決しているかの正当性を説明、 つまり、なぜこの変更を加えた後の結果のほうが優れているのか、 を説明します。

  3. もしあれば、 検討したが採用しなかった代替案を記載してください。

問題の説明は現在形で書きます。 「入力 Y を与えるとコードは X をする」と書き、「入力 X を与えられるとコードは以前 Y をしていた」とは書きません。 「現在は~」という言葉をわざわざ入れる必要もありません。 なぜなら、 プロジェクトの慣例として、 問題説明で述べる現状とは「あなたの変更を適用する前のコード」の状態を指すからです。

変更内容の説明は命令形で書いてください。 たとえば「xyzzy に frotz をさせる」(make xyzzy do frotz)のように書きます。 「[このパッチは] xyzzy に frotz をさせる」や「[私が] xyzzy を frotz をするように変更した」のような書き方は避けてください。 コードベースに対して「振る舞いを変えなさい」と命令しているような形にします。 また、説明は外部の資料を見なくても理解できるようにしてください。 メーリングリストのアーカイブへの URL を貼るのではなく、 議論で重要だったポイントを自分で要約して書いてください。

履歴の「より安定した」(more stable)部分(つまり maintmasternext などのブランチ)に存在する別のコミットを参照したくなる理由がいくつかあります:

  1. あなたが修正しようとしているバグの根本原因を導入したコミット。

  2. あなたが強化・改良しようとしている機能を導入したコミット。

  3. あなたの作業をテストのために nextseen に試しにマージしたときに、競合を引き起こしたコミット。

(mastermaintnext のような)より安定したブランチ(more stable branch)にあるコミットを参照するときは、 "abbreviated hash (subject, date)" 形式("省略ハッシュ (件名, 日付)")を使って下さい。 例えば以下のようなのです:

        Commit f86a374 (pack-bitmap.c: fix a memleak, 2015-03-30)
        noticed that ...

gitk の "Copy commit reference" コマンドを使うと、 この形式(件名がダブル・クオートで囲まれた形)で取得できます。 あるいは、 以下の git show の呼び出しでも同じ形式が得られます:

        git show -s --pretty=reference <commit>

or, on an older version of Git without support for --pretty=reference:< または、 --pretty=reference をサポートしていない古いバージョンの Git では以下のようにします:

        git show -s --date=short --pretty='format:%h (%s, %ad)' <commit>

Certify your work by adding your Signed-off-by trailer(Signed-off-by トレーラー追加であなたの作業であることを証明)

誰が何をしたかの追跡状況を改善するため、 あなたのパッチを「サイン・オフ」(signing off)することで、 あなたがそのパッチを自分で書いたか、 または我々と同じライセンスでそれを渡す権利があることを証明していただくようお願いしています。 サインオフ(sign-off)が無い場合、 私たちはあなたのパッチを受け入れることができません。

以下の D-C-O を認証する場合(そして、 その場合に限る):

Developer’s Certificate of Origin 1.1

By making a contribution to this project, I certify that:

  1. The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or

  2. The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or

  3. The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.

  4. I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.

上記の訳:開発者起源証明書 1.1

このプロジェクトに貢献することにより、私は以下のことを証明します:

  1. その貢献の全部または一部は私が作成したものであり、 私はそのファイルに示されたオープンソース・ライセンスの下でそれを提出する権利を有する。 もしくは、

  2. その貢献は、 私の知る限りにおいて、 適切なオープンソース・ライセンスが付与されている以前の作品に基づいており、 私は、 その作品の全部または一部を私が作成したか否かに関わらず、 その作品に修正を加え、 ファイルで示されているものと同じオープンソース・ライセンスの下で(異なるライセンスの下で提出することが許可されていない限り)提出する権利をそのライセンスの下で有している。もしくは、

  3. (a)または(b)または(c)を証明した他の人物から直接私へ提供されたものであり、 私が改変していないこと。

  4. 私は、 このプロジェクトと貢献が公開されること、 および貢献の記録(私のサインオフを含め、 私が貢献とともに提出した全ての個人情報を含む)が無期限に維持され、このプロジェクトまたは関連するオープンソース・ライセンスに従って再頒布される可能性があることを理解し、同意します。

以下のような "Signed-off-by" トレーラーをあなたのコミットに追加します:

        Signed-off-by: Random J Developer <random@developer.example.org>

-s オプションを指定して git-commit コマンドを実行することにより、 Git がこの行を追加するようにすることもできます。

注意: 上記の D-C-O のルールに従って他人のパッチを転送するときは、 あなた自身の Signed-off-by トレーラーを付けることができることに注意してください。 実際、 そうすることを強く推奨します。 変更の本当の作者に適切にクレジットを帰属させるために、 本文の先頭にインラインの "From: " 行を置くことを忘れないでください(上記 (2) 参照)。

この手順は元々 Linux カーネル・プロジェクト由来であるため、 我々のルールはそれと非常に似ていますが、 パッチにサインオフ(sign-off)することの正確な意味はプロジェクトごとに異なります。 したがって、 あなたが慣れているプロジェクトのものとは異なる場合があります。

Signed-off-by トレーラーでは匿名投稿は受け付けられないため、 既知の身元を使用してください。 実名を使用するのが一般的ですが、 必須ではありません。 一部の貢献者は実名を使用することに抵抗があるか、 偽名や希望する名前で投稿することを好む場合があることを我々は理解しており、 あなたが使用する名前とメールアドレスが明確で、 かつ識別可能で、 かつ誤解を招く恐れが無い限り、 どちらの場合でもパッチを受け付けます。

このポリシーの目的は、 あなたの貢献について質問が生じた場合に、 あなたに連絡するための十分な情報を持つことです。

あなたの必要に応じて、 末尾に追加のトレーラーを追加できます:

  1. Reported-by: は、 パッチが修正しようとしているバグを見つけた人にクレジットを付けるために使用します。

  2. Acked-by: は、パッチが変更しようとしている領域に詳しい人がそのパッチを気に入ったことを示します。

  3. Reviewed-by: は、他のトレーラーとは異なり、 詳細な分析の後にパッチに完全に満足した場合にのみ、 レビューアー自身が付けることができます。

  4. Tested-by: は、 その人がパッチを適用し、 期待した効果があったことを確認したことを示すために使用します。

  5. Co-authored-by: は、パッチを提出する前に人々がパッチの下書きをやりとりしたことを示すために使用します。

  6. Helped-by: は、 パッチ形式での正確な変更を提供せずに、 変更のアイデアを提案してくれた人にクレジットを付けるために使用します。

  7. Mentored-by: は、メンターシップ・プログラム(たとえば GSoC や Outreachy)の一環としてパッチの開発を支援してくれた人にクレジットを付けるために使用します。

  8. Suggested-by: は、パッチのアイデアを提案してくれた人にクレジットを付けるために使用します。

状況によってはあなた独自のトレーラーを作成することもできますが、 我々は、 その代わりに、 上記で明示した、 このプロジェクトで一般的に使用されているトレーラーのいずれかを使用することを推奨します。

トレーラーの最初の文字だけを大文字(capitalize)にしてください。 つまり、 "Signed-Off-By" や "Acked-By" ではなく、"Signed-off-by" や "Acked-by:" が好ましいです。

Use of Artificial Intelligence (AI)(人工知能AIの利用)

Developer’s Certificate of Origin(開発者起源証明書)は、 貢献者がプロジェクトへの自分の貢献の出所を知っており、 プロジェクトのライセンスの下でそれを提出する権利があることを証明することを求めています。 AI ツールによって生成された大量のコンテンツを提出する場合、 これを法的に満たすことができるかどうかはまだ明確ではありません。

AI 生成コンテンツに関するもう一つの問題は、 AI に誤りを指摘してもなお、 しばしば幻覚(hallucination;ハルシネーション)を起こしたり、 質の悪いコード・コミット・メッセージの、 ドキュメントや出力(output)を生成してしまう点です。

これらの問題を避けるため、 我々は、 AI 生成らしく見えるものや、過度に形式的で冗長なものや、典型的な AI の粗悪な出力(AI slop)のように見えるものや、 表面上は良く見えるが意味をなさないものや、 送信者が理解しておらず説明できないもの、 は拒否します。

我々は AI ツールを慎重かつ責任を持って使用することを強く推奨します。

貢献者は、 AI に完全な解決策を求め、 それをまるっとコピペするよりも、 AI を使用してステップ・バイ・ステップで自分で解決策を作成するよう導き、 助けてもらうことで、 より多くの利益を得ることが多いでしょう。 また、 送信前に AI をデバッグ(debugging)の助けに使用したり、 明らかなミスや、 改善できる点や、 我々のスタイル・ガイドライン・フィードバック、 に合わない点をチェックしたりすることもできます。

Generate your patch using Git tools out of your commits.(Gitツールでコミットからパッチ生成)

Git ベースの diff ツールは unidiff を生成しますが、 これが好ましい形式です。

パッチにファイル名の変更が含まれる場合でも、 git diffgit format-patch-M オプションを使うことを恐れる必要はありません。 受け取る側は問題なく処理できます。

あなたのパッチにコメント・アウトされたデバッグ・コードが残っていたり、 目的と関係ない余分なファイルが含まれていないようにしてください。 パッチ生成後には必ず内容を確認し、 正確であることを確かめてください。 送信前に、「Choose a starting point」セクションで選んだ起点に対してパッチがきれいに適用できることも確認してください。

Note
レビューする側から見ると、 デフォルトで期待される起点は master ブランチです。 したがって、 別の起点を選んだ場合は、 カバー・レターでその旨を明確に伝えてください。

Sending your patches.

Choosing your reviewers(レビューワーの選び方)

Note
セキュリティに関係する可能性のあるパッチは、 公開メーリングリストではなく、 Git セキュリティ・メーリングリスト
[Git セキュリティ・メーリングリスト: git-security@googlegroups.com]
に非公開で送信してください。

あなたのパッチを送信する際は、 "To:" にメーリングリストを指定し、 "cc:" には自分が触っている領域に関係する人々を記載して、 コメントやレビューを募集してください(contrib/contacts/ にある git-contacts スクリプト
[contrib/ の下にあるスクリプトは、 コア git バイナリの一部ではないため、 直接呼び出す必要があります。 Git コードベースのクローンを作成し、 perl contrib/contacts/git-contacts を実行します。]
を使うと、 これらの人を特定するのに役立ちます)。 また、 自分のトピックを試しに nextseen にマージした際に、 他の人の作業とコンフリクトが発生していた場合、 その人たちは自分が触っている領域に詳しい可能性が高いです。

あなたが send-email を使う場合、 以下のようにして git-contacts の出力を渡すことができます:

        git send-email --cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch

メーリングリスト上で「このパッチを適用すべき」という合意が得られた後、 "To:" にメンテナー
[The current maintainer: gitster@pobox.com]
を、 "cc:" にメーリングリスト
[The mailing list: git@vger.kernel.org]
を指定して再送信し、 マージを依頼してください。 特に、 メンテナーが議論にあまり参加せず、 レビューを信頼できる他の人に任せていた場合は、 この手順が重要です。

最終版を送信する際は、 パッチに貢献してくれた人々にクレジットを付けるため、 必要に応じて Acked-by:Reviewed-by:Tested-by: などのトレーラーを忘れずに追加し、 その人たちを "cc:" に入れてください。

format-patchsend-email

可能であれば format-patchsend-email の使い方を学んでください。 これらのコマンドは、 パッチ送信ワークフロー用に最適化されており、 既存の(多くの場合 "multipart/*" MIME 形式に最適化されている、)電子メール・クライアントによってパッチが使用できなくなる可能性があるさまざまな状況を回避します。

Note
ここでは format-patchsend-email を使った手順を説明しますが、 代わりに GitGitGadget を使ってパッチを送信することもできます(MyFirstContribution 参照)。

Git メーリングリスト上の人々は、 あなたが送信した変更を読み、 コメントできる必要があります。 開発者が標準的なメール・ツールであなたの変更を「引用」(quote)して、 コードの特定の部分にコメントできるようにすることが重要です。 そのため、 各パッチを一括して添付ファイル群とせず、 それぞれ別々のメールとして「インライン」(それそれ本文に掲載して)で送信してください。

パッチ・シリーズやその他の関連パッチの後続のすべてのバージョンは、 読者がシリーズのすべての部分を見つけやすいように、 全て同じメール・スレッドにまとめてください。 そのためには、 追加の「カバー・レター」(後述)や、 最初のパッチや、またはそれぞれの直前のパッチへの返信として送信してください。 パッチシリーズの更新バージョンの送信方法については step-by-step guide を参照してください。

(Signed-off-by トレーラーに記載されているあなたの名前を含む)ログ・メッセージが ASCII で書き込みできない場合は、 正しいエンコードでメッセージを送信していることを確認してください。

Warning
メール・クライアント(MUA)の自動折り返し機能によってパッチが壊れることがあります。 パッチをコピペしないでください。 注意しないとタブ(TAB)が消えることがあります。

メールの件名の先頭に [PATCH] を入れるのが一般的な慣例です。 これにより、 他のメール議論と区別しやすくなります。 [PATCH] だけでなく、 [] 内に追加のマーカーを入れてパッチの性質を示すことも推奨されます。 たとえば、 [RFC PATCH] (RFC は "request for comments" の略で、さらに議論が必要な場合に使用)とか、 以前に送った内容の更新版であることを示すための [PATCH v2] ・ [PATCH v3] などはよく使われます。

git format-patch コマンドは、 現在のベスト・プラクティスに従ってメール本文を整形します。 パッチの冒頭にはコミット・メッセージが来て、 そして、 Signed-off-by トレーラーで終わり、 その後に 3 本のダッシュ(---)からなる行、 そして diffstat 情報、 最後にパッチ本体が続きます。 他人のパッチを転送する場合は、 任意でメールの冒頭(コミット・メッセージの直前)に "From: " 行を置いてその人の名前を記載できます。 デフォルトの "[PATCH]" を "[<text>]" に変えるには git format-patch --subject-prefix=<text> を使ってください。 ショートカットとして、 --rfc--subject-prefix="RFC PATCH" と同等で、 -v <n>--subject-prefix="PATCH v<n>" と同等です。

コミット・メッセージ以外にパッチについて追加の説明をしたいことがよくあります。 そのような「カバーレター」用の内容は、3 本のダッシュの行(---)と diffstat の間に置いてください。 複数回のレビューと議論が必要なパッチの場合、 各繰り返し間(iteration)の変更説明を Git-notes に保存しておき、 git format-patch --notes によって 3 本のダッシュ(---)の直後に自動的に挿入することもできます。

これは実験版 です。

トピックを送信する際、オプションで、 "What’s cooking" レポートに掲載された時のためのトピック名や 1 段落の概要を提案できます。 その場合、 リリースノートにそのまま使える 2〜5行 のわかりやすい段落を書いてください(Documentation/RelNotes/* 内の箇条書きに多数の例があります)。 その段落を カバーレターの1番目(トピック名も提案する場合は2番目)の段落にしてください。 トピック名を提案する場合は XX/your-topic-name の形式にしてください(XX は主著者のイニシャル、 your-topic-name はダッシュで区切った簡単な説明)。 単一パッチのシリーズの場合は、 前述の通り、 3本のダッシュの行(---)と diffstat の間に書いてください。

パッチシリーズが複数のシリーズにまたがる大きな取り組みの一部である場合は、 その全体の目標を簡単に説明し、 現在のシリーズがその目標のどこに位置するかを明記してください。 上記 のようにトピック名を提案する場合は、"XX/the-broader-goal-part-one", "XX/the-broader-goal-part-two" のようにしてください。

パッチを、圧縮・非圧縮問わず MIME 添付ファイルで送信してはいけません。 メール・クライアントに quoted-printable や format=flowed を送らせないでください。 これらはパッチ内の空白(whitespaces)を壊します。 多くの一般的なメールアプリは MIME 添付を純粋なテキストとして送ることができず、 あなたのコードへのコメントが実質的に不可能になります。 これによって、 MIME 添付された変更が受け入れられる可能性が低下するわけではありませんが、 後回しにされる可能性が高くなります。

例外: あなたのメールソフトがパッチを壊してしまう場合、 誰かが「MIME で再送して」と頼むことがあります。 そのときは MINE 添付で送信して構いません。

あなたのパッチに PGP 署名をしないでください。 ほとんどの場合、 メンテナーやメーリングリストの人々はあなたの PGP キーを保有しておらず、 わざわざ取得しようともしません。 あなたのパッチは誰が書いたかではなく内容で判断されます。 知らない人からの良いパッチの方が、 著名な人からの悪いパッチよりはるかに受け入れられやすいです。

どうしても PGP 署名したい場合は、 "multipart/signed" 形式にしてください。 -----BEGIN PGP SIGNED MESSAGE----- で始まる text/plain メッセージは text/plain ではありません。 ホンマにホンマにホンマにやめてくれよな!ホンマやで!

Handling Conflicts and Iterating Patches(競合処理とパッチの繰り返し)

あなたがパッチを修正する際は、 他の進行中のトピックと競合する可能性を認識することが重要です。 以下の推奨手順に従うことで、 競合を効果的に回避・解決できます:

  1. 適切なベース・ブランチの上に構築してください(上記セクション 参照)。その上で format-patch でシリーズを作成します。 前回の回(previous round)から "rebase -i" でその場(in-place)で更新している場合は、 以前と同じベースが再利用されるため、 後述の (2) と (3) はほぼ自動的に行われます。

  2. 前回の回(the last round)がどこにキューイングされたかを確認してください。

    $ mine='kn/ref-transaction-symref'
    $ git checkout "origin/seen^{/^Merge branch '$mine'}...master"
  3. あなたの format-patch の結果を適用します。 そうすると以下の2つの場合があります

    1. 物事はきれいに適用(apply)され、テストも問題ない場合。 (4) へ進んで下さい。

    2. 問題は正しく適用(apply)されますが、ビルドされなかったりテストが失敗するパターンと、 そもそも問題が正しく適用(apply)されないパターン。

      この場合、 古いベースと (1) で構築したベースとの違いに起因するテキスト的または意味的な矛盾が発生しています。 破損の原因を特定してください(たとえば (2) のベース以降に、 (1) のベースまでに1つまたは2つのトピックがマージされた、 など)。

      最新の origin/master ((2) で使ったベースより新しいハズ)をチェックアウトし、 そこに新しく依存するようになったトピックを merge --no-ff でマージします。 そのマージ結果を新しいベースとして使い、 シリーズを再構築(rebuild)し、 もう一度テストしてください。 最後にマージしたコミットから自分のトピックの先端まで format-patch を実行します。 たとえば以下のようにします

      $ git checkout origin/master
      $ git merge --no-ff --into-name kn/ref-transaction-symref fo/obar
      $ git merge --no-ff --into-name kn/ref-transaction-symref ba/zqux
      ... rebuild the topic ...

      そして、 これらの「基礎を整えた」(preparing the ground)マージの上であなたのトピックフォーマットします。 たとえば以下のようにします

      $ git format-patch "HEAD^{/^Merge branch 'ba/zqux'}"..HEAD

      カバーレターに、 あなたが行った master の上のあなたのベースにトピックを含める作業を行ったのを書くのを忘れないでください。 その後 (4) に進みます。

  4. あなたのトピックを nextseen にマージする事を試みます。 たとえば以下のようにします。

    $ git checkout --detach 'origin/seen'
    $ git revert -m 1 <the merge of the previous iteration into seen>
    $ git merge kn/ref-transaction-symref

    (今回の例のように、)前回で既に seen に取り込まれている場合、 revert が必要になります。 あるいは、 master..origin/seen をゼロから作り直しつつ自分の前回分を除外する方法を選んでも構いません。 その場合メンテナー側での処理をより厳密に模擬することになります。

    この試行マージで競合が発生することもあります。 試行マージの主な目的は、 あなたのトピックが他のトピックとどのような競合を起こすかを確認することです。 あなたのトピックを master 上で動かすために必ずこの試行マージの競合を解決する必要がある訳ではありません。 なぜなら、 あなたのトピックが先に next に入った場合、 競合の解消はむしろ他のトピックのオーナーの仕事になる可能性があるからです。

    試行マージであなたが出会った競合はカバーレターに記載してください。 必ずしもそれらを自分で解決する必要はありませんが、 お互いに関連領域で他の人が何をしているかを学ぶ良い機会となるでしょう。

    $ git checkout --detach 'origin/next'
    $ git merge kn/ref-transaction-symref

    これは、 あなたのトピックが現在進行中の他のトピックとどのような競合を起こすかを確認するためのものです。 (3)-2 が、 更新された masternext から取得した依存トピックの上にベースを準備した場合、 これは競合しないはずです。 深刻なコンテキストの変更がない限り(判断方法の1つは、 古い回でも同じ試行マージをしてみることです。 似たような競合が出るなら問題は同様)、 メンテナー側で処理されることを期待してください(手に負えなくなったら、 私があなたのパッチを受け取ったときにリベースを依頼します)。

Subsystems with dedicated maintainers(専任メンテナーがいるサブシステム)

システムの一部には、 独自のリポジトリーを持つ専任のメンテナーがいます。

  • git-gui/ は、 Johannes Sixt によって管理されている git-gui プロジェクト由来です:

    https://github.com/j6t/git-gui
    貢献は git メーリング リスト経由で行う必要があります。
  • gitk-git/ は、Johannes Sixt によって保守されている gitk プロジェクト由来です:

    https://github.com/j6t/gitk
    貢献は git メーリング リスト経由で行う必要があります。
  • po/ ローカライゼーション・コーディネーターの Jiang Xin 管理です:

    https://github.com/git-l10n/git-po/

これらのパーツへのパッチは、 そのツリーに基づいて作成する必要があります。

  • Jean-Noël Avila が率いる「Git ドキュメント翻訳」(Git documentation translations)プロジェクトは、 ドキュメント・ページを翻訳しています。 彼らの作業成果物は、 ツリーの一部としてではなく、 このプロジェクトとは別に維持されます:

    https://github.com/jnavila/git-manpages-l10n/

GitHub CI

GitHub アカウントを持っていれば、 GitHub CI を使って Linux と Mac と Windows 上であなたの変更をテストできます。 最近の CI 実行例は https://github.com/git/git/actions/workflows/main.yml を参照してください。

初回のセットアップは以下の手順で行ってください:

  1. https://github.com/git/git を自分の GitHub アカウントにフォーク(fork)してください。フォークの詳しい手順は https://help.github.com/articles/fork-a-repo/ を参照してください。

初回セットアップ後、 GitHub 上の自分の Git フォークに新しい変更をプッシュするたびに CI が実行されます。 あなたのすべてのブランチのテスト状態はこちらで確認できます: https://github.com/<あなたの GitHub ハンドル名>/git/actions/workflows/main.yml

ブランチがすべてのテストに合格しない場合、 緑色のチェックマークではなく赤い × が表示されます。 その場合は、 失敗したジョブをクリックし、 "ci/run-build-and-tests.sh" や "ci/print-test-failures.sh" に移動してください。 また、 デバッグに関連するテスト・データを含む tar 化された(または zip 圧縮された)アーカイブを含む zip アーカイブである「Artifacts」をダウンロードすることもできます。

問題を修正したら、 その修正を自分の GitHub フォークにプッシュしてください。 これにより新しい CI ビルドが起動し、 すべてのテストが通ることを確認できます。

MUA specific hints(メール・クライアント毎のヒント)

メーリングリストから受け取ったり(receive)拾ったり(pick up)するパッチの一部には、 共通の破損パターンが見受けられます。 空白(whitespaces)が壊れないよう、 あなたのメール・クライアント(MUA)が正しく設定されていることを確認してください。

自分のパッチを自分自身にメールで送り、 git-am(1) で適用してみることであなたのパッチをチェックする際のヒントについては、 git-format-patch(1) の DISCUSSION セクションを参照してください。

その時ついでに、 そのパッチを適用する試行で得られるコミット・ログ・メッセージも確認してください。 結果として得られるコミットに含まれる内容が、 あなたが本当に見せたいものと完全に一致していない場合、 メンテナーがあなたのパッチを適用する際に手動でログ・メッセージを編集する羽目になる可能性が非常に高いです。 "Hi, this is my first patch.\n" のような文は、 あなたが本当にパッチ・メールに入れたい場合でも、 コミット・メッセージの終わりを示す 3 本のダッシュの行(---)の後に置くべきです。

Pine メール・クライアント

(Johannes Schindelin)

pine を今でも使っている人がどれだけいるかはわかりませんが、
そういう可哀想な人たちのために、最近のバージョンでは
quell-flowed-text が必要であることを書いておくと良いかもしれません。

... また、"no-strip-whitespace-before-send" オプションも必要です。
私の知る限り、 これは 4.60 で導入されました。

(Linus Torvalds)

そして 4.58 では少なくとも以下のパッチが必要です。

diff-tree 8326dd8350be64ac7fc805f6563a1d61ad10d32c (from e886a61f76edf5410573e92e38ce22974f9c40f1)
Author: Linus Torvalds <torvalds@g5.osdl.org>
Date:   Mon Aug 15 17:23:51 2005 -0700

    Fix pine whitespace-corruption bug

    There's no excuse for unconditionally removing whitespace from
    the pico buffers on close.

diff --git a/pico/pico.c b/pico/pico.c
--- a/pico/pico.c
+++ b/pico/pico.c
@@ -219,7 +219,9 @@ PICO *pm;
            switch(pico_all_done){      /* prepare for/handle final events */
              case COMP_EXIT :          /* already confirmed */
                packheader();
+#if 0
                stripwhitespace();
+#endif
                c |= COMP_EXIT;
                break;

(Daniel Barkalow)

> SubmittingPatches に、Pine 4.63 ユーザ向けの MUA 固有の
> ヘルプセクションを追加するパッチは、とてもありがたいと思います。

えーっと、 最近のバージョンでデフォルトの振る舞いがが正しいものに変更され、
設定オプションの意味が逆になったようです(もしくは Gentoo がそうしたのかもしれません)。
`no-strip-whitespace-before-send` オプションが存在するなら、それを設定(set)する必要があります。
そして
`strip-whitespace-before-send` オプションは設定を外す(unset)する必要があります。

Thunderbird, KMail, GMail

git-format-patch(1) の「MUA-SPECIFIC HINTS」セクションを参照してください。

Gnus (Emacs メッセージ・リーダー)

*Summary* バッファで "|" を使用すると、 現在のメッセージを外部プログラムにパイプできます。 これが git am を実行する便利な方法です。 しかし、 メッセージが MIME エンコードされている場合、 パイプされる内容は *Article* バッファで MIME を展開した後に見えている表示形式になります。 これは多くの場合、望ましくない結果になります。 理由は2つあります。 非 ASCII 文字(特に人名)を壊しやすいことと、 空白(whitespaces)を壊すことです(パッチの場合、致命的)。 これを回避するには、"|" でパイプを実行する前に C-u g を押してメッセージを生の形式で表示しておくと上手くいきます。