Chris
Chris

Reputation: 1587

Git/Sourcetree basic branching and merging

Newbie question alert!!! I am just starting to get into using Git, and particularly Sourcetree which seems like a good application for visualizing it. On my first test it went along pretty well, branching and merging (see the top diagram). I know this structure means I'm using the development and master branch the wrong way round, but that's fine because at least it worked.

On my second try though, I couldn't seem to visualise any branches, even though work was being done in both of them they seem to appear in one single branch (with a '7 ahead' note), and when I try and merge nothing seems to happen. Hopefully the second screenshot is enough for someone to tell me what is happening here? If not I will try and give some more info.

I'm just playing around at the moment, so still getting to grips with proper workflow, just trying to get the basic branching and merging actions to take place in a consistent manner through Sourcetree. Any help will be appreciated.

enter image description here

Upvotes: 42

Views: 51795

Answers (4)

Guney Ozsan
Guney Ozsan

Reputation: 330

You can prevent branches from disappearing in Source Tree permanently by enabling "Do not fast-forward when merging, always create commit" in Tools/Options.

Disabling fast-forward when merging permanently in Source Tree

If you want to decide for each merge operation, there is an option "Create a new commit even if fast-forward is possible" in the Merge dialog box.

Disable fast-forward when merging during each merge operation in Source Tree

Also I suggest referring Eelke Blok's answer for the technical details.

Upvotes: 2

Eelke Blok
Eelke Blok

Reputation: 51

There's a few things going on here. First, it's useful to understand that branches in Git are really just "labels" that are stuck to a particular commit, and that will be moved automatically when you commit to the the branch; Git will create the new commit, with a new commit hash, and update the branch/label to point to the new commit. (You might ask, how is this different from tags, then? A tag is stuck to the same commit, and will not get updates when you call git commit.)

When you create a new branch, all that happens is that Git creates a new label, pointing to the same commit you were on. Only when you create a new commit while this new branch is checked out, will you see the new branch diverge from the other branch.

The real confusion starts when you start merging branches again, and this is largely due to a weird thing Git calls "fast forward merging", which it does by default. Let's take your second example and imagine that your master and develop are where originally origin/master and origin/develop were:

Simple linear branching example

When you ask Git to merge one branch into another, Git will go and figure out what it needs to do to get the difference between those branches into the target branch. Let's say you want to merge the changes you made to develop into master, so you tell git:

$ git checkout master
$ git merge develop

Git will look at the branches, and see that develop is just ahead of master by a few commits, but there's nothing more complicated going on than that. So, it will do a "fast forward" merge, by simply taking the master label and sticking it to the commit where develop is pointing. Mission accomplished, changes that were only in develop before are now also in master.

Should each branch have extra commits, like in your first example right before merging master into develop, "something more complicated" is going on. You made a commit on master, then did a git checkout develop, made a commit there, and then asked Git to merge master back into develop. Git can now no longer "cheat" by just moving branch-labels around. It will need to figure out how to unify the changes from the two branches into a single state of the files under its control (let's assume, for now, it is always able to do that, which is not that far from the truth; its quite good at it. If it can't, you have a merge conflict, which is really not as bad as it sounds).

The new content, after the merge, will neither be the last state of the first branch, nor will it be the state of the second branch. So, it needs to be represented with a brand new commit, which is what you see at the top of your first example; Git created what it calls a "merge commit" to represent the new state with the changes from each branch merged into a single state.

Lastly, you can force Git to always create a merge commit, eventhough it is strictly, technically, not needed. In the command line, you can do this with the flag --no-ff, for no fast forward. Graphical clients will have a checkbox that will accomplish the same thing (in SourceTree, it is currently labeled "Create a commit even if merge resolved via fast-forward"). Many (including myself) actually recommend to just merge with --no-ff, because that way the act of merging is always recorded in history, regardless of technicallities like whether it would technically be possible to just move branch pointers around.

Upvotes: 4

Jason Alford
Jason Alford

Reputation: 21

I just ran into this same problem and found that there's a setting in SourceTree to "Do not fast-forward when merging, always create commit". Make sure that's checked and you'll see the branch structure from them on.

This setting is found on the Git tab in preferences.

Upvotes: 2

quickshiftin
quickshiftin

Reputation: 69731

In the second picture there are branches. Locally you have 2 branches, master & develop. Both branches are resting at the same commit though. If you want to 'see branches' as in the first picture you can make a commit on develop, however the graph will still apear to be linear. You'll be able to merge develop into master at that point if you want.

If you want to see the graph diverge, try putting a commit on master as well. Then you will start to see something more like the first picture.

To get an idea of how git works with a visualization program like this, I suggest you do actions like I suggested above, and take a look at the graph at each intermediate step.

Upvotes: 13

Related Questions