web-dev-qa-db-ja.com

単一のコミットはどのくらいの大きさにすべきですか?

仕事で議論が出てきたので、他のプログラマの意見を聞きたい。

大学時代は、ソース管理にSVNのみを使用していました。全員が同じサーバーにコミットし、すべての変更がすべてのマシンにプルされます。このシステムでは、変更をプッシュする必要があるとき、つまり変更が完了したときは簡単です。ただし、これにより、複数の開発者による変更セットのマージは完全な悪夢になります。

ただし、ここ1年ほど、私が専門的にプログラミングしてきたため、ソース管理にMercurialを使用しています。最初、私はSVNのようにそれを使用していました:featur、commit、Pushを一度に実行しましたが、それが終了したときのみです。

徐々に、私の習慣は変わり始めました。私はブランチ、コミットがドラフト、パブリック、シークレットになる方法について学び、USBスティックを中央リポジトリとして使用しました。私のコミットは小さくなりましたが、量は増えました。一度にコミットしてプッシュするのではなく、名前付きブランチのすべての変更をコミットします。

私の個人プロジェクトのリポジトリは次のようになります。

Repository layout

このアプローチにはいくつかの利点があります。

  • 小さなコミットは、それらが単一の主題に焦点を当てていることを意味します。すべてのコミットは、変更についての1行の説明を取得するため、何週間も非アクティブになった後でも簡単に追跡できます。

  • 名前付きブランチは、トピックにあなたを保ちます。たとえば、「refactor-text-rendering」ブランチで作業している場合は、数学ライブラリを変更しないでください。これは、ブランチのトピックとは関係がないためです。

しかし、主な開発者は私の方法論に悩まされています。彼は、小さなコミットがリポジトリの履歴を乱雑にすると感じています。彼の好ましい方法論は、パッチで動作することです。機能が完了すると、彼はコミットをマージし、一度にプッシュします。

それで、あなたは何を好みますか?コミットの意識の歴史の流れ、または時々の変更のパッチ?それとも完全に別のものですか?

23
knight666

参考文献を探しに行きましたが、残念ながら見つかりませんでした。

一般的に、小さなコミットはベストプラクティスであると広く考えられていると思います。より正確には、ビルド可能な状態にあるまとまりのある機能を表す最小のコミット。

どうして?

  1. 小さく、頻繁にチェックインすることで、ハードウェア障害、地震、ゾンビの大惨事が発生した場合に作業が失われるのを防ぎます。
  2. ピアは、最後まで待機して1つの大きなコミットを行うよりも早く変更を取得できます。
  3. 機能をロールバックする必要がある場合は、チェンジセットの「半分」ではなく1つのチェンジセットをロールバックできます。
  4. チェックインが小さいほど、変更領域が少なくなるため、他の人の作業と競合する可能性が低くなります。
18
Telastyn

この分野にはかなりの意見があると私はほぼ確信していますが、私はいくつかのルールに従う傾向があり、それからコミットのサイズを決定する傾向があり、これについていくつかの考えがあります:

  1. 単一のコミットは「ロールバック可能」である必要があります。コミットがロールアウトされた場合、機能はシステムの動作能力に影響しますか?コミットはまとまりのある単位である必要があり、それらのまとまりのある単位は機能に(可能な限り)適切に「マッピング」する必要があります。
  2. チームから「醜さ」を守るために可能な限りプライベートにブランチします。最終的には、コミットの大小を問わず、機能Bでの作業に影響を与えてはなりません。

あなたがこれらの経験則の両方に従うならば、あなたのコミットは必ずしも「比較的」または「比較的」ではないかもしれません。確かに小さなコミットはいいですし、時には推論するのも簡単ですが、それらがすべて強く結合されていると、対処が少し難しくなるかもしれません。それが最小のまとまりのある機能グループになっている限り、私は(理由の範囲内で)「大きな」コミットで大丈夫です。

5
Jack

個人プロジェクトの例として、コミット履歴を取り上げます。 1日間で13のコミットメッセージがあります(つまり、「2日前」)。次に、50〜200人以上の開発者が同じ方法でプロジェクトに取り組んだ場合、同じ期間にその履歴がどのようになるかを想像してください。それは1日あたり650〜2600のコミットメッセージです。 1週間のコミット履歴は人間にとって扱いにくいものです。

したがって、それはチームの規模によって異なります。小規模なチームでは、詳細な情報として役立ちます。チームが大きくなると、それはすぐに混乱のノイズに爆発し、履歴は機能的に役に立たなくなります。

5
Steven Evers
  • それを修正する別のものをすぐに作成するつもりでも、意図的にリポジトリを壊れた状態にするコミットを行わないでください。

  • 大きなコミットよりも小さなコミットを優先する。リポジトリを細かく切り刻んで問題の原因を突き止める場合、手順が小さいと問題の原因を突き止めるのが簡単になります。小さなコミットで変更をすばやく理解する方が簡単です。

  • 単一の機能、修正、またはその他の論理的な作業単位に対して単一のコミットを優先します。さらなるコミットなしでは機能しない変更を導入する「部分的な」コミットを避け、いくつかの無関係な変更を含む複合的なコミットを避けます。機能を変更しないスタイルの変更を行う場合は、個別にコミットします。これらすべてにより、ビルドが壊れないままになる可能性が高まり、コードベースの問題を選択していない別の人が、行われた機能的な変更のシーケンスを理解し、個々の変更をすばやく把握することがはるかに容易になります。

  • 非常に複雑な機能に取り組んでいる場合や、部分的に書き込んでもコミットしても安全または有用にならないリファクタリングの場合は、プライベートブランチで作業し、頻繁にコミットし、トランクを最新の状態に保つようにしてください。最終的にトランクにマージするときは、将来のメンテナがプライベートブランチの歴史にたどり着く方法を残せるようにしてください。

つまり、要約すると、単一の論理作業単位を完了するために必要かつ十分である、可能な限り最小のコミットを行うことを常に目指します。

5
moonshadow

Mercurialを使用する場合、私はあなたのアプローチを好みます。 GitやMercurialなどの最新のソース管理システムは、高速コミットにより頻繁にコミットできるという考えに基づいて構築されています。大量の変更を保存して一度にコミットするべきではありません。

Gitでは、「スカッシュ」機能を使用して、複数のコミットを1つのコミットに圧縮できますが、これはMercurialのデフォルトでは提供されていません。コミット履歴の変更はMercurialの理念に反するものであり、歴史は不変である必要があると述べています。ただし、Gitのつぶし機能を試して再現したい場合-リード開発者の気の利いた振る舞いを守りながらツールを適切に使用し続けることができるように-この質問は役立つかもしれません:

https://stackoverflow.com/questions/1725607/can-i-squash-commits-in-Mercurial

3
Ant

どちらの方法にも有効な引数があります。一方で、ソース管理はバックアップメカニズムではありません。本番環境にコミットするまで作業が安全であることを確認するには、シェルビング、ローカルリポジトリ、または古いバックアップを使用する必要があります。一方、一連の変更が完全で個別のバグ修正、機能などを表す場合は、準備ができたらコミットするのが妥当と思われます。将来的には、より小さく、より「モジュール化された」コミットをレビューする方が、何百ものファイルが変更されたリビジョンをたどるよりも簡単になるかもしれません。

また、ソース管理ログの純粋さを維持しようとすることは、長期的には負けたゲームのようであり、ソフトウェア自体ではなく、開発プロセスの成果物を管理することに焦点を当てています。

2
Dan1701