History
Last updated on 2025-04-03 | Edit this page
Overview
Questions
- Why is a linear history useful?
Objectives
- Visualise our git history.
- Learn the difference between merge, squash merge, and rebase.
The history of your repository is simply its commits. A more linear history is easier to understand and can be helpful when using certain git commands to explore your history.
Your Git history will look different depending on the merge strategy
you use when merging PRs and whether you allow merging main
into a feature branch. It’s up to you and your team to decide which
strategy is best for your repository.
In the Introduction
to Version Control with Git lesson you learnt that we can use the
git log
command to view the commit history of our
repository.
We can use certain flags with git log
to better
visualise the history in graph form:
The GitHub Documentation
for git log has information on all the available flags. Some useful
examples of git log
alias’s and flags can be found on this
Stackoverflow comment.
IDE Git History Extensions
Your IDE may have extensions which render your git history as easy to read graphs. If you use VSCode we recommend the Git Graph extension.
Merge Options
When you open a PR you are given three options for merging your
feature branch into main
. We will now explore how each
merging method affects the history of your repository. In all the
examples below we start with the same git history.
Merge
Starting with:
gitGraph
accDescr {A Git graph showing the main branch with a feature branch branching off at the second commit of main.}
commit id: '4631ebc'
commit id: 'ee406ac'
branch feature
checkout feature
commit id: '7cec787 Cool feature'
checkout main
commit id: '62440f8'
checkout feature
commit id: 'cd2db46 Cool feature docs'
Using merge creates a merge commit joining the two branches:
gitGraph
accDescr {A Git graph showing the result of merging a feature branch with the main branch. The history is non-linear in this case and difficult to read.}
commit id: '4631ebc'
commit id: 'ee406ac'
branch feature
checkout feature
commit id: '7cec787 Cool feature'
checkout main
commit id: '62440f8'
checkout feature
commit id: 'cd2db46 Cool feature docs'
checkout main
merge feature
This results in a non-linear history which can be hard to navigate.
You can avoid this non-linear history by rebasing your
feature
branch before you merge. Rebasing a branch before
you submit a PR for review is covered in the next episode.
Some teams choose to use Merge because it keeps all the individual commits that made up your change so more accurately represents the history of your repository.
Squash and Merge
Starting with:
gitGraph
accDescr {A Git graph showing the main branch with a feature branch branching off at the second commit of main.}
commit id: '4631ebc'
commit id: 'ee406ac'
branch feature
checkout feature
commit id: '7cec787 Cool feature'
checkout main
commit id: '62440f8'
checkout feature
commit id: 'cd2db46 Cool feature docs'
Squashing before merging squashes all the commits on the feature branch into one commit which is then merged onto main:
gitGraph
accDescr {A Git graph showing the result of squashing then merging a feature branch with the main branch.}
commit id: '4631ebc'
commit id: 'ee406ac'
commit id: '62440f8'
commit id: '5rtw8bq Squash & Merge Cool feature'
The last commit on main
5rtw8bq Squash & Merge Cool feature
is the two feature
branch commits squashed together into a new one.
Here the history is linear but all our commits have been squashed into one. If you have a very large branch with many commits you might not want to squash them all into one commit. Squashing in this case will make bug hunting harder. Remember you should try and break work down into small pieces so you avoid huge branches.
Rebase
Starting with:
gitGraph
accDescr {A Git graph showing the main branch with a feature branch branching off at the second commit of main.}
commit id: '4631ebc'
commit id: 'ee406ac'
branch feature
checkout feature
commit id: '7cec787 Cool feature'
checkout main
commit id: '62440f8'
checkout feature
commit id: 'cd2db46 Cool feature docs'
Rebase re-writes your git history removing the feature
branch commits from the feature
branch and adding them to
main
:
gitGraph
accDescr {A Git graph showing the result of rebasing a feature branch with the main branch.}
commit id: '4631ebc'
commit id: 'ee406ac'
commit id: '62440f8'
commit id: '9bfg54s Cool feature'
commit id: '1vyd742 Cool feature docs'
Rebase Re-Writes History
Rebasing re-writes your git history. Do NOT rebase
shared branches such as main
.
Since rebase re-writes your history you have to force push to the
GitHub remote to override your remotes history. The history in this case
is linear and retains all the commits which makes it easier to search
for a commit that introduced a bug. Rebasing a feature branch can be
difficult / impossible if you have merged main
into your
feature branch to update it with the latest changes or resolve
conflicts. You should choose to move your feature branch to the
HEAD
of main
using rebasing instead.
Your team will decide what approach is right for your project.
Key Points
-
git log --decorate --oneline --graph
lets you visualise your repository history in graph form. - There are three options for merging your feature branch into
main
. - merge: creates a merge commit and results in a non-linear history unless you first rebase your feature branch.
- squash and merge: squashes all your feature branch commits into one
merge commit on
main
. Your history is linear. - rebase: re-writes your git history so that all the feature branch
commits are now on
main
. Your history is linear.