SYNOPSIS

git *

DESCRIPTION

この文書は、 git.git 自体に使用されるワークフロー要素のいくつかを書き留めて動機付けしようとしています。一般に多くのアイデアが当てはまりますが、関係者が少ない小規模なプロジェクトではこのような完全なワークフローが必要になることはめったにありません。

私たちが、すぐに参照できるように一連の「ルール」を作ったのは、本当にみんなのモチベーションを高めるためです。ですから常に文字通りに解釈する必要はありません。このような文章よりも、自分の行動に対する正当な理由を大切にしてください。

SEPARATE CHANGES

原則として、変更を小さな論理ステップに分割し、それぞれでコミットするようにしてください。それらは一貫性があり、その後のコミットとは独立して機能し、テストスイートに合格する必要があります。これにより、レビュープロセスがはるかに簡単になり、その履歴は、たとえば git-blame(1)git-bisect(1)を使用して後で検査や分析する時にはるかに役立ちます。

これを実現するには、最初から作業を小さなステップに分割してみてください。1つの大きなコミットを複数に分割するよりも、いくつかのコミットをまとめる方が常に簡単です。途中で小さすぎる、または不完全なステップを作成することを恐れないでください。いつでも後で戻って、公開する前に git rebase --interactive を使用してコミットを編集できます。 git stash push --keep-index を使用して、他のコミットされていない変更とは無関係にテストスイートを実行できます。 git-stash(1) の「EXAMPLES」セクションを参照してください。

MANAGING BRANCHES

あるブランチから別のブランチへの変更を含めるために使用できる2つの主要なツールがあります。 git-merge(1)git-cherry-pick(1) です。

マージには多くの利点があるため、マージだけで可能な限り多くの問題を解決しようとしています。 cherry-pickingまだ時々役に立ちます。例については、以下の「Merging upwards」を参照してください。

最も重要なことは、マージはブランチレベルで機能し、チェリーピッキングはコミットレベルで機能することです。これは、マージが1、10、または1000のコミットからの変更を同じように簡単に引き継ぐことができることを意味します。つまり、ワークフローは多数の貢献者(および貢献)に対してはるかに適切にスケーリングされます。マージコミットは、すべての親からのすべての変更が含まれた「約束」(promise)であるため、マージも理解しやすくなります。

もちろん、トレードオフがあります。マージには、より慎重なブランチ管理が必要です。以下のサブセクションでは、重要なポイントについて説明します。

Graduation

特定の機能が実験的なもの(experimental)から安定したもの(stable)に変わると、ソフトウェアの対応するブランチ間でも「段階的に」(graduates)移行します。 git.git は以下の「統合ブランチ」(integration branches)を使用します:

  • maint は、次の「メンテナンスリリース」(maintenance release)、つまり最後にリリースされた安定バージョンの更新に入るコミットを追跡します

  • master は、次のリリースに入る予定のコミットを追跡します。

  • next は、masterの安定性をテストするトピックのテストブランチとして意図されています。

少し異なる方法で使用される4番目の公式ブランチがあります:

  • seen (メンテナによって表示されるパッチ)は、まだ含める準備が整っていないモノの統合ブランチです(以下の「Integration Branches」を参照)。

4つのブランチのそれぞれは、通常、その上のブランチの直接の子孫です。

概念的には、機能(feature)は不安定なブランチ(通常は「next」または「seen」)に入り、十分に安定している(stable)と見なされると、次のリリースのために「master」に「卒業」(graduates)します。

Merging upwards

上記の「downwards graduation」(下向きの卒業)は、実際に下向きにマージすることによって実行することはできません。なぜなら、不安定なブランチの「すべての」変更が安定したブランチにマージされるためです。 したがって、以下のようになります:

Rule: Merge upwards

修正を必要とするサポートされている最も古いブランチに常に修正をコミットします。 次に、 (定期的に)統合ブランチを互いに上向きにマージします。

これにより、修正のフローが非常によく制御されます。たとえば、修正を適用したことに気付いた場合。 maint でも必要な master は、(git-cherry-pick(1) を使用して)下向きにチェリーピックする必要があります。これは数回発生しますが、頻繁に実行しない限り心配する必要はありません。

Topic branches

重要な機能を実装するにはいくつかのパッチが必要であり、その存続期間中に追加のバグ修正または改善が行われる可能性があります。

統合ブランチですべてを直接コミットすると、多くの問題が発生します。不正なコミットは元に戻せないため、1つずつ元に戻す必要があります。これにより、変更のグループの一部を元に戻すのを忘れると、混乱した履歴とエラーが発生する可能性があります。並行して作業すると、変更がごちゃまぜになり、さらに混乱が生じます。

「topic branches」(トピックブランチ)を使用すると、これらの問題が解決されます。名前はかなり自明ですが、上記の「merge upwards」(上向きにマージ)ルールに由来する警告があります:

Rule: Topic branches

すべてのトピック(機能、バグ修正など)のサイドブランチを作成します。最終的にマージする最も古い統合ブランチでフォークします。

そうすれば、以下のように多くのことが非常に自然に実行できます:

  • 機能/バグ修正を統合ブランチに取り込むには、それをマージするだけです。その間にトピックがさらに進化した場合は、再度マージしてください。 (必ずしも最初に最も古い統合ブランチにマージする必要はないことに注意してください。たとえば、最初にバグ修正を next にマージし、テスト時間を与え、安定していることがわかったら maint にマージできます。)

  • トピックの作業を続行するためにブランチ other の新機能が必要な場合は、 other を topic にマージします。 (ただし、これを「習慣的に」行わないでください。以下を参照してください。)

  • 分岐したブランチが間違っていることに気づき、それを「過去にさかのぼって」移動したい場合は、 git-rebase(1) を使用してください。

注意: 最後の項目が他の2つと衝突することに注意してください。他の場所でマージされたトピックは、リベースしないでください。 git-rebase(1) の「RECOVERING FROM UPSTREAM REBASE」に関するセクションを参照してください。

(通常は理由もなく)「習慣的に」統合ブランチをあなたのトピックにマージすること(つまり、トピックを拡張し、定期的に上流からマージし続けること)は眉をひそめられる行為であることを指摘しておく必要があります。

Rule: 明確に定義されたポイントでのみ下流にマージします

正当な理由がある場合を除いて、ダウンストリームにマージしないでください。正当な理由とは、例えば、アップストリームAPIの変更がブランチに影響する、ブランチがアップストリームにきれいにマージされなくなりました、等です。

正当な理由以外の場合、マージされたトピックには、(激しくバラバラの)突然の複数の変更が含まれます。結果として生じる多くの小さなマージは、履歴を大幅に混乱させます。後でファイルの履歴を調査する人は、そのマージが開発中のトピックに影響を与えたかどうかを確認する必要があります。アップストリームは、誤って「より安定した」ブランチにマージされることさえあるかも等々。

使い捨て統合

先程の話題についていうと、多くの小さなトピックブランチがあり、あなたはそれらがどのように相互作用するのかワケワカメに思うことがあるでしょう。それらをマージしたらちゃんと機能しないかも? そして、このようなマージは簡単に元に戻せないため、我々はこれらに対して「安定した」場所でのマージは避けたいと考えています。

もちろん、解決策は、元に戻すことができるマージを作成することです。つまり、使い捨てブランチ(throw-away branch)にマージします。

Rule: Throw-away integration branches

いくつかのトピックの相互作用をテストするには、それらを使い捨てのブランチにマージします。あなたは決してそのようなブランチに基づいて作業を行ってはいけません!

テストの直後にこのブランチが削除されることを(非常に)明確にすると、このブランチを公開して、たとえば、テスターがこのブランチを操作できるようにしたり、他の開発者が進行中の作業に互換性があるかどうかを確認したりすることもできます。 git.git には、「seen」と呼ばれるそのような公式の使い捨て統合ブランチがあります。

Branch management for a release

上記のマージアプローチを使用していると仮定すると、プロジェクトをリリースするときに、追加のブランチ管理作業を行う必要があります。

「master」は次の機能(feature)リリースに入るコミットを追跡するため、機能(feature)リリースは「master」ブランチから作成されます。

master ブランチは、 maint のスーパーセットであると想定されています。この条件が満たされない場合、 maint には master に含まれていないコミットが含まれています。したがって、 maint のコミットによって表される修正は、機能(feature)リリースには含まれません。

master が実際に maint のスーパーセットであることを確認するには、 git log を使用します:

Recipe: master が maint のスーパーセットであることを確認(verify)します:

git log master..maint

このコマンドは、コミットを一切リストしないはずです。そうでない場合は、「master」をチェックアウトし、「maint」をマージします。

これで、あなたは機能(feature)リリースの作成に進むことができます。リリースバージョンを示すタグを「master」の先端に適用します:

Recipe: Release tagging

git tag -s -m "Git X.Y.Z" vX.Y.Z master

あなたは新しいタグをパブリックGitサーバーにプッシュする必要があります(以下の「DISTRIBUTED WORKFLOWS」参照)。これにより、プロジェクトを追跡している他のユーザーがタグを利用できるようになります。プッシュでは、更新後のフックをトリガーして、リリースtarballの作成や事前にフォーマットされたドキュメントページなどのリリース関連の項目を実行することもできます。

同様に、メンテナンスリリースの場合、「maint」はリリースされるコミットを追跡します。ゆえに、タグのリリース手順では、「master」ではなく「maint」にタグを付けてプッシュするだけです。

機能リリース後のメンテナンスブランチ管理

機能(feature)リリース後、あなたはメンテナンスブランチを管理する必要があります。

まず、直近のリリースより前に行われた機能リリースのメンテナンス修正を引き続きリリースする場合は、その前のリリースのコミットを追跡するために別のブランチを作成する必要があります。

これを行うために、現在のメンテナンスブランチは、以前のリリースバージョン番号で名前が付けられた別のブランチにコピーされます(例: maint-X.Y.(Z-1) ここでX.Y.Zは現在のリリースとする)。

Recipe: Copy maint

git branch maint-X.Y.(Z-1) maint

maint ブランチは、新しくリリースされたコードに早送り(fast-forwarded)され、現在のリリースのメンテナンス修正を追跡できるようになります:

Recipe: Update maint to new release
  • git checkout maint

  • git merge --ff-only master

早送り(fast-forwarded)ではないためにマージが失敗した場合は、機能リリースで「maint」のいくつかの修正が欠落している可能性があります。前のセクションで説明したようにブランチのコンテンツを検証(verify)した場合、これは発生しません。

機能リリース後の「next」と「seen」のブランチ管理

機能のリリース後、統合ブランチ next は、オプションで、 next の残りのトピックを使用して、 master の先端から巻き戻されて再構築される場合があります:

Recipe: Rewind and rebuild next
  • git switch -C next master

  • git merge ai/topic_in_next1

  • git merge ai/topic_in_next2

これを行うことの利点は、「next」の履歴がクリーンになることです。 たとえば、「next」にマージされた一部のトピックは、最初は有望に見えたかもしれませんが、後で望ましくないか時期尚早であることがわかりました。このような場合、トピックは「next」から元に戻され(revert)ますが、一度マージされて元に戻されたという事実は履歴に残ります。「next」を再作成することで、そのようなトピックの別の化身に再試行するためのきれいな状態を与えることができます。機能のリリースは、これを行うための履歴上の良い地点です。

これを行う場合は、「next」が巻き戻されて再構築されたことを示す公開アナウンスを行う必要があります。

「seen」についても、同じの巻き戻しと再構築のプロセスを行います。なお、上記のとおり「seen」は使い捨てのブランチであるため、公の発表は必要ありません。

DISTRIBUTED WORKFLOWS

前セクションを読んだ今となっては、あなたはトピックを管理する方法を知っておくべきです。 一般的に、プロジェクトに取り組んでいるのはあなただけではないので、あなたの仕事は共有しなければなりません。

大まかに言えば、マージとパッチという2つの重要な作業フローがあります。重要な違いは、マージ作業フローはマージを含む完全な履歴を伝播できますが、パッチは伝播できないことです。両方の作業フローを並行して使用できます。git.git では、サブシステムメンテナのみがマージ作業フローを使用し、他のすべての作業フローはパッチを送信します。

注意: メンテナは、インクルードするために提出されたすべてのコミット/パッチが遵守しなければならない「Signed-off-by」要件などの制限を課すことができることに注意してください。より詳細な情報については、プロジェクトのドキュメントを参照してください。

Merge workflow

マージ作業フローは、上流(upstream)と下流(downstream)の間でブランチをコピーすることによって機能します。上流では、貢献の結果を公式の履歴に統合することができます。下流では、公式の履歴に基づいて作業します。

これに使用できる主なツールは3つあります:

  • git-push(1) は、ブランチをリモートリポジトリにコピーします。通常は、関係者全員が読み取れるリポジトリにコピーします。

  • git-fetch(1) は、リモートブランチをあなたのリポジトリにコピーします。

  • git-pull(1) は、フェッチしてマージするのを一度に行います。

注意: 最後の点に注意してください。 実際にリモートブランチをマージする場合を除いて git pull を使用しないでください。

変更を取得するのは簡単です:

Recipe: push/pull: branches/topics の公開

git push <remote> <branch> を実行、そして、どこからフェッチできるかをみんなに伝えます。

あなたは今の所メールなどの他の手段で人々に伝えなければなりません。 (Gitは git-request-pull(1) を提供して、このタスクを簡素化するために、事前にフォーマットされたプルリクエストをアップストリームのメンテナーに送信します。 )

統合ブランチの最新のコピーを取得したいだけの場合は、最新の状態に保つのも簡単です:

Recipe: push/pull: 最新の状態に保つ

最新の状態に保つには git fetch <remote> または git remote update を使います。

次に、以前に説明したように、安定したリモートからトピックブランチをフォークするだけです。

あなたがメンテナであり、他の人のトピックブランチを統合ブランチにマージしたい場合、他の人々は通常、メールでそうするようにリクエストを送信してきます。そのようなリクエストは以下のようになります

Please pull from
    <URL> <branch>

その場合、 git pull は、以下のように、フェッチとマージを一度に実行できます。

Recipe: Push/pull: Merging remote topics

git pull <URL> <branch>

場合によっては、メンテナが下流(downstream)から変更をプルしようとすると、マージの競合が発生することがあります。 この場合、下流にマージを実行して競合を彼ら自身で解決するように依頼できます(おそらく、彼らは競合を解決する方法をよりよく知っているでしょう)。これは、下流が上流(upsteram)からマージする必要があるまれなケースの1つです。

Patch workflow

あなたが変更を電子メールの形式でアップストリームに送信する貢献者の場合は、通常どおりトピックブランチを使用する必要があります(上記参照)。 次に、 git-format-patch(1) を使用して、対応する電子メールを生成します(メンテナの作業が楽になるため、手動でフォーマットするよりもこれを使うのを強く推奨します)。

Recipe: format-patch/am: Publishing branches/topics
  • git format-patch -M upstream..topic を使用して、事前に形式が決まっているパッチファイルに変換します

  • git send-email --to=<recipient> <patches>

使用上の注意については、 git-format-patch(1)git-send-email(1) のmanpageを参照してください。

あなたのパッチがもはや現在の上流(upstream)に適用されなくなったとメンテナが告げた場合は、トピックをリベースする必要があります(format-patch マージができないため、マージを使用できません):

Recipe: format-patch/am: Keeping topics up to date

git pull --rebase <URL> <branch>

あなたはその後、リベース中に競合を修正できます。おそらくあなたはメール以外であなたのトピックを公開していないので、それをリベースすることは問題ではありません。

あなたがこのようなパッチシリーズを受け取った場合(メンテナとして、または送信先のメーリングリストの読者として)、メールをファイルに保存し、新しいトピックブランチを作成し、 git am を使用してコミットをインポートします:

Recipe: format-patch/am: Importing patches

git am < patch

指摘する価値のある機能の1つは、競合が発生した場合に役立つ3方向マージです。 git am -3 は、パッチに含まれるインデックス情報を使用して、マージベースを把握します。他のオプションについては git-am(1) を参照してください。

SEE ALSO

GIT

Part of the git(1) suite