mainline
(master
と同等)といくつかのローカル機能ブランチを含むgitリポジトリがあります。例えば:
$ git branch
* mainline
feature1
feature2
feature3
次のようにすると、機能ブランチのすべての編集をmainline
への1つのコミットにスカッシュマージできます。
$ git checkout mainline
$ git pull
$ git checkout feature1
$ git rebase mainline
$ git checkout mainline
$ git merge --squash feature1
$ git commit
$ git Push
私の質問は、現時点でfeature1
ブランチを削除しようとすると、完全にマージされていないことを示しています。
$ git branch -d feature1
error: The branch 'feature1' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature1'.
このエラーの原因は何ですか? git merge --squash feature1
はfeature1
をmainline
に統合したと思いました。
これは、スカッシュマージがブランチ固有のさまざまなコミットと「同等」であることをGitが認識していないために発生します。 git branch -D
ではなくgit branch -d
を使用して、ブランチを強制的に削除する必要があります。
(これの残りは単に約なぜこれが事実です。)
コミットグラフ(の一部)を描きましょう(このステップはGitの多くのことに適しています...)実際、もう1つステップを戻して、git rebase
の前に次のようなコードを追加します。
...--o--o--o <-- mainline
\
A--B--C <-- feature1
ブランチnameは、mainline
やfeature1
のように、1つの特定のコミットのみを指します。そのコミットは前のコミットを指すように(左方向に)戻ります。実際のブランチを形成するのはこれらの後方ポインターです。
上の行のコミットはすべてo
と呼ばれていますが、これはちょっと退屈なので、文字名は付けていません。コミットの一番下の行A-B-C
は、ブランチfeature1
ではonlyです。 C
はそのような最新のコミットです。 B
に戻り、A
は退屈なo
コミットの1つに戻ります。 (余談ですが、左端のo
コミットは、...
セクション内の以前のすべてのコミットとともに、両方ブランチにあります。)
git rebase
を実行すると、3つのA-B-C
コミットがコピーからnewコミットにmainline
の先端に追加され、 :
...--o--o--o <-- mainline
\ \
\ A'-B'-C' <-- feature1
\
A--B--C [old feature1, now abandoned]
新しいA'-B'-C'
コミットは元の3つとほとんど同じですが、グラフでは移動です。 (現在、3つの退屈なo
コミットは両方のブランチにあることに注意してください。)元の3つを放棄すると、通常、Gitはコピーをオリジナルと比較しませんhave。 (オリジナルが他の名前(たとえば、古いfeature1
に追加されたブランチ)で到達可能であった場合、Git can少なくともほとんどの場合、これを理解します。正確な詳細Gitがこれをどのように計算するかについては、ここでは特に重要ではありません。)
とにかく、今度はgit checkout mainline; git merge --squash feature1
を実行します。これにより、feature1
上にある3つのコミットの「スカッシュコピー」である1つの新しいコミット、または多くのコミットが作成されます。私は古い捨てられたものを描くのをやめて、スカッシュのために新しいスカッシュコミットS
を呼び出します:
...--o--o--o--S <-- mainline
\
A'-B'-C' <-- feature1
Gitにfeature1
の削除を依頼すると、安全性チェックが実行されます:「feature1
はmainline
にマージされますか?」この「マージされる」テストは、純粋にグラフ接続に基づいています。名前mainline
はコミットを示しますS
; commit S
は、最初の退屈なo
コミットを指します。これにより、より退屈なo
コミットに戻ります。 C'
の先端であるfeature1
のコミットはnotS
から到達可能です:右方向への移動は許可されていません。左方向への移動のみが許可されています。
これを "通常の"マージM
と比較してください。
...--o--o--o---------M <-- mainline
\ /
A'-B'-C' <-- feature1
同じテストを使用して、「mainline
のティップコミットからfeature1
のティップコミットに到達可能ですか?」—コミットM
には、C'
をコミットするための左下のリンクがあります。 (コミットC'
は、Gitの内部用語では、マージコミットM
の-2番目の親です。)
スカッシュマージは実際にはmergesではないため、S
からC'
への接続はありません。
繰り返しますが、GitはS
がA'
、B'
、またはC'
と「同じ」かどうかを確認するtryさえしません。ただし、そうした場合、S
は3つのコミットすべてのsumと同じであるため、「同じではない」と表示されます。 S
を押しつぶしたコミットに一致させる唯一の方法は、そのようなコミットを1つだけにすることです(この場合、最初に押しつぶす必要はありません)。