7: 上級の話題

この段階で、読者は開発プロセスの仕組みについて理解したものと期待されます。しかし、学習すべきことがまだあります。本セクションでは、Linuxカーネル開発プロセスの常連になることを目指す開発者に役立つ、様々な話題について述べます。

7.1: gitによるパッチ管理

Linuxカーネルの分散型バージョン管理は2002年に開始され、この時にLinusは初めて独自のBitKeeperアプリケーションによるバージョン管理に取り組みました。BitKeeperについては賛否両論がありますが、その中で具体化されたソフトウェア・バージョン管理のアプローチについては疑う余地のない確立されたシステムです。この分散型バージョン管理により、カーネル開発プロジェクトはさらに加速されました。現在はBitKeeperの代りになるフリーソフトウェアがいくつかあります。良くも悪くも、カーネル・プロジェクトはツールとして git を選択しました。

特にパッチの数が増すにつれ、gitによるパッチ管理は開発者の負担を大幅に軽減します。gitには荒削りな部分もあり、多少の危険性もありますが、若く力強いツールであり、現在もその開発者による改良が行われています。この文書は、読者に対しgitの使用法を説明するようなことはしません。そのことを説明している資料はほかにたくさんあります。その代わり、ここでは git がカーネル開発プロセスにどうマージされているかということに特に焦点を当てます。git について十分に学習し使えるレベルに到達したい開発者向けには、以下のサイトに詳しい内容があります。

http://git.or.cz/

http://www.kernel.org/pub/software/scm/git/docs/user-manual.html

また、上記以外にも、Web上には様々な教材があります。

git を使ってパッチを他の人に利用させようとする前に、最初に取り組むべきことは、これらのサイトの内容を良く読み、gitの動作を確実に理解することです。gitを使う開発者は、メインライン・レポジトリのコピーの取得、リビジョン履歴の調査、ツリーへの変更の追加、ブランチの利用等ができるはずです。また、履歴の書き直しのためのgitツールを理解することも有用です(rebaseなど)。gitにはその特有の用語や概念があります。gitを初めて使うユーザーはref、remote branch、index、fast-forward merge、pushやpull、detached headといった内容について理解することが必要です。これらはいずれも最初は少し困難さを感じますが、少し学習すれば、その概念を把握することはそれほど難しくありません。

git を使ってパッチを作成しメールで提出することは、gitを使いこなせるようになるための良い練習になります。

他から見ることのできる gitツリーを立ち上げる準備ができたら、当然ながらその内容をプルするためのサーバが必要となります。インターネットにアクセス可能なシステムがあれば、そのようなサーバにgit-daemonをセットアップするのは比較的簡単な作業です。さもなければ、フリーのパブリック・ホスティング・サイト(たとえばGithub)がネット上でサービスを提供しております。また既に経験のある開発者はkernel.orgにアカウントを得ることができますが、そのような開発者になるのは簡単なことではありません。詳細についてはhttp://kernel.org/faq/を参照してください。

通常の git ワークフローには多くのブランチが使用されます。各開発ラインは独立したトピックブランチ「topic branch」に分けることができ、独立した管理が可能です。gitにおけるブランチは簡単に作れます。これらを自由に使わない理由はありません。また、いかなる場合であっても、外からプルさせようとするブランチで自分の開発を行うべきではありません。一般に公開するブランチは慎重に作成することが必要です。開発ブランチからのパッチのマージは、そのパッチが十分に完成して準備が整うまでは行わないでください。

gitには、自分の開発履歴を書き直すことができる、強力なツールがあります。不都合なパッチ(bisectionを破壊するものや、その他の明白なバグのあるものなど)は所定の場所に固定したり、あるいは履歴から完全に消去したりすることができます。何ヶ月も作業を続けてきたパッチ群であっても、あたかも現在のメインライン上に書かれてきたかのようにパッチ群を書き直すことができます。変更をひとつのブランチから別のブランチへと透過的に移すことができます。その他、多くの機能があります。履歴を改訂できるgitの能力を賢く利用することで、問題の少ないクリーンなパッチ群が作成できます。

ただし、この機能を過度に利用すると、完全なプロジェクト履歴を作成したいという単純な要求以外の別の問題が発生する可能性があります。履歴の書き直しは、その履歴に含まれる変更の書き直しとなり、テスト済み(と期待される)カーネル・ツリーが未テストのツリーに変わってしまいます。しかし、それ以上に、プロジェクト履歴の表示が共有できない場合、開発者間の連携が困難になります。たとえば、他の開発者がそのレポジトリにプルした履歴を自分が勝手に書き直してしまった場合、その開発者にとって面倒なことになります。そのため、ここでは、「外部にエクスポートされた履歴は原則としてそれ以降、不変とする」という簡単な経験則が適用されます。

したがって、その変更セットを自分の公開サーバにプッシュした後は、その変更について書き直しを行ってはなりません。もし「fast-forward merge」が行えないような変更(同じ履歴を共有していない変更)をプッシュしようとしても、gitはこのルールを適用されます。このチェックを無効にすることは可能で、またエクスポート済みツリーの書き直しが必要となる場合もあると考えられます。その1例として、linux-nextでの競合を避けるためツリー間で変更セットを移動することもあります。しかし、そのようなことは稀です。これは、開発は(必要に応じ書き直しが可能な)プライベート・ブランチで行い、十分に熟成した状態になってからパブリック・ブランチに移動させるべきだということのひとつの理由です。

メインライン(または変更のベースとなるその他のツリー)が進化するにつれ、その最先端のツリーを追いかけるためにこのツリーにマージしたいと思うでしょう。プライベート・ブランチの場合には別のツリーに遅れないようレベルを合わせていくためのベースの変更は容易ですが、外部の世界に対しツリーをエクスポートしてしまった後は、ベースを変更するという選択肢はありません。一度これを行なってしまった後は、全体の完全なマージを行わなければなりません。時折マージを行うことはたいへん意味のあることですが、過度な頻度でマージを行うと、履歴が不必要に乱雑になってしまいます。この場合に提案される手法はマージの頻度を減らすことで、一般には特定のリリース・ポイント(メインラインの -rc リリースなど)に限定することです。特定の変更が気になる場合、プライベート・ブランチでのテスト・マージはいつでも可能です。gitの「rerere」ツールはそのような場合に有効です。このツールはマージの競合がどのように解決されたかを記憶しているため、同じ作業を2回繰り返す必要はありません。

何回もむしかえされるgitのようなツールに関する不満は、パッチがひとつのレポジトリから別のレポジトリへと大量に移動することにより、不具合のある変更も紛れ込み、レビューのレーダー監視網を逃れてメインラインに入り込むというものです。カーネル開発者は、このような事が発生すると悲しい思いをします。レビューされていないパッチや話題からずれたパッチが含まれたツリーを立ち上げてしまうと、将来的には自分のツリーをプルしてもらえなくなってきます。Linusの言葉を引用します。

皆さんは私にパッチを送ることができますが、私がgitパッチをプルするためには、私はそのツリーで何が行われているかを知る必要があります。その時、個々の変更を自らの手でチェックすることなく、そのことを信用できることが必要です。

(http://lwn.net/Articles/224135/ )

このような状況を避けるため、そのブランチに含まれるすべてのパッチがその関係するトピックに密接に関係しているようにすることが必要です。たとえば「driver fixes」というブランチがコアメモリー管理用のコードの変更を行うようなことがあってはなりません。また、最もやってはいけないことはなことは、レビュー・プロセスをバイパスするためにgitツリーを使わないということです。時折、関連するメーリングリストにツリーのサマリーをポストし、適切なタイミングでそのツリーをlinux-nextに含めるよう依頼しましょう。

他から自分のツリーに含めるようパッチが送られてくるようになった場合、それらパッチのレビューを忘れないようにします。また、正しい作者情報を維持するようにします。gitの「am」ツールはこの点で最適ですが、サードパーティ経由で送られてきた場合、自分でそのパッチに「From:」行を追加することが必要となる場合もあります。

プルを依頼する場合、そのツリーのある場所、プルすべきブランチ、またそのプルによりどのような変更が行われるかなど、関係する情報をもれなく提供するようにしてください。gitの「request-pull」コマンドはこの点で役に立ちます。このツールは他の開発者の期待するフォーマット化を行うと共に、パブリック・サーバにそれらの変更をプッシュしたことが記憶されていることも確認します。

7.2: パッチのレビュー

一部の読者は、初心者のカーネル開発者でもパッチのレビューを行うはずだということから、この項目を「高度なトピック題」に含めることには反対でしょう。たしかに、他人がポストしたコードをレビューする以外にカーネル環境におけるプログラミングの方法を学習する良い方法はない、ということは言えます。それに加え、レビューアは常に不足しています。コードを良く見ることで、全体としてのプロセスに大きく貢献することができます。

コードのレビューにはプレッシャーがかかりがちです。特に、新たにカーネルの開発を行う人は、より経験の深い開発者がポストしたコードについてオープンな場で質問することには緊張感を感じるでしょう。しかし、最も経験の深い開発者が書いたコードであっても、その改良が可能な場合はあります。おそらく、レビューア(すべてのレビューア)に対する最も適切なアドバイスは、レビューのコメントを「批判」ではなく「質問」の形で表現することです。「このロックは、このパスでどのように開放されるのでしょうか?」という質問は、「ここのロックは間違っている」という言い方よりも常に良い結果が出ます。

様々な開発者が、それぞれ別の観点からレビューを行います。コーディング・スタイルや、コード行の最後にスペースが入っているかどうか、といったことを主として気にする人もいます。また、そのパッチの変更がカーネルにとって全体的に良いことか悪いことかに重点を置く人もいます。またその他にも、問題の多いロックや過度のスタックの利用、セキュリティ問題の可能性、他の部分とのコードの重複、ドキュメンテーションの適切さ、性能に対する悪影響、ユーザー空間ABIの変更といった内容をチェックする人もいます。そのレビューが優れたコードをカーネルにマージすることにつながるなら、すべて歓迎される価値のあるレビューです。