Most work done in branches eventually gets merged together.
Merging combines the changes from one branch into another, bringing their diverged timelines back together.
When you merge, Git looks at the two branches and figures out how their histories have diverged since their merge base (i.e., the most recent common ancestor commit of two branches). It then applies the changes from the other branch onto your current branch, creating a new commit. The new commit created when merging is called a merge commit — it records the result of combining both sets of changes.
Given below is an illustration of how such a merge looks like in the revision graph:

- We are on the
fix1branch (as indicated byHEAD). - We have switched to the
masterbranch (thus,HEADis now pointing tomasterref). - The
fix1branch has been merged into themasterbranch, creating a merge commitf. The repo is still on themasterbranch.
A merge commit has two parent commits e.g., in the above example, the merge commit f has both d and e as parent commits. The parent commit on the receiving branch is considered the first parent and the other is considered the second parent e.g., in the example above, fix1 branch is being merged into the master branch (i.e., the receiving branch) -- accordingly, d is the first parent and e is the second parent.
In this hands-on practical, we continue with the samplerepo-things repo from earlier, which should look like the following. Note that we are ignoring the feature1-alt branch, for simplicity.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
commit id: "m2"
branch feature1
commit id: "f1"
commit id: "[feature] f2"
checkout master
commit id: "[HEAD → master] m3"
checkout feature1
1 Switch back to the feature1 branch.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
commit id: "m2"
branch feature1
commit id: "f1"
commit id: "[HEAD → feature1] f2"
checkout master
commit id: "[master] m3"
checkout feature1
2 Merge the master branch to the feature1 branch, giving an end-result like the following. Also note how Git has created a merge commit (shown as mc1 in the diagram below).
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
commit id: "m2"
branch feature1
commit id: "f1"
commit id: "f2"
checkout master
commit id: "[master] m3"
checkout feature1
merge master id: "[HEAD → feature1] mc1"
$ git merge master
Right-click on the master branch and choose merge master into the current branch. Click OK in the next dialog.
The revision graph should look like this now (colours and line alignment might vary but the graph structure should be the same):

Observe how the changes you did in the master branch (i.e., the imaginary bug fix in m3) is now available even when you are in the feature1 branch.
Furthermore, observe (e.g., git show HEAD) how the merge commit contains the sum of changes done in commits m3, f1, and f2.
3 Add another commit to the feature1 branch.
Switch to the master branch and add one more commit.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
commit id: "m2"
branch feature1
commit id: "f1"
commit id: "f2"
checkout master
commit id: "m3"
checkout feature1
merge master id: "mc1"
commit id: "[feature1] f3"
checkout master
commit id: "[HEAD → master] m4"
4 Merge feature1 to the master branch, giving and end-result like this:
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
commit id: "m2"
branch feature1
commit id: "f1"
commit id: "f2"
checkout master
commit id: "m3"
checkout feature1
merge master id: "mc1"
commit id: "[feature1] f3"
checkout master
commit id: "m4"
merge feature1 id: "[HEAD → master] mc2"
git merge feature1
Right-click on the feature1 branch and choose Merge.... The resulting revision graph should look like this:
Now, any changes you did in feature1 branch are available in the master branch.
done!
When the branch you're merging into hasn't diverged — meaning it hasn't had any new commits since the merge base — Git simply moves the branch pointer forward to include all the new commits, keeping the history clean and linear. This is called a fast-forward merge because Git simply "fast-forwards" the branch pointer to the tip of the other branch. The result looks as if all the changes had been made directly on one branch, without any branching at all.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
commit id: "[HEAD → master] m2"
branch bug-fix
commit id: "b1"
commit id: "[bug-fix] b2"
checkout master
→
[merge bug-fix]
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
commit id: "m2"
commit id: "b1"
commit id: "[HEAD → master][bug-fix] b2"
checkout master
In the example above, the master branch has not changed since the merge base (i.e., m2). Hence, merging the branch bug-fix onto master can be done by fast-forwarding the master branch ref to the tip of the bug-fix branch (i.e., b2).
Let's continue with the same samplerepo-things repo we used above, and do a fast-forward merge this time.
1 Create a new branch called add-countries, switch to it, and add some commits to it. You should have something like this now:
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "[master] mc2"
branch add-countries
commit id: "a1"
commit id: "[HEAD → add-countries] a2"
2 Go back to the master branch.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "[HEAD → master] mc2"
branch add-countries
commit id: "a1"
commit id: "add-countries] a2"
3 Merge the add-countries branch onto the master branch. Observe that there is no merge commit. The master branch ref (and the HEAD ref along with it) moved to the tip of the add-countries branch (i.e., a2) and both branches now points to a2.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master (and add-countries)'}} }%%
commit id: "mc2"
commit id: "a1"
commit id: "[HEAD → master][add-countries] a2"
done!
It is possible to force Git to create a merge commit even if fast forwarding is possible. This is useful if you wish the revision graph to visually show when each branch was merged to the main timeline.
To prevent Git from fast-forwarding, use the --no-ff switch when merging. Example:
git merge --no-ff add-countries
Windows: Tick the box shown below when you merge a branch:
Mac:
Trigger the branch operation using the following menu button:

In the next dialog, tick the following option:
To permanently prevent fast-forwarding:
- Go to Sourcetree
Settings. - Navigate to the
Gitsection. - Tick the box
Do not fast-forward when merging, always create commit.
A squash merge combines all the changes from a branch into a single commit on the receiving branch, without preserving the full commit history of the branch being merged. This is especially useful when the feature branch contains many small or experimental commits that would clutter the main branch’s history. By squashing, you retain the final state of the changes while presenting them as one cohesive unit, making the project history easier to read and manage. It also helps maintain a linear, simplified commit log on the main branch.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "[HEAD → master] m1"
branch feature
checkout feature
commit id: "f1"
commit id: "[feature] f2"
→
[squash merge...]
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
commit id: "m1"
branch feature
checkout feature
commit id: "f1"
commit id: "[feature] f2"
checkout master
commit id: "[HEAD → master] s1 (same as f1+f2)" type: HIGHLIGHT
In the example above, the branch feature has been squash merged onto the master branch, creating a single 'squashed' commit s1 that combines the all commits in feature branch.