Skip to content

Commit 5d99633

Browse files
Adds the episode 07-history detailing how to graphically explore commit history and the effect of different merge strategies on your repositories history
1 parent 5d9b9f4 commit 5d99633

File tree

1 file changed

+284
-0
lines changed

1 file changed

+284
-0
lines changed

episodes/07-history.md

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
---
2+
title: History
3+
teaching: 15
4+
exercises: 0
5+
---
6+
7+
::::::::::::::::::::::::::::::::::::::: objectives
8+
9+
- Visualise our git history.
10+
- Learn the difference between merge, squash merge, and rebase.
11+
12+
::::::::::::::::::::::::::::::::::::::::::::::::::
13+
14+
:::::::::::::::::::::::::::::::::::::::: questions
15+
16+
- Why is a linear history useful?
17+
18+
::::::::::::::::::::::::::::::::::::::::::::::::::
19+
20+
The history of your repository is simply
21+
its commits.
22+
A more linear history is easier to understand
23+
and can be helpful when using certain git
24+
commands to explore your history.
25+
26+
## Viewing History
27+
28+
You have already learnt that we can use the
29+
`git log` command to output the commit history
30+
of our repository.
31+
32+
```bash
33+
$ git log
34+
```
35+
36+
```output
37+
commit acce45c86ece7fd4823ddc6c1addb43edf4c0794
38+
Merge: e3fc783 ca8aca9
39+
Author: Robert FitzRoy <[email protected]>
40+
Date: Mon Sep 23 15:50:15 2024 +0100
41+
42+
Merge pull request #1 from MetOffice/mo-fitzroy-patch-1
43+
44+
Create CITATION.cff
45+
46+
commit ca8aca9f2f43a4d799eb5c9ce9596b42360faa8b
47+
Author: Robert FitzRoy <[email protected]>
48+
Date: Mon Sep 23 15:49:36 2024 +0100
49+
50+
Create CITATION.cff
51+
52+
commit e3fc783648222d5eef0739922b06794b8d690341
53+
Author: Robert FitzRoy <[email protected]>
54+
Date: Fri Sep 20 13:01:05 2024 +0100
55+
56+
Initial commit
57+
```
58+
59+
This shows the first 3 commits to the `git-training-demo` repository (the full output isn't shown here because it's very long).
60+
We can use certain flags with `git log` to better
61+
visualise the history in graph form:
62+
63+
```bash
64+
$ git log --decorate --oneline --graph
65+
```
66+
67+
```output
68+
* d800b46 (HEAD -> main, origin/main, origin/HEAD) Merge pull request #2 from MetOffice/mo-fitzroy-patch-2
69+
|\
70+
| * dbc944d Add pre-commit checks
71+
|/
72+
* acce45c Merge pull request #1 from MetOffice/mo-fitzroy-patch-1
73+
|\
74+
| * ca8aca9 Create CITATION.cff
75+
|/
76+
* e3fc783 Initial commit
77+
```
78+
79+
The [GitHub Documentation for git log](https://git-scm.com/docs/git-log) has information on all the available flags.
80+
The key here is `--graph` shows us the graphical
81+
representation of our history on the left of the
82+
terminal.
83+
`*`'s are commits which are connected by lines.
84+
The vertical lines on the far left represent the `main` branch.
85+
The output above shows two feature branches each with
86+
only one commit which were then merged back into
87+
`main` via a pull request.
88+
89+
You can either remember the flags using
90+
the phrase "git dog", `d` for `--decorate`,
91+
`o` for `--oneline`, `g` for `--graph` or
92+
you can set an alias for the `git log` command:
93+
94+
```bash
95+
$ git config --global alias.dog "log --decorate --oneline --graph"
96+
```
97+
98+
This alias makes these two commands equivalent:
99+
100+
```bash
101+
$ git dog
102+
$ git log --decorate --oneline --graph
103+
```
104+
105+
You can of course customise the log command
106+
with other keywords and set more aliases for
107+
different log views.
108+
Some useful examples can be found on
109+
[this Stackoverflow comment](https://stackoverflow.com/questions/1838873/visualizing-branch-topology-in-git/34467298#34467298).
110+
111+
::: callout
112+
113+
### IDE Git History Extensions
114+
115+
Your IDE may have extensions which render your
116+
git history as easy to read graphs.
117+
If you use VSCode we recommend the [Git Graph extension](https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph).
118+
119+
:::
120+
121+
## Merge Options
122+
123+
When you opened your PRs you were given
124+
three options for merging your feature
125+
branch into `main`.
126+
We will now explore how each merging method
127+
affects the history of your repository.
128+
In all the examples below we start with the same git history.
129+
130+
### Merge
131+
132+
Starting with:
133+
134+
```mermaid
135+
gitGraph
136+
accDescr {A Git graph showing the <code>main</code> branch with a <code>feature</code> branch branching off at the second commit of <code>main</code>.}
137+
commit id: '4631ebc'
138+
commit id: 'ee406ac'
139+
branch feature
140+
checkout feature
141+
commit id: '7cec787 Cool feature'
142+
checkout main
143+
commit id: '62440f8'
144+
checkout feature
145+
commit id: 'cd2db46 Cool feature docs'
146+
```
147+
148+
Using merge creates a merge commit joining
149+
the two branches:
150+
151+
```mermaid
152+
gitGraph
153+
accDescr {A Git graph showing the result of merging a <code>feature</code> branch with the <code>main</code> branch. The history is non-linear in this case and difficult to read.}
154+
commit id: '4631ebc'
155+
commit id: 'ee406ac'
156+
branch feature
157+
checkout feature
158+
commit id: '7cec787 Cool feature'
159+
checkout main
160+
commit id: '62440f8'
161+
checkout feature
162+
commit id: 'cd2db46 Cool feature docs'
163+
checkout main
164+
merge feature
165+
```
166+
167+
This results in a non-linear history which
168+
can be hard to navigate.
169+
You can avoid this non-linear history by rebasing
170+
your `feature` branch before you merge.
171+
Rebasing a branch before you submit a PR for
172+
review is covered in the next episode.
173+
174+
Some teams choose to use Merge because it
175+
keeps all the individual commits that made
176+
up your change so more accurately represents
177+
the history of your repository.
178+
179+
### Squash and Merge
180+
181+
Starting with:
182+
183+
```mermaid
184+
gitGraph
185+
accDescr {A Git graph showing the <code>main</code> branch with a <code>feature</code> branch branching off at the second commit of <code>main</code>.}
186+
commit id: '4631ebc'
187+
commit id: 'ee406ac'
188+
branch feature
189+
checkout feature
190+
commit id: '7cec787 Cool feature'
191+
checkout main
192+
commit id: '62440f8'
193+
checkout feature
194+
commit id: 'cd2db46 Cool feature docs'
195+
```
196+
197+
Squashing before merging squashes all the
198+
commits on the feature branch into one
199+
commit which is then merged onto main:
200+
201+
```mermaid
202+
gitGraph
203+
accDescr {A Git graph showing the result of squashing then merging a <code>feature</code> branch with the <code>main</code> branch.}
204+
commit id: '4631ebc'
205+
commit id: 'ee406ac'
206+
commit id: '62440f8'
207+
commit id: '5rtw8bq Squash & Merge Cool feature'
208+
```
209+
210+
The last commit on main `5rtw8bq Squash & Merge Cool feature`
211+
is the two feature branch commits squashed
212+
together into a new one.
213+
214+
Here the history is linear but all our commits
215+
have been squashed into one.
216+
If you have a very large branch with many commits
217+
you might not want to squash them all into one commit.
218+
Squashing in this case will make bug hunting harder.
219+
Remember you should try and break work down into
220+
small pieces so you avoid huge branches.
221+
222+
### Rebase
223+
224+
Starting with:
225+
226+
```mermaid
227+
gitGraph
228+
accDescr {A Git graph showing the <code>main</code> branch with a <code>feature</code> branch branching off at the second commit of <code>main</code>.}
229+
commit id: '4631ebc'
230+
commit id: 'ee406ac'
231+
branch feature
232+
checkout feature
233+
commit id: '7cec787 Cool feature'
234+
checkout main
235+
commit id: '62440f8'
236+
checkout feature
237+
commit id: 'cd2db46 Cool feature docs'
238+
```
239+
240+
Rebase re-writes your git history removing
241+
the `feature` branch commits from the `feature`
242+
branch and adding them to `main`:
243+
244+
```mermaid
245+
gitGraph
246+
accDescr {A Git graph showing the result of rebasing a <code>feature</code> branch with the <code>main</code> branch.}
247+
commit id: '4631ebc'
248+
commit id: 'ee406ac'
249+
commit id: '62440f8'
250+
commit id: '7cec787 Cool feature'
251+
commit id: 'cd2db46 Cool feature docs'
252+
```
253+
254+
::: caution
255+
256+
### Rebase Re-Writes History
257+
258+
Rebasing re-writes your git history.
259+
Do **NOT** rebase shared branches such as `main`.
260+
261+
:::
262+
263+
Since rebase re-writes your history you have to force
264+
push to the GitHub remote to override your remotes history.
265+
The history in this case is linear and retains all
266+
the commits which makes it easier to search for
267+
a commit that introduced a bug.
268+
269+
Your team will decide what approach is right
270+
for your project.
271+
If you choose to perform normal merge's on
272+
your PRs we recommend rebasing your feature branch
273+
before the PR is ready for review.
274+
275+
:::::::::::::::::::::::::::::::::::::::: keypoints
276+
277+
- `git log --decorate --oneline --graph` lets you visualise your repository history in graph form.
278+
- There are three options for merging your feature
279+
branch into `main`.
280+
- merge: creates a merge commit and results in a non-linear history unless you first rebase your feature branch
281+
- squash and merge: squashes all your feature branch commits into one merge commit on `main`. Your history is linear.
282+
- rebase: re-writes your git history so that all the feature branch commits are now on `main`. Your history is linear.
283+
284+
::::::::::::::::::::::::::::::::::::::::::::::::::

0 commit comments

Comments
 (0)