Every branch you create eventually needs to come back together. That’s where understanding what does git merge do becomes critical for anyone working in a team or managing parallel changes across a repository.
Git merge is one of the most used commands in version control, yet it’s also one of the most misunderstood. Developers run it daily, but many don’t fully grasp the mechanics behind fast-forward merges, three-way merges, or why conflicts happen in the first place.
This guide breaks down how the git merge command actually works, the different merge strategies Git offers, how to handle merge conflicts, and the common mistakes that trip up even experienced developers. Whether you’re merging feature branches or syncing with a remote, you’ll know exactly what’s happening under the hood.
What Does Git Merge Do

Git merge is a command that combines the work from one branch into another. It takes changes made in a source branch and integrates them into your current working branch, producing a unified commit history.
That’s the short answer. But the actual behavior depends on the state of both branches at the time you run it.
If the target branch has no new commits since the source branch was created, Git performs a fast-forward. It just moves the branch pointer forward. No extra commit gets created.
If both branches have diverged (meaning each has new commits the other doesn’t), Git performs a three-way merge. It compares both sets of changes against a shared ancestor, combines them, and creates a new merge commit with two parent commits.
The version control system handles most of this automatically. But when both branches modify the same lines in the same file, Git can’t decide which version to keep. That’s a merge conflict, and you fix it manually.
Stack Overflow’s developer survey found that 93% of developers use Git as their primary version control system. Merging is the most common way those developers bring parallel work together.
According to Hutte research, nearly 90% of developers have experienced merge conflicts at some point, which shows just how central the merge operation is to daily work.
How Git Merge Works Step by Step

Running git merge triggers a sequence that happens fast, but involves several distinct stages under the hood.
Step 1: Git identifies the common ancestor commit between the two branches. This is the point where they originally split.
Step 2: Git compares changes from each branch against that ancestor. It looks at what was added, modified, or deleted on each side.
Step 3: Git applies both sets of changes. If they touch different files, or different parts of the same file, the merge resolves automatically.
Step 4: A new merge commit is created. This commit has two parent commits (one from each branch), which preserves the full history of both lines of work.
Step 5: The branch pointer of your current branch moves forward to this new merge commit.
The whole process is built on Git’s three-way merge algorithm. Without the common ancestor as a reference point, Git would have no baseline for determining what actually changed on each side.
The Role of the Common Ancestor
The merge base (common ancestor) is what makes Git’s merging actually work. It gives Git a “before” snapshot to compare against.
Say you and a teammate both branch off from the same commit. You edit file A, they edit file B. When you merge, Git checks file A against the ancestor, sees your changes, and keeps them. It checks file B, sees their changes, and keeps those too.
The tricky part comes when both of you edit the same file. Git compares each version against the ancestor to figure out which parts were modified by which branch. If the edits are in different regions, Git merges them cleanly. Same region? Conflict.
A study analyzing 182,273 merge scenarios across 80 open-source projects found that the main factors leading to conflicts are branch isolation time and lack of communication between developers (Ribeiro et al. 2022). The longer your branch stays isolated from the main line, the more likely the ancestor drifts from both versions.
Fast-Forward Merge vs. Three-Way Merge

Git doesn’t always merge the same way. The method depends on whether your branches have diverged.
| Merge Type | When It Happens | Creates Merge Commit? | History Shape |
|---|---|---|---|
| Fast-forward | Target branch has no new commits | No | Linear |
| Three-way | Both branches have diverged | Yes | Branched |
| No-ff (forced) | Manually requested via –no-ff | Yes | Branched |
Fast-Forward Merge
A fast-forward happens when there’s nothing new on the target branch. Git just moves the pointer forward to the latest commit on the source branch. No merge commit. Clean, linear history.
This is what you get when you create a feature branch, make some commits, and nobody else touched main in the meantime.
Hutte’s research shows that 50% of developers use squash merging or rebasing specifically to maintain a more readable, linear history. Fast-forward merges serve a similar purpose when conditions allow them naturally.
Three-Way Merge
When both branches have new commits, Git can’t just move a pointer. It needs to compare three snapshots: the common ancestor, your branch tip, and the target branch tip.
The result is a dedicated merge commit that ties both histories together. You can see it clearly with git log --graph, where the history line splits and reconnects.
Some teams prefer this because the merge commit acts as documentation. It marks exactly when and where integration happened.
The –no-ff Flag
Even when a fast-forward is possible, you can force a merge commit with git merge --no-ff.
Why would you do this? Because it preserves the branch topology. You can look at the git log graph and clearly see where a feature branch started and ended. Without it, the feature commits just blend into the main line, and that context disappears.
Hutte data indicates 78% of organizations enforce branch protection rules, and many of those protections include requiring merge commits for audit purposes.
What Are Merge Conflicts and Why Do They Happen

A merge conflict happens when Git can’t automatically combine changes from two branches. It’s not a bug. It’s Git telling you it doesn’t want to guess.
Conflicts arise specifically when both branches modify the same lines in the same file. Or when one branch deletes a file that the other branch edited. Git marks the conflict in the file with markers like <<<<<<<, =======, and >>>>>>>, and waits for you to sort it out.
Research from Ghiotto et al. (2020) found that 8% to 21% of merge attempts in open-source projects fail because of conflicts. That percentage climbs in larger, more active projects.
According to a Stack Overflow survey, 45% of developers run into merge conflicts at least once a month, and 12% deal with them daily. So yeah, this is a regular thing.
Common conflict triggers:
- Two developers editing the same function or method
- Renaming a file on one branch while the other branch modifies it
- Large-scale code refactoring on a long-lived branch
- Formatting changes (tabs vs. spaces, line endings) conflicting with content edits
- Import statement changes in languages like Java or Python
The main culprit, though? Time. The longer a branch lives in isolation from the main codebase, the higher the chance of conflicts when you finally merge.
How to Resolve a Merge Conflict
Took me a while to get comfortable with conflict resolution when I first started. The markers look intimidating. But the process is actually straightforward once you’ve done it a few times.
Open the conflicted file. Look for the conflict markers. Everything between <<<<<<< HEAD and ======= is your current branch’s version. Everything between ======= and >>>>>>> is the incoming branch’s version.
Decide what to keep. Sometimes you want one side. Sometimes you combine both. Sometimes you rewrite the section entirely.
Remove the markers. Delete the <<<<<<<, =======, and >>>>>>> lines.
Stage and commit. Run git add on the resolved file, then git commit to complete the merge.
Tools like VS Code, IntelliJ IDEA, and git diff make this easier with visual side-by-side comparisons. The built-in git mergetool command opens a graphical conflict resolution interface if you’ve configured one (KDiff3, Beyond Compare, and SourceTree are popular picks).
A 2024 study from ASE evaluated multiple merge tools and found that no single tool resolves all conflict types correctly. KDiff3 showed the best applicability across diverse scenarios, but manual review is still needed for correctness (Schesch et al. 2024).
Git Merge vs. Git Rebase

This is the comparison that sparks the most debate in any team chat. Both commands integrate changes from one branch into another, but they do it differently.
Git rebase takes your commits and replays them on top of the target branch, rewriting history into a straight line. Git merge preserves both branch histories and ties them together with a merge commit.
| Feature | Git Merge | Git Rebase |
|---|---|---|
| History | Preserves full branching topology | Creates linear history |
| Commit hashes | Original hashes stay intact | Rewrites commit hashes |
| Merge commit | Yes (in three-way merges) | No |
| Safe for shared branches? | Yes | No (rewrites history) |
| Conflict resolution | Once, at merge time | Per replayed commit |
The practical split I see most teams follow: rebase for cleaning up local feature branch history before integration. Merge for actually bringing that work into shared branches like main or develop.
Hutte data shows that after training, 60% of developers found rebasing became a strong part of their workflow. But the other 40% stuck primarily with merge, and that’s fine. The real danger is rebasing a branch that others are already working from. Rewritten hashes cause chaos in a shared context.
Netflix, Google, and Microsoft practice trunk-based development where developers make frequent, small commits to main. In that model, short-lived branches get merged (or squash-merged) quickly, and the merge-vs-rebase debate matters less because branches rarely live long enough for it to make a difference.
The “Accelerate” research from the DORA team confirmed that trunk-based development with frequent integration leads to higher software delivery performance, regardless of whether teams use merge or rebase for the actual integration step.
Git Merge Strategies and Options

Git doesn’t just have one way to merge. It supports several merge strategies, and the one it picks depends on the situation.
Default Strategy: Recursive (ORT)
The default strategy for two-branch merges has been “recursive” for years. In Git 2.33 and later, it was replaced by “ort” (Ostensibly Recursive’s Twin), which handles the same cases but runs faster.
Both work the same way from a user perspective. They find the common ancestor, do a three-way comparison, and produce a merged result. The ort strategy just does it with less memory usage and better performance on large repositories.
The Linux kernel project, one of the longest-running Git repositories, recorded 75,314 commits in 2024 alone, with over 2,000 active contributors per release cycle (Command Linux). At that scale, merge strategy performance matters.
Squash Merge
Running git merge --squash combines all the commits from the source branch into a single set of changes, stages them, but doesn’t create a merge commit. You then commit manually.
The result: one clean commit on the target branch instead of the full branch history. This is popular for feature branches where the individual commits (like “WIP”, “fix typo”, “actually fix it this time”) don’t add value to the main line.
GitHub pull requests offer squash merge as a default option, and many teams configure their repos to only allow it. It keeps the main branch history readable without requiring developers to manually clean up their feature branch commits.
Other Strategies
Octopus: Merges more than two branches simultaneously. Git uses this automatically when you pass multiple branch names to git merge. It won’t handle conflicts, though. If any conflict arises, it bails out.
Ours: Keeps your current branch’s version for everything. The incoming branch’s changes are recorded in history but not actually applied. Useful for marking a branch as merged without taking its code.
–abort: Not a strategy, but worth knowing. Running git merge --abort cancels a merge in progress and returns your working directory to the state before you started. Useful when a conflict is messier than expected and you want to regroup.
Teams working across a complex software development process with multiple release tracks sometimes combine these strategies. A hotfix branch might get merged with the default ort strategy into main, then merged via --ours into a legacy release branch where the fix doesn’t apply.
Common Git Merge Commands and Syntax
The basic syntax is git merge [branch-name]. You run it from the branch you want to merge into, not from the branch you’re merging.
That trips people up more often than you’d think. If you want to merge a feature branch into main, you switch to main first, then run the merge command targeting your feature branch.
| Command | What It Does | When to Use |
|---|---|---|
| git merge feature | Merges “feature” into current branch | Standard branch integration |
| git merge –no-ff feature | Forces a merge commit | Preserving branch history |
| git merge –squash feature | Combines all commits into one | Clean single-commit merges |
| git merge –abort | Cancels merge in progress | Backing out of messy conflicts |
| git merge origin/main | Merges remote tracking branch | Syncing with remote repository |
Checking Merge Results
After merging, run git log --graph --oneline to see how the commit history looks. The graph view shows the merge point and both parent branches visually in your terminal.
Git status is your go-to during any merge. It tells you if there are unresolved conflicts, which files need attention, and whether the merge is complete.
For a more detailed look at what actually changed, git diff HEAD~1 compares the merge commit against its first parent. That shows you exactly what the merge brought in.
Merging Remote Branches
GitHub hosts over 420 million repositories, and most teams work with remote branches daily (GitHub About page, 2025).
Before merging a remote branch, always run git fetch first. This updates your local tracking references without changing your working directory. Then git merge origin/main brings those fetched changes into your current branch.
The shortcut? git pull. It combines fetch and merge into one step. But if you want more control over what happens (especially around conflict handling), keeping them separate is the safer habit. Many developers prefer running fetch manually for exactly this reason.
When to Use Git Merge in a Team Workflow

Git merge isn’t something you do in isolation. It fits into a broader workflow, and the way your team uses it depends on the branching strategy, the build pipeline, and how often you deploy.
The State of DevOps report found that high-performing teams deploy 208 times more often than low performers, with a lead time that’s 106 times faster. Merging is one of the gateways in that pipeline.
Feature Branch Merges
The most common pattern: a developer creates a branch from main, builds a feature, then merges it back when finished.
On GitHub and GitLab, this happens through pull requests and merge requests. The merge itself is often the final step after the code review process passes and CI checks run green.
Hutte research shows 75% of developers find that peer programming or code review catches Git issues early, before the merge ever happens.
Branching Strategies That Rely on Merge
Git Flow: Uses dedicated develop, release, and hotfix branches. Every branch eventually merges back into main and develop. Best for teams shipping versioned software with scheduled releases.
GitHub Flow: Simpler. Just main and feature branches. You merge feature branches directly into main through pull requests. Works well for web apps and teams that deploy multiple times per day.
Trunk-based development: Developers merge very small changes into main frequently, sometimes multiple times daily. Microsoft, Netflix, and Google use this approach.
CI/CD and Merge Events
ElectroIQ data shows GitHub Actions runs over 5 million workflows daily, and continuous deployment through Actions has increased by 50%.
Most of those workflows trigger on merge events. When a pull request gets merged into main, the CI pipeline runs tests, builds the application, and pushes it toward production. The merge commit acts as the trigger point in the continuous integration chain.
Uber built a custom system called MergeQueue that handles hundreds of changes per hour across monorepos. It reduced CI resource usage by 53% and P95 waiting times by 37% through speculative validation and conflict prediction (Git Merge Conference 2025).
Mistakes to Avoid When Using Git Merge
Merge mistakes are annoying, and some are genuinely destructive. I’ve seen entire teams grind to a halt because someone force-pushed after a bad merge on a shared branch.
Most of these are preventable. You just have to know what to watch for.
Merging Without Pulling First
This is the most common one. You’re working on main, someone else pushed changes, and you try to merge a feature branch without pulling the latest remote state.
The result: your local main is behind origin. The merge goes through locally, but your push gets rejected because the remote branch has commits you don’t have.
Fix it: always run git pull (or git fetch + git merge origin/main) before merging anything into main. Make it muscle memory.
Letting Feature Branches Live Too Long
Research from Ribeiro et al. found that the main factor leading to merge conflicts is how long a branch stays isolated. The longer the gap between branching and merging, the more the main branch drifts from your branch.
Short-lived branches (merged within a day or two) rarely cause problems. Branches that sit for weeks? That’s where the painful conflicts stack up. Atlassian’s documentation points out that short-lived task branches paired with continuous deployment make “merge hell” a thing of the past.
Force-Pushing After a Merge on Shared Branches
Don’t do this. Running git push --force after a merge overwrites the remote branch with your local version. Anyone who pulled the old version now has a broken reference.
Hutte data shows 78% of organizations enforce branch protection rules to prevent exactly this. If your team hasn’t set up branch protections yet, do it now. GitHub, GitLab, and Bitbucket all support them.
If you absolutely must force-push (on your own feature branch only), use git push --force-with-lease instead. It checks whether the remote branch has new commits before overwriting, which at least prevents you from accidentally erasing someone else’s work.
Forgetting Conflict Markers in Committed Code
This happens more than anyone wants to admit. You resolve a conflict, stage the file, commit, but accidentally leave a <<<<<<< or ======= marker in the code.
The commit goes through just fine. Git doesn’t check for leftover markers. Your build might catch it, or it might not. A teammate finds it later and wonders what happened.
Prevention: use pre-commit hooks or linting tools that flag conflict markers before a commit is allowed. Hutte data shows 55% of developers use pre-commit hooks to catch exactly this kind of mistake.
Merging Into the Wrong Branch
Sounds silly until it happens to you. You think you’re on your feature branch, but you’re actually on develop. You run git merge, and now develop has changes that shouldn’t be there yet.
If you catch it before pushing, git merge --abort (during the merge) or git reset (after committing) can undo it. If you already pushed, you’ll need git revert to create a new commit that undoes the merge without rewriting history.
Hutte findings show 85% of developers rely on Git documentation or online resources to recover from these situations. The full list of Git commands helps, but honestly, keeping git status and git log in your habits prevents most wrong-branch merges before they happen.
FAQ on What Does Git Merge Do
What does git merge actually do?
Git merge combines changes from one branch into another. It finds the common ancestor between both branches, compares the differences, and integrates them into a single branch with a unified commit hash history.
Does git merge delete the source branch?
No. After merging, the source branch still exists. You need to manually delete the branch with git branch -d if you no longer need it. Most teams clean up merged branches to keep the repository tidy.
What is the difference between git merge and git pull?
Git pull runs two commands in sequence: git fetch followed by git merge. So git pull includes a merge. Running them separately gives you more control over when integration happens.
How do I know if a merge conflict occurred?
Git prints a CONFLICT message in the terminal and marks affected files. Running git status shows all unmerged files. Open them, look for conflict markers, resolve the differences, then stage and commit.
Can I undo a git merge?
Yes. If the merge isn’t pushed yet, git reset --hard HEAD~1 removes the merge commit. If already pushed, use git revert -m 1 to create a new commit that reverses the merge without rewriting shared history.
What is a fast-forward merge?
A fast-forward merge happens when the target branch has no new commits since the source branched off. Git simply moves the branch pointer forward. No merge commit is created, keeping history linear.
When should I use git merge vs git rebase?
Use merge for integrating work into shared branches like main. Use rebase for cleaning up local feature branch history before merging. Never rebase branches that other developers are actively working from.
Does git merge affect the remote repository?
Not directly. Git merge changes your local branch only. You need to push the changes afterward with git push for the merge to appear on the remote repository.
What does git merge –squash do?
Git squash merging takes all commits from the source branch and combines them into a single staged change. You then commit manually. It keeps the target branch history clean without individual feature commits.
How do I merge a specific branch in Git?
First, check out the branch you want to merge into. Then run git merge branch-name. The changes from that specific branch get integrated into your current working branch.
Conclusion
Knowing what does git merge do is one of those things that separates developers who use Git from developers who actually understand it. The command looks simple on the surface, but the behavior changes depending on branch state, merge strategy, and how your team handles conflict resolution.
Whether you’re running a fast-forward merge on a solo project or resolving a three-way merge across a busy repository, the fundamentals stay the same. Git finds a common ancestor, compares both branches, and combines the results.
Pick the right workflow for your team. Keep branches short-lived. Pull before you merge. Set up branch protection rules.
The developers who merge confidently are the ones who understand what’s happening at each step, not just the ones who memorized the syntax for merging two branches. Build that understanding, and version control stops being a source of frustration.
- Google Play Store Not Working: How to Fix It - July 22, 2026
- How to Make a Repository Private in GitHub - July 20, 2026
- How to Set Up Google Play Family Library - July 18, 2026



