web-dev-qa-db-ja.com

プルリクエストのgitコミットをスカッシュするのはなぜですか?

私がプルリクエストを行うすべての深刻なGithubリポジトリで、コミットを1つのコミットに押しつぶしたいのはなぜですか?

私はgitログがそこにあると思ったので、すべての履歴を調べて、どこで何が変更されたかを正確に確認できますが、それを潰すと、履歴から引き出され、すべてが1つのコミットにまとめられます。ポイントは?

これはまた、「早期にコミットし、頻繁にコミットする」というマントラに反するようです。

221
hamstar

そのため、行われた変更とその理由を明確かつ簡単に文書化する、明確で簡潔なgit履歴があります。

たとえば、私にとっての典型的な「つぶされていない」gitログは次のようになります。

7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
787g8fgf78... hotfix for #5849564648
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

なんてめちゃくちゃ!

これに対して、メッセージにもう少し焦点を当てた、より慎重に管理およびマージされたgitログは次のようになります。

7hgf8978g9... 8483948393 Added new slideshow feature
787g8fgf78... 5849564648 Hotfix for Android display issue
9080gf6567... 6589685988 Implemented pop-up to select language

私はあなたがコミットを潰すポイントを一般的に見ることができると思います、そして同じ原理がプルリクエストに適用されます-履歴の読みやすさ。また、すでに数百または数千のコミットがあるコミットログ。これにより、成長する履歴を短く簡潔にすることができます。

早く、頻繁にコミットしたい。これは多くの理由でベストプラクティスです。これにより、「wip」(進行中の作業)または「パートAが完了」または「タイプミス、マイナーフィックス」であるコミットが頻繁に発生し、gitを使用して作業を支援し、次のコードがうまくいかなくても問題なく動作するようになったら、戻ることができます。ただし、コミットを押しつぶすことができるように、最終的なgit履歴の一部としてその履歴を必要としないか、必要としません。ただし、これが開発ブランチとマスターで何を意味するかについては、以下のメモを参照してください。

明確な作業段階を表す主要なマイルストーンがある場合でも、機能/タスク/バグごとに複数のコミットがあっても問題ありません。ただし、これにより、開発中のチケットが「大きすぎる」ため、スタンドアロンにできる小さなピースに分解する必要があるという事実がしばしば強調されます。たとえば、次のようになります。

8754390gf87... Implement feature switches

「1枚の作品」のようです。それらが存在するか、存在しないかのどちらかです。それを壊すのは意味がないようです。ただし、経験から、(組織の規模と複雑さに応じて)より詳細なパスは次のようになる可能性があることがわかりました。

fgfd7897899... Add field to database, add indexes and a trigger for the dw group
9458947548g... Add 'backend' code in controller for when id is passed in url.
6256ac24426... Add 'backend' code to make field available for views.
402c476edf6... Add feature to UI

小さなピースは、より簡単なコードレビュー、より簡単なユニットテスト、QAへのより良い機会、単一責任の原則へのより良い調整などを意味します.

実際にそのようなスカッシュを行うタイミングの実用性のために、基本的に独自のワークフローを持つ2つの異なるステージがあります

  • あなたの開発、例えばプルリクエスト
  • mainlineブランチに追加された作業(例:主人

開発中は、「早期かつ頻繁に」、迅速な「使い捨て」メッセージをコミットします。あなたは時々ここでスカッシュしたいと思うかもしれません、例えば。 wipとtodoのメッセージコミットで押しつぶされます。ブランチ内で、開発で行った個別のステップを表す複数のコミットを保持しても問題ありません。スカッシュのほとんどは、開発中にマスターにマージする前に、これらの機能ブランチ内にあるはずです。
メインラインブランチに追加する場合、コミットを簡潔にして、既存のメインライン履歴に従って正しくフォーマットする必要があります。これには、チケットトラッカーシステムIDが含まれる場合があります。例に示すJIRA。マスターでいくつかの異なるコミットを「ロールアップ」したくない限り、ここではスカッシュは適用されません。通常はそうではありません。

マスターにマージするときに--no-ffを使用すると、マージに1つのコミットが使用され、履歴が(ブランチに)保存されます。これをベストプラクティスと見なしている組織もあります。詳しくは https://stackoverflow.com/q/9069061/631619 をご覧ください。実際の効果はgit logでも確認できます。ここで--no-ffコミットは最新のコミットです。 HEAD(完了時))の上部にありますが、--no-ffがない場合は、日付やその他のコミットによっては、履歴のさらに下にある可能性があります。

168
Michael Durrant

多くの場合、PRを引っ張る人は、「ベーステンプレート、バグ修正関数X、関数Yを追加、コメントのタイプミスを修正、データスケーリングパラメーターを調整して」ではなく、「追加機能X」のコミットの正味の影響に注意を払うため、ハッシュマップはリスト "...詳細レベル

16個のコミットが1個の「追加機能X、Xを使用するようにリファクタリングされたZ」ではなく2個のコミットで最もよく表されていると思われる場合、2個のコミットでprを提案することはおそらく問題ありませんが、提案するのが最善の場合があります。その場合、2つの別個のpr(リポジトリがまだ単一のコミットprを要求している場合)

これは、リポジトリの場合のように、「早期にコミットして頻繁にコミットする」というマントラに反するものではありません。開発中は細かい詳細が残っているため、作業が失われる可能性は最小限であり、他の人がレビュー/プル/提案できます新しいprが開発されている間、prはあなたの仕事に反対します。

27
Andrew Hill

追加された機能と修正されたバグの履歴を明確かつ簡潔に示すことについて、このスレッドの他の回答で表明された意見に同意します。しかし、私はあなたの質問が回避したが明示的に述べていない別の側面に取り組みたいと思いました。 gitの動作方法のいくつかについてあるハングアップの一部は、そのようなアクションが不可能な他の形式のソース管理を使用した後にgitに導入されたときに奇妙に見える履歴をgitで書き換えることができることです。さらに、これは、ソース管理の一般に受け入れられている原則に反します。ソース管理に何かがコミット/チェックインされると、そのコミット後に行った変更に関係なく、その状態に戻ることができるはずです。あなたの質問で暗示するように、これはそれらの状況の1つです。 gitは優れたバージョン管理システムだと思います。ただし、それを理解するには、実装の詳細とその背後にある設計上の決定のいくつかを理解する必要があり、その結果、学習曲線が急になります。 gitは分散バージョン管理システムであることが意図されていたので、デザイナーがgit履歴をこの例の1つであるスカッシュコミットで書き直すことができる理由を説明するのに役立ちます。

2
Fred Thomsen

コードが公開されるかどうかを確認します。

プロジェクトが非公開のままの場合:

押しつぶさずにソーセージの作り方を見ることをお勧めします。優れた小さなコミットを使用する場合、git bisectなどのツールは非常に便利であり、人々は回帰コミットをすばやく特定して、なぜそれを行ったのかを確認できます(コミットメッセージのため)。

プロジェクトが公開されるとき:

一部のコミットにはセキュリティリークが含まれる可能性があるため、すべてを潰します。たとえば、コミットされて再度削除されたパスワード。

1
Vince V.

パースペクティブがあるため...ベストプラクティスは、1つのコミットを1つにすることです<<issue-management-system>>可能であれば発行してください。

自分の機能ブランチ/リポジトリで必要なだけコミットを行うことができますが、これはあなたが現在実行していることに関連する履歴です。あなたの観点から言えば...チーム全体、プロジェクト、またはアプリケーションからの履歴ではありません。数か月後の展望...

ですから、バグ修正や機能を一般的なリポジトリ(この例は、developブランチにあります)にコミットしたいときはいつでも、次のように実行できます。

機能ブランチをリベースして迅速に開発する方法

    # set your current branch , make a backup of it , caveat minute precision
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # squash all your changes at once 
    git reset $(git merge-base develop $curr_branch)

    # check the modified files to add 
    git status

    # add the modified files dir by dir, or file by file or all as shown
    git add --all 

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # add the single message of your commit for the stuff you did 
    git commit -m "<<MY-ISSUE-ID>>: add my very important feature"

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # make a backup once again , use seconds precision if you were too fast ... 
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # compare the old backup with the new backup , should not have any differences 
    git diff <<old-backup>>..<<new-backup-branch>>


    # you would have to git Push force to your feature branch 
    git Push --force 
1
Yordan Georgiev