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.