git
fast-forward vs. rebase
1. fast-forward (ff) merge
A --- B --- C main
\
D --- E featuregit checkout main
git merge featureGit moves pointer forward, history is exactly preserved:
A --- B --- C --- D --- E
main, feature2. ff-incompatible scenario
Consider the following scenario:
A --- B --- C --- F main
\
D --- E featureGit cannot simply move the pointer forward, no obvious way to solve the merge. This leaves two options to get D and E into main:
- rebasing
- merge commit
3 options to solve this
3.1 rebase main onto feature, followed by ff
git checkout feature
git rebase mainGit will
- Find commits unique to feature (D, E)
- Temporarily remove them
- Move feature to F
- Replay the changes
Result:
A --- B --- C --- F --- D' --- E'D' and E' are “new” commits (get new commit hashes)
Then enables a frictionless (fast-forward) merge:
git checkout main
git merge featurerebase simply enables a fast-forward merge.
3.2 merge commit
git checkout main
git merge featureA --- B --- C --- F -------- M main
\ /
D --- E ---------- featureAdvantage: branching structure is preserved, D and E remain exactly as commited.
3.3 squash merge
git checkout main
git merge --squash feature
git commitResuls in
A --- B --- C --- F --- S main
\
D --- E featureScontains everything fromDandE- Original commits do not make it into main
Implications
- For pulling remote changes,
git pull --rebaseis often a good choice (can be set viagit config --global pull.rebase true, if not already the case) - Merges of pull requests often rely on squash merges