再フォーマットとバージョン管理


23

コードのフォーマットが重要です。インデントさえ重要です。そして、小さな改善よりも一貫性が重要です。ただし、プロジェクトには通常、1日目から明確で完全で検証可能強制的なスタイルガイドがなく、大きな改善がいつでも届きます。たぶんあなたはそれを見つける

SELECT id, name, address
FROM persons JOIN addresses ON persons.id = addresses.person_id;

/として書かれた方が良い

SELECT persons.id,
       persons.name,
       addresses.address
  FROM persons
  JOIN addresses ON persons.id = addresses.person_id;

クエリに列を追加する作業中。これは、コード内の4つのクエリすべての中で最も複雑なものか、数千ものクエリの中でささいなクエリかもしれません。移行がどれほど困難であっても、価値があると判断します。しかし、主要なフォーマットの変更全体でコードの変更をどのように追跡しますか?あきらめて「これが私たちが再び開始するポイントです」と言うか、リポジトリ履歴全体のすべてのクエリを再フォーマットすることができます。

Gitのような分散バージョン管理システムを使用している場合は、最初のコミットに戻り、そこから現在の状態に変更できます。しかし、それは多くの作業であり、作業中は他のすべての人が作業を一時停止する必要があります(または、すべてのマージの母親に備える必要があります)。すべての結果の中で最高のものを提供する履歴を変更するより良い方法はありますか?

  • すべてのコミットで同じスタイル
  • 最小限のマージ作業

明確にするために、これはプロジェクト開始時のベストプラクティスに関するものではなく、大規模なリファクタリングがGood Thing™と見なされたが、追跡可能な履歴が必要な場合に何をすべきかを示しています。バージョンが常に同じように動作することを保証する唯一の方法である場合、履歴を書き換えることは素晴らしいことではありませんが、クリーンな書き換えの開発者の利点はどうですか?特に、書き換えたバージョンが元のバージョンとまったく同じように機能することを保証する方法(テスト、構文定義、またはコンパイル後の同一のバイナリ)がある場合はどうでしょうか?


24
なぜ歴史を書き直したいのですか?バージョン管理の目的に反します。3か月前に出荷したアプリケーションが、わずかな疑いなく、リビジョンxxxxxxと一致することを確認する必要があります。些細な再フォーマットでさえも受け入れられません。
サイモンベルゴ

5
「リフォーマット。機能変更なし」というタグを付けてこれを行うコミットをコメントするのが好き
リグ

3
無関係なトピックについては、すべてのコードを再フォーマットすることでGitの履歴を書き直すことを提案していたようです。人々にアイデアを与えないでください。Git履歴を書き直すことは、99.9%のケースにとって悪いことです。再フォーマットは.1%のエッジケースではありません。
アンドリューTフィンネル

4
一部の言語(私はあなた、Pythonを見ています)では、再フォーマットによってコードの論理的な機能が変わる可能性があります。再フォーマットを安全に追跡および無視するには、VCSに保存されているすべての言語を解析できる必要があります。
ジョリスティマーマンズ

3
再フォーマットはコードの変更であり、そのままコミットする必要があります。
デビッドカウデン

回答:


26

個別のコミットとして再フォーマットを行います。これにより、履歴への影響が最小限に抑えられ、どのコミットが単なる再フォーマットであり、どのコミットが実際にコードを変更するかが一目でわかるはずです。それはゆがんgit blameで類似している可能性がありますが、それが再フォーマットのみのコミットを指している場合、その前に以前の変更を探すのはかなり簡単です。


開発者の1人がこれは良いアイデアだと考えたため、プロジェクトが数週間にわたって脱線しことがあります。これを行う場合は、リスクを事前に理解し、フォーマットをどこまで進めるかを正確に決定します。mjfgatesには正しい答えがあると思います。
ジョントロン

1
問題のチームにはコードのフォーマットよりも大きな問題があるように思えます。しかし、そう、あなたが必要なことをしない限り、これを行うことはお勧めしません。変更を再フォーマットしたい場合、機能的な変更と混合するよりも、別々のコミットとして行う方が良いと思います。
ハラルド

ええ、多くの問題:PIは、新しい開発者に、それが聞こえるほど単純ではないことを警告したいだけです。バルク再フォーマットツールはリスクが高く(特に、自分で正規表現を使用してビルドする場合-少なくともASTを使用する場合)、コードレビューとバグトラッキングが必要な場合は、プロセスが混乱する可能性があります。個人的には、各ファイルのスタイルに合わせてコードを記述していますが、いくつかの関数が再フォーマットされたときにコードをレビューすることは気にしません。多くの開発者はコードスタイルに
とらわれ

プログラミングでは、
見た目

13

VCSの履歴を書き換えないでください。VCSの原則に反します。

書式設定の修正を自動化しようとしないでください。実際の問題ではなく、症状を処理しています(=開発者がコーディング標準に従っていない)。

一般的なドキュメントでコーディング標準とフォーマットのベストプラクティスを定義し、すべての開発者に同意してもらいます。

あなたはGitに言及していますが、それは配布されているからです。DVCSを使用すると、ゲートキーパーワークフローを通じてベストプラクティスを簡単に実施できます。ゲートキーパー、共通のガイドラインに準拠していないマージ提案(= Gitのプルリクエスト)を拒否します。そして、太字で拒否することを意味します。そうしないと、違反しているコーダーはルールに従うことを気にせず、同じ間違いを繰り返し続けます。

このテクニックは私にとってはうまくいきます。コーダーは自分の作業をマージすることを望んでいるので、最初のいくつかのミスの後、ルールに従うようになります。

既存のコードベースを修正するごとに...おそらく、モジュールごとに、またはプロジェクトにとって意味があるように、徐々に行うことをお勧めします。各ステップで慎重にテストします。馬鹿げているように聞こえるかもしれませんが、書式設定などの些細な変更でも間違いが発生するため、道路での小さな衝突に備えてください。


1
これは、「... 1日目から明確で完全で検証可能で強制的なスタイルガイド」で始まっていないプロジェクトのコンテキストであると著者が明確に述べているためです。彼は本当の問題を扱うことができません。それはすでに起こっているからです。私もあなたに同意します:)
ジョントロン

2
リジェクトとは、人間とロボットの間に戦いがあること意味します。行ったことがある。遅かれ早かれ、ロボットは非常に複雑なコードを判読不能な方法でフォーマットする必要があります。例:Java文字列は実際にはSQLステートメントですが、ロボットはこれを知りません。括弧を閉じる前の空白には、人間のコードの構造に関する情報が含まれる場合がありますが、ロボットの情報は含まれません。関数パラメーターは複数の行に最も無意味な方法で分割されます
...-18446744073709551615

9

実際の質問に対する答えは、「あなたはしません」です。ある方法でフォーマットされたコードから、主要なフォーマット変更、およびコードが新しい方法でフォーマットされた後のさらなる変更まで、ロジックの変更をトレースできる現在のSCMツールはありません。そして、あなたはこれを知っています、コードの一部で履歴を失うことは良くありません。

したがって、私はあなたの最初の文に少し矛盾するつもりです。コードのフォーマットはそれほど重要はありません。かなりいいですが、それは私たちがここにいるものではありません。それの何かない限り、書式設定は、実際に何が起こっているのか理解するのに支障はない...私は理解だけでなく、2スペースのインデントと誰かの旧地獄のような奇妙なK&Rバリアントコードにダンプ取得することを誰もが(1)を吸うが、並外れ病理学的。その場合、とにかくコードを変更する際に問題が発生するので、気にする必要はありません。

したがって、確立されたコードを厳密に変更して再フォーマットすることは価値がありません。変数名を変更し、長い関数を分割し、コンテンツを変更するリファクタリングのすべてを実行します。はい、ただし再フォーマットするだけではありません。

1)-Windows Clipboard Viewerをしばらく所有していました。全部が1つ、150kのCモジュールでした。さまざまな人が30行以内に5つの異なるブレーススタイルを使用していた場所を見つけました。しかし、そのセクションはうまくいきました。私はそのコードの塊の印刷物を10年間持ち歩いたが、その歴史は重要であり、そのコードは少なくとも3つのソースツリー(Windows 3.x、NT、future 95)にあり、すべてが生きていたため、別の建物で。


過去に、を使用してhg、私はパーツごとのマージがトリッキーな大きなリファクターマージに対処する上で非常に貴重なツールであることを発見しました。通常、私がすることは、大きなリファクタリングの前にコミットをマージし、それから大きなリファクタリング自体をマージし、リファクタリング以降のコミットをマージします。これらの3つのマージはそれぞれ、すべてのマージを一度に実行することで生じる混乱を解決しようとするよりもはるかに簡単です。
マークブース

全くもって同じ意見です!さらに、多くの開発者がフォーマットの変更とコードスタイルの開発に乗り出し(自分自身の若いバージョンも含まれています)、最終的に欠陥を導入することになりました。ここにコンマ/セミコロンがありません。変数宣言は関数の先頭に移動し、forループはfor-eachに変更されました。これらはすべて微妙なバグを引き起こす可能性があります。これらの変更を安全に行うには、欺くほどのスキルが必要です。
ジョントロン

4

しかし、主要なフォーマットの変更全体でコードの変更をどのように追跡しますか?

書式の変更コードの変更です。コードに対する他の変更と同様に扱います。重要なプロジェクトに取り組んできた人なら誰でも、誰かがコードを「ただ」再フォーマットすることを決めたときに作成されたバグやその他の問題を目にすることでしょう。

しかし、それは多くの作業であり、他のすべての人は作業中に作業を一時停止する必要があります(または、すべてのマージの母親のために準備する必要があります)。

なぜすべてを一度にすべて再フォーマットする必要があるのですか?特に、再フォーマットを行ってもコードの意味が変わらない場合は、ファイルを個別に再フォーマットして、作業中にチェックインできるようにする必要があります。チームの全員にスタイルに同意してもらい(そうでない場合は再フォーマットする意味がありません)、他の作業の過程で全員に再フォーマットを行わせてください。しばらくすると、プロジェクトの残りの部分を中断することなく、ほとんどのコードをカバーできます。


1

これについては、実行可能な2つのアプローチがあります。

1.コミットフックでコードを再フォーマットする

最初にコードを送信した後にコードを変更するのは難しいですが、再フォーマット手順(astyleなど)がコードを傷つけない場合は、安全な操作です。時間の経過とともに、すべてのコードが最終的に同じに見えることをチーム全体が理解するでしょう。明らかに、包括的なユニット/自動化されたテストを行うことで、何も破られないことが保証されます。

2.すべてのコードの1回限りの再フォーマット

私の経験ではこれはより危険であり、ビッグバン全体の問題を追跡することは困難ですが、それは可能です。後ですべてのテストを実行することが不可欠です。コーディングスタイルの場合、ほとんどの違いは空白の使用を中心にしています-インデントまたは改行。まともなマージツールは、すべての空白の違いを無視するように指示できる必要があるため、これはマージに役立ちます。


1
大部分のコードベースでさざ波をオンにしたときにオプション1を選択すると、各ファイルが変更されるのと同じビッグバンになりますか?
サイン

@Sign:まさに私のポイント-コミットフックが変更されると、履歴がほとんど役に立たないものに劣化する可能性があります。機能を変更しないフォーマットはコミットではなく、コード履歴全体に移植する必要があります。
l0b0

1
IDEがサポートしている場合は、3)IDEが保存時に自動フォーマットされることもあります。次に、どこでも同じ設定を使用します-これは、IDEでデフォルトを使用する場合に最も簡単です。

これらのアプローチの両方を実行しました。最初のアプローチは、新しいファイルが初めてコミットされるたびに大量の変更があるため、非常に目障りです。2番目のアプローチは、絆創膏をすばやく取り去るなど、チームにとってより良い方法です。
ドルスカ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.