What is a merge and what is the difference between a fast-forward and a merge commit?
Show answer — try answering out loud first
A merge integrates the changes from one branch into another. If the target branch hasn't advanced since the other one was created, Git does a fast-forward: it just moves the pointer forward, without creating a new commit. If both branches advanced separately, Git creates a merge commit that joins the two histories and has two parents.
You worked on a feature branch and now you want to bring those changes into main. You stand on main and run git merge feature. There are two scenarios:
- Fast-forward:
maindidn't receive new commits while you were working onfeature. Since the history is linear, Git simply advances the pointer ofmainup to the last commit offeature. No merge commit is created. - Merge commit (three-way merge): both
mainandfeaturereceived different commits. Git can't just advance the pointer, so it creates a special merge commit with two parents (the last one of each branch) to join both histories. This is where conflicts can appear if the two branches touched the same lines.
# I'm on feature and I want to integrate it into main
git switch main
git merge feature
# Fast-forward case (main didn't advance):
# Output: Updating 1a2b3c4..5d6e7f8
# Fast-forward
# No new commit is created, the pointer just moves forward
# Merge commit case (both branches advanced):
# Output: Merge made by the 'ort' strategy.
# A merge commit with two parents is created
# ALWAYS force a merge commit, even if a fast-forward is possible
git merge --no-ff feature
# Useful to leave a record in the history that a branch existed
# After merging, delete the branch
git branch -d feature
Believing that a merge always creates a merge commit. No: if it's a fast-forward, no commit is created, only the pointer moves, and the history stays linear. Another mistake is forgetting that the merge is run from the target branch: you have to be on main (or wherever you want to integrate) and merge the other branch into it.
"A merge integrates the changes from one branch into another. I stand on the target branch, for example
main, and rungit merge feature. Ifmaindidn't advance sincefeaturebranched off, Git does a fast-forward: it just moves the pointer forward, without a new commit. If both branches advanced separately, it creates a merge commit with two parents to join the histories, and that's where conflicts can appear. Sometimes I use--no-ffto force the merge commit and leave a record that there was a branch."
You created feature from main, made 2 commits on feature, and main didn't change anything in the meantime. You run git merge feature from main. Is a merge commit created?
Show answer
No. Since main didn't advance, the history is linear and Git does a fast-forward: it simply advances the main pointer up to the last commit of feature, without creating any merge commit. If you wanted to force a merge commit anyway, you would use git merge --no-ff feature.