2016-12-27 13 views
1

理解しようとすると、それがない操作がはるかにマージよりリベースのようなあるようですので、なぜコマンドgitがマージされていません--squashは本当にgit rebase -squashですか?

git merge --squash mybranch 

git rebase -squash mybranch 

と呼ばれていません。私の理解は、それが現在のブランチとmybranchの共通ベースコミットを見つけるまで、コミットツリー内を検索し戻すことです。次に、その基本ノードからmybranchの先頭までのすべてのコミットを現在のブランチの先頭に再適用(再分配)します。しかし、これをインデックス/ワークスペースに入れて、単一のコミットとして適用することができます。完了すると、マージされた2つのブランチを示す通常のマージがあるので、マージノードはありません。私は正しい理解を持っていますか?

+0

'merge --squash'はブランチからのすべてのコミットを1つに縮めます。履歴を変更することはありません。 –

+0

Andyが言っていることは、併合が起こる前に潰れが起こることです。そのため、ターゲットブランチの観点から見ると、まだマージが見えます。 –

+0

私のポイントは通常のマージの後であった。グラフはマージされた2つのブランチを1つのマージノードに結合するが、マージ後に--squash&commitは2つのブランチがまだ分かれていることを示すが、現在のブランチに移動します。私には、一回のコミットに押しつぶされたrebaseのように見えます。しかし、私が求めていた本当の疑問は、私のコンセプト - スカッシュの概念が根本的に正しいのか、そして@torekによる拡張された答えから、まだ学ぶことがより複雑な詳細があると結論づけていたということでした。 – JonN

答えて

2

よく、マージとリベースは基本的に異なる操作です。マージ-でいる私は、新しいマージコミット-ん確かに共通する直近のコミットのコミットグラフを通じてバック検索作成し、通常のgit mergeを意味する:

...--o--*--o--o--A <-- mainbr 
     \ 
      B--C--D--E <-- sidebr 

をここでは、一般的な最新のコミットは*です。その後、マージプロセスは、とコミットAをコミットして「私たちが行ったこと」を調べ、Eに対してdiff *を比較して、「彼らが何をしたか」を見つけ出します(git diffのように)。 M*の差分のこと「の一つ与えるよう、2つの履歴を結合し、「彼らが何をしたか」「私たちが何をしたか」と組み合わせた

...--o--*--o--o--A---M <-- mainbr 
     \  /
      B--C--D--E <-- sidebr 

:それは、新しい単一のマージは、2人の両親と、コミットますそれぞれの変化 "。

ここでマージベースを選択することはできません.Gitはそれを把握しており、それだけです。

Rebaseは、コピーするコミットとコピーする場所を別々に指定することができます。デフォルトでは、コミットは*です。もう一度ですが、コピーをコピーします。元のコミットは、git cherry-pickまたは同等のものを使用してコミットされます。最後に、ブランチを最後にコピーされたコミットを指すように移動します。

...--o--*--o--o--A <-- mainbr 
     \  \ 
      \  B'-C'-D'-E' <-- sidebr 
      \ 
      B--C--D--E 

(この場合B-C-D-E)コミットの元の鎖がリポジトリにまだある、まだ検索可能:彼らは、ハッシュIDにより求めることができる、とsidebrためREFLOGで、及び他の任意場合ブランチまたはタグ名を使用すると、その名前で到達可能なままになります。何git merge --squash

はわずかにマージ処理を変更することです:代わりにMをコミットマージすることで、Gitはマージベース - あなたが選ぶ、反対し得ることはありませんが差分のマージを通じていつものように機械を行きます現在のコミットと他のコミット、およびインデックスと作業ツリーの変更を組み合わせることができます。

:グラフ全体-フラグメントは次のようになりますように、それは当時のための明白な理由 -stops、あなたは結果をコミットする git commitを実行し、そしてあなたが行うときになり、それは、通常、非マージコミットです今
...--o--*--o--o--A--F <-- mainbr 
     \ 
      B--C--D--E <-- sidebr 

内容コミットF私たちは本当のマージを行うときMをコミットの内容と同じでマージされ、そして、ここで本当のキッカー、それはだもだから生ずる-the スナップショットツリー rebaseを実行したときのコミットE'の内容と同じです。

さらに、サイドブランチsidebrに1つのコミット(B)があったとします。これで、すべてmergeの3、merge --squash、およびrebaseはあなたに私達はちょうどこのように描くかもしれない何かで終わる絵与える:

...--o--*--o--o--A--B' <-- ??? 
     \   ? 
      B????????? <-- ??? 

内容新しいコミットB'、すなわちのを、最後のスナップショットは、あります3つすべての場合において同じである。しかし、git mergeの場合、新しいコミットはブランチmainbrにあり、コミットABを指し、sidebrBを指します。 git merge --squashの場合、新しいコミットはmainbrになり、Aに戻るだけです。そしてgit rebaseのために、新しいコミットはまったくBに何も明らかにポインティングと、sidebrになり、私たちは、このように描く必要があります。

...--o--*--o--o--A <-- mainbr 
     \  \ 
      B  B' <-- sidebr 

mainbr以来Aのコミットを指すように続けます。最後に

が、これはもう少しそれがリベースのようなよりも、マージのように見えます。 (それがすべてで、「スカッシュマージ」と呼ばれていなかった場合は、私は幸せになります。)


Gitが*を発見する方法は多少異なっている:それは実際には単一のコミットはありません、むしろ最後の大量のコミット、つまり<upstream>の引数からgit rebaseに到達可能なすべてのコミットのうちの最後のものです。 (紛らわしいこと、マージベースはまた、コミットのセットすることができますが、それははるかに制限されたセットです。ベストはまだ、グラフ理論に飛び込むしない。:-))

我々はを望んでいた場合、それ停止するには、--no-commitを通常のノンスカッシュgit mergeと同じように使用できます。だからなぜを自動的に停止するのですか?

関連する問題