This is due to the fact that Git does not know that merging squash is equivalent to "different specific branches". You must force remove the branch with git branch -D
instead of git branch -D
.
(The rest is just why this is).
Draw a commit graph
Let draw (part) a commit graph (this step is suitable for many things in Git ...). Actually, let go one more step so that we start with your git rebase
, with something like this:
...
A branch name, such as mainline
or feature1
, points to only one specific commit. This commit points back (to the left) to the previous commit, etc., and these are the back pointers that form the actual branches.
The top line of commits, just called o
here, is a little boring, so we did not give them letter names. The bottom line of commits, ABC
, is only on the feature1
branch. C
is the newest such fixation; it goes back to B
, which goes back to A
, which leads to one of the boring o
commits. (Aside: the leftmost o
commit, along with all earlier commits in the ...
section, is in both branches.)
When you started git rebase
, the three ABC
commands were copied to the new commits added to the mainline
tip, giving us:
...
The new A'-B'-C'
commands are basically the same as the original three, but they move on the chart. (Note that all three o
drills are on both branches now.) Failure to use the original three means that Git usually does not need to compare copies to the originals. (If the originals were available to a different name - a branch added to the old feature1
, for example, Git, can understand this, at least in most cases. The exact details of how Git shows it is not important here.)
Anyway, now you run git checkout mainline; git merge --squash feature1
git checkout mainline; git merge --squash feature1
. This makes one new commit, which is a squash copy of the three or even many commits that are on feature1
. I will stop drawing old abandoned ones and will call a new squash-commit S
for Squash:
...
"Delete security" is completely determined by the commit history
When you ask Git to remove feature1
, it performs a security check: " feature1
merged into mainline
?" This "merges into" test is based solely on graph connectivity. The name mainline
indicates a commit S
; commit S
points to the first boring o
commit, which returns to a more boring o
commit. Commit C'
, the tip of feature1
not available from S
: we are not allowed to move to the right, only to the left.
Compare this to creating a โnormalโ merge M
:
...
Using the same test: "is feature1
tip feature1
achievable from mainline
tip fixation?" - the answer is now yes, because commit M
has a link down and left to commit C'
. (Commit C'
is in Git's internal expression, the second parent of the merge commit is M
)
Since squash mergers do not actually merge, but there is no connection from S
back to C'
.
Again, Git doesn't even try to see if S
is the same as A'
, B'
or C'
However, if that were the case, then it would say "not the same thing" because S
matches the sum of all three commits. The only way to get S
to match crushed commits is to have only one such commit (and in this case there is no need to crush first).