Git Pull and Merge: Update a Branch, Merge a GitHub PR
Git pull and merge are one command in two steps: git pull runs git fetch to download new commits from the remote, then git merge (or git rebase, if you configure it) to bring them into your current branch. A pull request (PR) is something else. It’s GitHub’s page for proposing that one branch be merged into another, with review and automated checks first. Once it’s approved, you merge it with one of three methods: a merge commit, squash and merge, or rebase and merge.
We ran the pull, merge, rebase, revert and branch commands below on Git 2.50.1 in November 2026, and the test caught a mistake in an earlier version of this post, about what git branch -d does after a squash merge. The commands are for developers who share a GitHub repository and merge through PRs. If you only commit to your own repository, pulling and pushing are all you need, and on GitLab or Bitbucket the Git commands still apply but the PR steps don’t.
Git pull vs a pull request

git pull runs two commands:
git fetchdownloads new commits, branches and tags from the remote. It doesn’t touch your working files; it only updates remote-tracking branches such asorigin/main.git mergethen merges those changes into the branch you have checked out.
A PR happens on GitHub instead of on your machine. Both end in a merge, but the PR puts review and checks in front of it.
| Workflow | Use it to | Best for |
|---|---|---|
git pull |
Bring your local branch up to date with its remote branch. | Updating main on your machine before you start work. |
| Pull request | Propose changes to a shared branch and get them reviewed. | Any change to a branch your team shares, and open-source contributions. |
Use git pull to update main, and a PR to get your feature into it.
git merge on its own only joins branches you already have locally, while a pull downloads from the remote first. Pull when the new commits are on GitHub, and merge when they are already on your machine.
What each command changes
| Command | Contacts the remote? | Changes your files? | What happens to the history? |
|---|---|---|---|
git fetch |
Yes | No | Nothing on your branch. Only remote-tracking branches such as origin/main move. |
git merge origin/main |
No | Yes | Fast-forwards if it can, otherwise adds a merge commit. |
git pull with no default set |
Yes | Yes | Fast-forwards if it can, otherwise stops and asks you to choose. |
git pull --no-rebase |
Yes | Yes | Fast-forwards if it can, otherwise adds a merge commit. |
git pull --rebase |
Yes | Yes | Replays your local commits on top, with new hashes. |
git pull --ff-only |
Yes | Yes | Fast-forwards if it can, otherwise stops with an error. |
Pull request vs merge request
They are the same idea under two names. GitHub calls it a pull request and GitLab calls it a merge request, and either way it’s a place to review and discuss a change before it merges. This guide uses GitHub’s term.
Keeping your local branch in sync

A pull fetches and merges in one step, so you can hit conflicts or a surprise merge commit before you’ve seen what changed. Splitting it into two steps lets you look first.
Fetch first, then merge
git fetch origin
# Commits on the remote that you don't have yet
git log main..origin/main
# Then either merge them...
git merge origin/main
# ...or replay your local commits on top of them
git rebase origin/main
git merge origin/mainties the two histories together with a merge commit, unless it can fast-forward. Nothing is rewritten.git rebase origin/mainsets your local commits aside, moves your branch toorigin/main, and replays your commits on top. History stays linear, but your commits get new hashes, so don’t rebase commits you have already pushed to a branch others use.
Pull with rebase
git pull --rebase fetches and then rebases your local commits instead of merging, so your log doesn’t fill with “Merge branch ‘main’ of …” commits. To make it the default:
git config --global pull.rebase true
If you haven’t set a default and both your branch and the remote have new commits, recent versions of Git stop with “Need to specify how to reconcile divergent branches.” You then pick one of three settings: pull.rebase false to merge, pull.rebase true to rebase, or pull.ff only to fast-forward and fail otherwise.
The pull request process
In this three-minute video, Keep On Coding forks a repository, clones it, commits a change on a new branch, pushes the branch and opens a PR, then approves and merges it as the repository owner. On a team repository you skip the fork and push the branch to the repository itself.
The GitHub pull request workflow has four steps: create a branch, push it, open the PR, and merge it after review. Teammates read your change and CI runs against it before anything reaches the shared branch. You can open the PR on GitHub or with the GitHub CLI:
git switch -c fix-login-error
# ...edit and commit...
git push -u origin fix-login-error
gh pr create --base main --title "Fix login failure on invalid password"
To update an open PR, push new commits to the same branch. They show up on it with no extra step.
Writing a PR reviewers can approve
A reviewer who can’t tell what a PR does will leave it waiting, so give them four things. Start with a specific title, such as “Fix login failure on invalid password” instead of “Fix bug”. Say what problem the change solves and link the issue or ticket. Describe the approach in a sentence or two. Then list the steps a reviewer can follow to check it.
Keep PRs small. IonWarp, our sister product, is an AI code reviewer, and across the 1,232 PRs it reviewed in our own repos it put a should-fix flag on 11% of those under 100 changed lines and 57% of those with 1,000 to 2,999 (our write-up). We’re one small team, so treat that as a data point and not a benchmark. We’d rank small, reviewed PRs with short iterations and CI/CD among the SDLC best practices that pay off most. There’s more on reviews in code review good practices.
Cleaning up commit history
Before you ask for review, you can turn “WIP” and “fix typo” commits into a few meaningful ones with an interactive rebase, git rebase -i origin/main. It lets you squash related commits into one, reword commit messages, and reorder commits so they tell the story of the change.
If your team uses squash and merge, this matters less, because the PR becomes a single commit on main anyway.
Before you merge
- Your branch is up to date with the base branch, and any conflicts are resolved.
- All required checks are green.
- The title and description still describe what the PR does.
- You have the approvals your team requires.
Choosing a merge method on GitHub
GitHub offers three ways to merge a pull request, and each leaves a different history on main:
| Merge method | History on main |
Keeps | Best for |
|---|---|---|---|
| Create a merge commit | Non-linear, with one merge commit per PR. | Every commit from the branch, unchanged. | Large features where the individual commits are a useful record. |
| Squash and merge | Linear, with each PR as one commit. | The PR as one change. The individual commits stay visible on the PR page. | Most feature branches, where “WIP” commits add nothing to main. |
| Rebase and merge | Linear, with each commit replayed onto main. |
Every commit, but rewritten with new hashes. | Teams that want a linear history and each commit kept. |
We’d default to squash and merge, because main gets one clean commit per PR. Teams that need the full branch history, for audits say, use merge commits. Whichever you pick, stick to it.
Merging from the command line
The GitHub CLI merges with the same three methods:
gh pr merge 123 --merge # create a merge commit
gh pr merge 123 --squash # squash and merge
gh pr merge 123 --rebase # rebase and merge
Add --delete-branch to delete the local and remote branch after the merge, or --auto to merge automatically once the required checks pass.
Git knows nothing about PRs, which live on GitHub, so gh is the usual way from a terminal. To try one on your machine first, run gh pr checkout 123, or fetch it with plain Git:
git fetch origin pull/123/head:pr-123
git switch pr-123
Scripts can merge through the REST API with PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge, setting merge_method to merge, squash or rebase (GitHub docs).
Setting the allowed merge methods
Choose which methods a repository allows in Settings › General › Pull Requests, where you check or uncheck Allow merge commits, Allow squash merging and Allow rebase merging. To limit the methods on one branch, use a ruleset, which can require particular merge methods. The Require linear history rule, also available in branch protection, blocks merge commits.
Merge trains on GitHub
Two PRs can each pass their checks and still break main once both land. GitHub’s merge queue stops that, and it does the same job as GitLab’s merge trains.
An admin turns on Require merge queue in the branch protection rule. Each queued PR is combined with the latest base branch and the PRs ahead of it, and GitHub merges it once the required checks pass on that combination. If they fail, the PR leaves the queue.
To queue a PR, click Merge when ready or run gh pr merge. GitHub Actions workflows must also trigger on the merge_group event, or the required check is never reported and the merge fails. Merge queues are available on public repositories owned by an organization, and on private organization repositories on GitHub Enterprise Cloud.
Resolving merge conflicts
A conflict happens when two branches change the same lines differently. Git can’t choose, so it stops the merge and marks the conflicting files for you to fix.
Reading conflict markers
<<<<<<< HEAD
your version of the lines
=======
the incoming version of the lines
>>>>>>> feature-branch
<<<<<<< HEADstarts your current branch’s version.=======separates the two versions.>>>>>>> feature-branchends the incoming branch’s version.
Edit the block so it contains only the code you want (yours, theirs, or a combination), and delete all three markers. Then stage the file and finish the merge:
git add path/to/file
git commit
Resolving conflicts in VS Code
VS Code highlights each conflict and puts actions above it:
- Accept Current Change keeps your version.
- Accept Incoming Change keeps the other branch’s version.
- Accept Both Changes keeps both, one after the other. Check the result, because it can duplicate or break logic.
- Compare Changes opens a side-by-side diff.
Save the file, then git add and git commit as above.
Resolving conflicts on GitHub
For simple conflicts, where both branches changed the same lines, GitHub has a web conflict editor. On the PR, click Resolve conflicts, edit the markers, click Mark as resolved for each file, then Commit merge. This merges the whole base branch into your branch. Other conflicts, such as a file one branch deleted and the other edited, have to be resolved locally.
You’ll get fewer of them if you sync with main often and keep PRs small, because fewer lines overlap.
Delete the branch after the merge
Once a PR is merged, delete its branch so stale branches don’t pile up. On your machine, that looks like this:
git switch main
git pull
git branch -d fix-login-error
git branch -d deletes a branch only if it’s fully merged into its upstream, or into the branch you’re on when it has no upstream. A squash or rebase merge never puts your local commits on main with the same hashes, so the result depends on whether the upstream still exists. In our test on Git 2.50.1, after a squash merge, -d deleted the branch with a warning while origin/fix-login-error was still there, and refused once the remote branch was deleted and pruned. If it refuses, check that the PR really merged, then force it with git branch -D fix-login-error.
To delete the branch on GitHub too:
git push origin --delete fix-login-error
Other people’s clones keep a stale origin/fix-login-error until they run git fetch --prune.
To skip that step, turn on Automatically delete head branches on the same settings page as the merge methods, and GitHub deletes the branch when its PR merges. gh pr merge --delete-branch does both sides in one command.
Frequently asked questions
What’s the difference between git pull and git fetch?
git fetch downloads new commits from the remote and updates remote-tracking branches such as origin/main, without touching your files. git pull runs that fetch and then merges (or rebases) those commits into your current branch. Fetch first when you want to see what changed before you integrate it.
How do I undo a merged pull request?
On GitHub, click Revert on the merged PR, and GitHub opens a new one that undoes it. From the command line, run git revert -m 1 <merge-commit-hash> and push; -m 1 keeps the first parent, the base branch, as the mainline. After a squash merge there’s one ordinary commit, so git revert <hash> is enough, and after a rebase merge you revert each commit. Don’t use git reset on a shared branch, because it rewrites history your teammates already have.
Can I merge a pull request with conflicts on GitHub?
No. GitHub disables the merge button until the conflicts are resolved. Fix simple ones in GitHub’s conflict editor (Resolve conflicts), or merge the base branch into your branch locally, resolve them, commit and push. The PR updates on its own.
Which merge method should I use?
Squash and merge suits most feature branches, because main gets one clean commit per PR. Use a merge commit when you need every commit of the branch kept as it was, and rebase and merge when you want a linear history that still keeps each commit. Limit the allowed methods in your repository settings so everyone uses the same one.
What’s the difference between git pull and git merge?
git merge joins a branch you already have locally into your current branch and doesn’t contact the remote. git pull downloads new commits from the remote first and then merges or rebases them, so use it when the new commits are on GitHub.
What’s the difference between git merge and a pull request?
git merge is a command that joins two branches on your machine. A PR is a page on GitHub that proposes a merge and collects review and checks before it happens. When you merge it, GitHub does the merge for you.
How do I use git pull with a merge?
Run git pull --no-rebase, or set git config --global pull.rebase false to make it the default. Git then adds a merge commit when both sides have new commits, and fast-forwards when only the remote does.
Do I pull or fetch first?
You don’t need to fetch before you pull, because a pull does the fetch for you. Fetch on its own when you want to look at what changed before bringing it in, then run git log main..origin/main to see those commits.
How do I merge a pull request after it’s approved?
On the PR page, pick a merge method from the merge button and confirm it, or run gh pr merge 123 --squash in a terminal. You need write access to the repository, and any required reviews and status checks must have passed.
Does a pull request merge automatically?
No. Someone has to merge it unless auto-merge is on. When auto-merge is enabled for the repository, anyone with write access can turn it on for a PR, or run gh pr merge 123 --auto, and GitHub merges it once the required reviews and checks pass.
Who should merge a pull request?
Anyone with write access can, so it’s a team decision. We’d have the author merge after approval, because the author knows whether the change is ready to ship and will be watching it once it lands.
How do I check if a pull request is merged?
The PR page shows Merged at the top. In a terminal, gh pr view 123 --json state,mergedAt prints the state (MERGED, OPEN or CLOSED) and the time it merged.
How do I merge two pull requests into one?
A PR tracks one branch, so combine the branches. Merge one branch into the other with git merge, push it, and close the PR you no longer need.
Should I cherry-pick or merge?
Merge when you want everything on a branch. Cherry-pick when you want one commit from it, such as a fix you need on a release branch, because git cherry-pick copies that commit under a new hash and leaves the rest behind.
How do I cancel a merge that has conflicts?
Run git merge --abort, and Git puts your branch back the way it was before the merge. If you had uncommitted changes when the merge started, it may not be able to restore them, so commit or stash your work first.
What does git pull --allow-unrelated-histories do?
It lets Git merge two histories that share no commit, which it refuses by default with “fatal: refusing to merge unrelated histories”. You usually see that error after running git init locally and creating a repository with a README on GitHub. Check that you’re pulling from the repository you meant to before you pass the flag.
Zest is AI coding analytics for engineering teams: it shows which coding agents, models and skills each engineer uses, what they cost, and which sessions end in merged pull requests. See how Zest works.