Merging brings changes from one branch back into another. This is how you integrate features and fix bugs into your main codebase. Usually this works smoothly, but when two branches modify the same lines, you get a merge conflict that needs manual resolution.
Branch Merging
git merge branch-name combines changes. If the branches have diverged without modifying the same lines, you get a fast-forward merge. When conflicts happen, Git pauses the merge and lets you edit the conflicting files manually. After resolving, commit to continue.
$ git checkout main
$ git merge feature-auth
$ git mergetool
$ git add file-with-conflict.txt
$ git commit
Fast-Forward vs Three-Way Merge
Git performs two types of merges depending on the branch history:
Fast-forward merge happens when the target branch has no new commits since you created your feature branch. Git simply moves the pointer forward:
# Before merge:
# main: A -> B -> C
# feature: C -> D -> E
# After fast-forward:
# main: A -> B -> C -> D -> E
Three-way merge happens when both branches have new commits. Git creates a new merge commit that combines both histories:
# Before merge:
# main: A -> B -> C -> F
# feature: C -> D -> E
# After merge:
# main: A -> B -> C -> F -> M (merge commit)
# feature: C -> D -> E -/
Handling Merge Conflicts
Merge conflicts occur when both branches modify the same lines in a file. Git marks the conflicting sections with special markers:
<<<<<<< HEAD
const port = 3000;
=======
const port = 8080;
>>>>>>> feature-port
To resolve a conflict:
- Open the file and find the conflict markers
- Choose which version to keep (or combine both changes)
- Remove the conflict markers
- Stage the resolved file and commit
# After resolving conflicts in the file
$ git add index.js
$ git commit -m "Merge feature-port, resolve port conflict"
Merging vs Rebasing
While git merge preserves the exact history of how branches were developed, git rebase replays your commits on top of the target branch, creating a linear history:
# Instead of merging, rebase your feature branch
$ git checkout feature
$ git rebase main
# Then switch to main and fast-forward merge
$ git checkout main
$ git merge feature
Rebasing creates a cleaner, linear history but rewrites commit hashes. Never rebase commits that have been pushed to a shared repository โ it can cause serious problems for other developers who have already pulled those commits.