7

Steps taken

I merged a feature branch back into master and deleted the feature branch. But it still shows up in the tree.

Result

Tree visualisation in SourceTree before deleting the feature branch: Tree before deleting the feature branch

Tree visualisation in SourceTree after deleting the feature branch: Tree after deleting the feature branch

The feature branch in the left-hand list is gone, as expected, and the label in the tree visualisation is gone as well, again as expected.

Questions

But:

  1. Why is the violet part still shown?
  2. Which Git commands would I have needed to execute to not see the violet part anymore? I probably answered this question myself two sections further down.

I understand that the final commit in the screenshot above has two parents. But I don't understand why the violet commit which happened on the feature branch is not inside the final merged commit on master (which would, I think, mean that the violet branch shouldn't be visible anymore after deleting it).

Replay of steps from the command line (instead of SourceTree)

I replayed it on the command line (just to check whether SourceTree did what I thought it did) and the final step was a git merge feature. Same situation:

Tree visualisation on the command line

Trial with --squash

I undid the last merge and tried this:

git merge --squash feature
git commit "Squashed merge"
git delete -D feature # Note that -d did not work; it said "error: The branch 'feature' is not fully merged."

And now it shows what I would have expected in the first place. One straight line and no indication of the feature branch ever existing:

Straight tree line after --squash

Question

  1. How is this merge different from the previous merge?

I guess I sort of pieced together what happens with those merges after all the trial and error above, but I would be grateful if someone could really explain in detail what the semantic difference of the above steps are.

Community
  • 1
  • 1
Lernkurve
  • 20,203
  • 28
  • 86
  • 118

2 Answers2

4

When you delete a branch, you're deleting a pointer to a commit, not the commit itself. If there are no other references to the commit, then the commit can eventually be garbage-collected, but the merged commit creates a reference to that commit (since that commit is its parent).

The initial merge workflow creates a merge commit with two parents, and the second parent commit still exists even if the branch pointing at it does not.

When you do git merge --squash, you are effectively causing a rebase of your commit onto the target branch, which gives you the linear history instead of the dual-parent history. For the distinction between that command and rebase, take a look at this question.

Community
  • 1
  • 1
merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • Nice link. It says there for `git merge --squash` "without marking any merge relationship". That's the part I didn't understand. Thanks! – Lernkurve Sep 24 '15 at 21:22
  • @Lernkurve. You are welcome. If you want to rewrite your history, you need to decide exactly what you want your history to look like. For example, do you want a dozen commits on top of your `master` branch or just one commit that is equivalent to all of them? – merlin2011 Sep 24 '15 at 21:28
  • I'm interested in the first example where I can keep the dozen commits on top of `master`. But for learning purposes, I'm also interested in the example where there is one commit that is equivalent to all of them. – Lernkurve Sep 24 '15 at 21:30
  • @Lernkurve, Create a new branch and use squash / rebase, and then cherry-pick the rest of the commits from master on top. – merlin2011 Sep 24 '15 at 21:45
  • Worked! :-) I just cherry-picked the hell out of it with [ranges](http://stackoverflow.com/questions/1994463/how-to-cherry-pick-a-range-of-commits-and-merge-into-another-branch). Delightful! Thank you very much. – Lernkurve Sep 24 '15 at 22:00
4
  1. You still see the violet part because you dit a git merge, which creates a merge commit assembling the two branches. Since branches have diverged, this is a "non fast forward" merge, this is why the history will still show this kind of tree.

  2. You don't want the violet part ? Use git rebase instead of git merge. In your case:

    • git checkout master
    • git rebase feature
    • git branch -d feature

This will replay the commits of feature on master before the divergence. You'll have a straight line in your history log.

  1. You did a git merge --squash which quite alike a rebase - but you're squashing all the commits of the source branch in one commit (in your case you only have one commit, so it doesn't really show)
topheman
  • 7,422
  • 4
  • 24
  • 33
  • Your second point was very helpful and it explains how to avoid getting the violet part in the first place. However, let's say I did perform a `git merge feature` and then another dozen commits on top of it on `master`: how can I make the violet part disappear so late in the game? Let's further assume I haven't pushed anything so rewriting history was acceptable. How would one do that? – Lernkurve Sep 24 '15 at 21:10
  • 1
    Assuming you didn't push anything, it's still doable. With a dozen commits on top, it depends ... You have two solutions : 1) Those commits are not too tied with the merge ? You can do an interactive rebase (it seems a little hard) - 2) `git reset` just before the merge, `git stash` your modifications, `git rebase feature` then `git stash pop` to retrieve your modifications, and redo your commits – topheman Sep 24 '15 at 21:23
  • @topheman Trying point 2: The "feature" was deleted, after the reset I don't see the branch "feature" again? – powder366 Oct 11 '15 at 20:21
  • Not a reset, a rebase: that's why you won't need this feature branch anymore on this scenario where you want to import code from feature to master. – topheman Oct 11 '15 at 20:31
  • While the high level concepts are mostly correct, I assume your second point was supposed to be the other way around? `git checkout feature`, `git rebase master`, `git checkout master`, `git branch -d feature`? – RayLuo May 05 '17 at 22:39