You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We can rebase the `feature_A` branch to the last commit in `master`:
25
25
@@ -31,17 +31,17 @@ git rebase master
31
31
The result will look like this.
32
32
33
33
{:class="img-responsive" style="max-width:100%"}
34
+
after rebase")
35
35
36
36
Checking out `master` again, we can merge `feature_A` with `master`. The merge will by default be a fast-forward. We end up with a linear history, which many find attractive as it is easy to follow. The disadvantage is that we rewrite the history as the commit hashes changes.
37
37
38
-
{:class="img-responsive" style="max-width:100%"}
38
+

39
39
40
40
### Merge
41
41
42
42
If we don’t use rebase, but just merge `feature_A` with `master`, we get an merge commit, a new commit pointing to the previous last commit in `master` and the previous last commit in `feature_A`.
43
43
44
-
{:class="img-responsive" style="max-width:100%"}
44
+

45
45
46
46
If we only do merges, we show the true story of the repository, how the code came to be. As the repository grows with new branches, maybe more contributors, following the history can become very challenging. The git graph can look like the tracks of a large railway station, where it can be hard to find the ancestors of a feature.
47
47
@@ -59,7 +59,7 @@ How will this look?
59
59
60
60
Let us say we have created a new function or class, something that belongs together - a semantic unit we call `feature_B`. The base of `feature_B` is the last commit in `master`.
61
61
62
-
{:class="img-responsive" style="max-width:70%"}
62
+

63
63
64
64
If we do a merge, git will by default do a fast-forward merge. Following our newly stated policy, we want this merge to be a merge commit. Consequently, we add the option --no-ff to the merge command:
The result will be like this, where the feature is clearly visible in a feature path, presumably with well written commit messages explaining what has been added in this path of work.
76
76
77
-
{:class="img-responsive" style="max-width:100%"}
77
+

78
78
79
79
#### Rebase revisited
80
80
81
81
Now we take the case where we checkout a branch from C1 to do some corrections. While we were doing the corrections, at least before we were able to complete the corrections, `master` moved to M1 as in the picture above. A merge commit will add unnecessary complexity to the story of our project. We are not adding a new semantic unit, just fixing things that got wrong in the first phase. That we started to fix things from C1 is not necessarily a important information to keep for the project.
82
82
83
-
{:class="img-responsive" style="max-width:100%"}
83
+

84
84
85
85
Following our second principle, we rebase the fix_typos branch to M1. Then we do a merge, but this time as fast-forward. If we have configured merge for not doing fast forward when possible, as the configuration statement above, we need to add the --ff-only argument:
86
86
```sh
@@ -91,7 +91,7 @@ git merge fix_typos --ff-only
91
91
```
92
92
The git graph will now look like this:
93
93
94
-
{:class="img-responsive" style="max-width:100%"}
94
+

95
95
96
96
### Rebase vs merge revisited
97
97
Rebase and merge serve two different purposes. We can use this to our advantage to create a clear story, a more readable git log (It is important to create a story, remember?). By using the above principles as guidance, we will become more conscious of where these operations will serve us or add more clutter. For instance, we might conclude that rebasing semantic branches, but insisting on a merge commit, is perfectly fine, because it is where the feature (the semantic entity) enters the `master` branch which is important, not where the development first started. Features will clearly stand out as a visible pattern in a git repository following such a practice.
0 commit comments