Search code examples
gitatlassian-sourcetreegit-interactive-rebase

git interactive rebase squash creates whole new branch


Here's a picture of the last part of my simple straightforward history (from SourceTree, time marches from bottom to top):

enter image description here

So, in this situation, I asked SourceTree to do an interactive rebase on the children of the bottommost commit ("Xcode 10.2, Swift 5"), because I wanted to collapse the next two commits ("darn, property list encoding" and "v1.1.1build24") into a single commit. There is no remote so I'm free to rewrite history and keep it clean and informative.

But when I did that, a whole bunch of new commits were created branching off from "Xcode 10.2, Swift 5" - copies of the existing chain of commits. I couldn't understand why, and it took me a lot of scurrying around to clean it up.

It wasn't exactly a new "branch" (as my question title has it); but the existing commits up thru "v1.1.2build28" ended up on their own dead-end branch line, and master now had these new commits in it, duplicating those commits but without the tags and with today's date.

My question is: why did that happen, and what should I have done instead?


Solution

  • It's done as expected.

    "darn, property list encoding" and "v1.1.1build24" are squashed as one commit. Git implements this squash by creating a new commit, whose parent is "Xcode 10.2, Swift 5" and whose changes are equivalent to those of "darn, property list encoding" and "v1.1.1build24".

    The parent or the base of "v1.1.1build25" was "v1.1.1build24". Now a new commit has replaced "v1.1.1build24" and "darn, property list encoding". As a result, the parent of "v1.1.1build25" needs to be the new commit. Otherwise, the commits above "v1.1.1build24" will no longer exist on master. In order to move "v1.1.1build25" from the old base to the new base, Git also generates a new commit for "v1.1.1build25", whose parent now is the squashed commit and whose changes are equivalent to those of "v1.1.1build25". Accordingly, all the rest descendants are recreated because their parents/bases are changed.

    Git creates new commits as if the old ones are replaced, but the old ones still exist in the repository except that they are no longer reachable from master. However the tags like "v1.1.1build25" and the branches like "temp" still point to the old commits. Since these old commits are not on the current master now, these tags and branches are not seen on master either.