gitでは、merge --squashとrebaseの違いは何ですか?


363

私はgitが初めてで、スカッシュとリベースの違いを理解しようとしています。私が理解しているように、リベースを行うときにスカッシュを実行します。

回答:


360

どちらgit merge --squashgit rebase --interactive「押しつぶさ」コミット生成することができます。
ただし、目的は異なります。

マージ関係をマークせずに、宛先ブランチで押し潰されたコミットを生成します。
(注:すぐにコミットが生成されるわけではありません。追加が必要 ですgit commit -m "squash branch"
これは、ソースブランチを完全に破棄する場合に便利です(SO質問から取得したスキーマ):

 git checkout stable

      X                   stable
     /                   
a---b---c---d---e---f---g tmp

に:

git merge --squash tmp
git commit -m "squash tmp"

      X-------------------G stable
     /                   
a---b---c---d---e---f---g tmp

そしてtmpブランチを削除します。


注:git mergeには--commitオプションがありますが、では使用できません--squash。なかった決して使用することも可能--commit--squash一緒に。
Git 2.22.1(2019年第3四半期)以降、この非互換性は明示的になります。

Vishal Verma()によるcommit 1d14d0c(2019年5月24日)を参照してください。(合併によりJunio C浜野- -33f2790コミットし、2019年7月25日)をreloadbrain
gitster

merge:ゴミ--commit付き--squash

以前は、--squashが提供されたときに ' option_commit'が通知なしで削除されました。これは、スカッシュのコミットなしの動作を--commit明示的にオーバーライドしようとしたユーザーにとっては驚くべきことでした。

git/git builtin/merge.c#cmd_merge() 今含まれています:

if (option_commit > 0)
    die(_("You cannot combine --squash with --commit."));

コミットの一部またはすべてを新しいベースで再生し、スカッシュ(または最近「修正」、このSO質問を参照)できるようにします。

git checkout tmp
git rebase -i stable

      stable
      X-------------------G tmp
     /                     
a---b

すべてのコミットをスカッシュすることを選択した場合tmp(ただし、とは逆にmerge --squash、一部をリプレイし、他のものをスカッシュすることを選択できます)。

したがって、違いは次のとおりです。

  • squashソースブランチ(tmpここ)には触れず、必要な場所に単一のコミットを作成します。
  • rebase同じソースブランチ進むことができます(まだtmp):
    • 新しい拠点
    • よりきれいな歴史

11
Gされてc--d--e--f--g一緒に押しつぶさ?
ウェインコンラッド

8
@ウェイン:はい、これらの例のGは、tmpまとめて押しつぶされたコミットを表します。
VonC 2010年

3
@ Th4wn:すべてのプロジェクトのスナップショットを使用するGitの理由により、によって導入された変更のためG、と同じコンテンツを表すことはありません。gX
VonC、2011年

1
@VonC:その最後のコメントについてはわからない。のgit merge --no-ff temp代わりにを使用している場合はgit merge --squash temp、厄介な履歴が表示されますが、などの操作もgit revert eはるかに簡単に行えます。散らかっていますが、正直で実用的な歴史であり、メインブランチはまだかなりクリーンなままです。
naught101

2
@ naught101同意する。ただし、stackoverflow.com / a / 7425751/6309で説明されているように、壊れないことgit bisectgit blame、頻繁に使用されない場合も同様です(例git pull --no-ffstackoverflow.com/questions/12798767/…)。一つのアプローチは、この記事では、3(説明理由である、とにかくありませんstackoverflow.com/questions/9107861/...を
VonC

183

コミットのマージ:すべてのコミットをブランチに保持し、ベースブランチのコミットでインターリーブしますここに画像の説明を入力してください

Merge Squash:変更を保持しますが、履歴から個々のコミットを省略します ここに画像の説明を入力してください

リベース:これにより、機能ブランチ全体がマスターブランチの先端から始まるように移動し、すべての新しいコミットがマスターに効果的に組み込まれます

ここに画像の説明を入力してください

詳細はこちら


81

Merge squashは、ツリー(一連のコミット)を1つのコミットにマージします。それはそれは、あるカボチャで行われたすべての変更n個のシングルにコミットコミットを。

リベースとは、ツリーの新しいベース(親コミット)を選択することです。多分これの水銀の用語はより明確です:彼らはそれを移植と呼んでいます:それはそれだけです:ツリーのために新しい地面(親コミット、ルート)を選ぶことです。

インタラクティブなリベースを行う場合、リベースするコミットをスカッシュ、選択、編集、またはスキップするオプションが提供されます。

それが明確だったことを願っています!


7
いつリベースし、いつスカッシュする必要がありますか?
Martin Thoma、2016年

31

次の例から始めましょう。

ここに画像の説明を入力してください

これで、機能ブランチの変更をマスターブランチにマージする3つのオプションがあります。

  1. コミットをマージする
    と、機能ブランチのすべてのコミット履歴が保持され、マスターブランチに移動され
    ます。ダミーのコミットが追加されます。

  2. リベースおよびマージ
    は、機能ブランチのすべてのコミット履歴をマスターブランチの前に
    追加します。ダミーのコミットは追加されません。


  3. Willをスカッシュしてマージすると、すべての機能ブランチのコミットが1つのコミットにグループ化され、マスターブランチの前に追加されて、
    ダミーのコミットが追加されます。

以下に、masterブランチがそれぞれの後にどのように表示されるかを示します。

ここに画像の説明を入力してください

すべての場合:機能ブランチを
安全に削除できます。


1
2枚目のダミーコミットとは何ですか?私はgitの初心者です。
ユスフ

1
@Yusuf、それは両方のブランチの更新を含む単なる追加のコミットです、それはデフォルトのコミットメッセージです=「マスターへの
メガ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.