git pull
Fetch changes from a remote repository and merge them into your current branch in one command.
Your teammate just merged their pull request into main, and you need those
changes in your local repository. Or you're working on a feature branch and want
to incorporate the latest updates from main. git pull fetches changes from the
remote repository and merges them into your current branch, keeping your local
code in sync with what's on the server.
Running git pull is actually a combination of two commands: git fetch (which
downloads commits from the remote) and git merge (which integrates those
commits into your current branch). When you're on main and run git pull, Git
downloads any new commits from origin/main and merges them into your local
main branch. If there are no conflicts, the merge happens automatically and your
working directory updates to include the new changes.
The default behavior merges changes, which creates a merge commit if your local branch has diverged from the remote. If both you and a teammate have made commits, pulling creates a commit that ties both histories together. Some developers find these merge commits cluttering, especially for simple cases where they just want to get the latest code. That's where pull options come in handy.
Rebase Instead of Merge
Running git pull --rebase changes the behavior to rebase your local commits on
top of the incoming changes instead of merging. If you've made two commits
locally and someone else pushed three commits, rebase replays your two commits
as if you made them after their three. This creates a linear history without
merge commits, which many teams prefer for cleaner logs. The downside is that
rebasing rewrites your local commits, giving them new identifiers, which can
cause problems if you've already pushed those commits and someone else has based
work on them.
Many developers configure Git to always rebase when pulling with
git config pull.rebase true. This makes git pull behave like
git pull --rebase by default, keeping their history linear without thinking
about it. If you work on a team that values clean history, this configuration is
common.
Handling Conflicts
When pulling results in conflicts—cases where you and someone else changed the
same lines of code—Git stops and asks you to resolve them manually. You'll see
files marked with conflict markers (<<<<<<<, =======, >>>>>>>), showing
both versions of the conflicting changes. You edit the files to keep what you
want, remove the markers, stage the resolved files with git add, and complete
the merge with git commit. If you pulled with --rebase, you'd use
git rebase --continue instead after staging the fixed files.
If conflicts feel overwhelming or you realize you pulled at a bad time,
git merge --abort (or git rebase --abort if rebasing) cancels the pull and
returns your branch to its state before you started. This lets you clean up your
working directory or commit your current work before trying to pull again.
Pull Request Workflows
In pull request workflows, pulling happens in a couple of contexts. First, you
regularly pull main to keep your feature branch up to date. You might switch to
main with git checkout main, pull the latest with git pull, then switch back
to your feature branch and merge or rebase main into it. This ensures your PR
will merge cleanly when approved.
Second, you pull your own feature branch when working across multiple machines or when other contributors have pushed commits to your PR branch. If you push commits from your laptop, then later want to continue work on your desktop, you pull the feature branch to download those commits. Some teams also push commits directly to each other's PR branches when pair programming or helping fix issues.
Fast-Forward and Behavior Modes
When your local branch hasn't diverged from the remote—you haven't made any local commits—pulling can "fast-forward" instead of merging. This just moves your branch pointer forward to match the remote without creating a merge commit. It's the simplest case and happens often when you're just staying up to date with main.
Git has three modes for handling divergent histories when pulling: merge (create
a merge commit), rebase (replay your commits), and fast-forward only (fail if
fast-forward isn't possible). You can set the default behavior with
configuration or specify it per-pull with flags like --ff-only, which prevents
accidental merges by only allowing pulls that can fast-forward.
Pull Specific Branches
While git pull pulls the current branch's upstream by default, you can pull
other branches with git pull origin branch-name. This fetches and merges that
specific branch into your current branch, which is useful when you want to
incorporate changes from a teammate's feature branch directly without switching
to it first.
Understanding pull means understanding that it's your primary way of getting other people's work onto your machine. Pull keeps you synced with the team, ensures you're building on the latest code, and helps prevent the drift that leads to painful merge conflicts later. The key decision is whether to merge or rebase when pulling—both work, but your team's conventions and the state of your local commits should guide which approach you use.
