Fetching and Pulling
To get other people's commits from a remote you have two commands. git fetch downloads new commits but doesn't change your branches, so you can look before you combine. git pull fetches and then immediately merges (or rebases) the changes into your current branch.
git fetch
Alex has pushed two commits. Sam's local repository doesn't know yet — git status only compares with what Sam last downloaded:
git status
On branch main Your branch is up to date with 'origin/main'. nothing to commit, working tree clean
git fetch
remote: Enumerating objects: 7, done. remote: Counting objects: 100% (7/7), done. remote: Compressing objects: 100% (4/4), done. remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (6/6), 564 bytes | 282.00 KiB/s, done. From https://github.com/sam-rivera/recipes 6b13d64..de456d3 main -> origin/main
git status
On branch main Your branch is behind 'origin/main' by 2 commits, and can be fast-forwarded. (use "git pull" to update your local branch) nothing to commit, working tree clean
Fetching updated origin/main, Sam's local record of the server's main. Sam's own main and working files haven't changed. Now Sam can see exactly what arrived:
git log --oneline main..origin/main
de456d3 (origin/main) Add cinnamon to porridge 8b0160c Add porridge recipe
git diff main origin/main --stat
porridge.txt | 1 + 1 file changed, 1 insertion(+)
Fetching is always safe — it never touches your branches or files — so you can run it whenever you like. git fetch --all fetches from every remote.
Bringing the changes in
After fetching, integrate the remote commits into your branch with a merge (or a rebase):
git merge origin/main
Updating 6b13d64..de456d3 Fast-forward porridge.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 porridge.txt
Because Sam had no new local commits, this was a fast-forward.
git pull = fetch + merge
git pull does both steps in one command, and it's what you'll normally use:
git pull
remote: Enumerating objects: 4, done. remote: Counting objects: 100% (4/4), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), 312 bytes | 312.00 KiB/s, done. From https://github.com/sam-rivera/recipes de456d3..6fc79e0 main -> origin/main Updating de456d3..6fc79e0 Fast-forward granola.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 granola.txt
When both sides have new commits
If you've committed locally and the remote has new commits, the branches have diverged. A fast-forward is impossible, and Git needs to know whether to merge or rebase. Without a setting, recent versions of Git stop and ask you to choose:
echo "Pancakes: flour, milk, eggs, sugar" > pancakes.txt git commit --quiet -am "Add sugar to pancakes" git pull
remote: Enumerating objects: 4, done. remote: Counting objects: 100% (4/4), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), 282 bytes | 282.00 KiB/s, done. From https://github.com/sam-rivera/recipes 6fc79e0..604368d main -> origin/main hint: You have divergent branches and need to specify how to reconcile them. hint: You can do so by running one of the following commands sometime before hint: your next pull: hint: hint: git config pull.rebase false # merge hint: git config pull.rebase true # rebase hint: git config pull.ff only # fast-forward only hint: hint: You can replace "git config" with "git config --global" to set a default hint: preference for all repositories. You can also pass --rebase, --no-rebase, hint: or --ff-only on the command line to override the configured default per hint: invocation. fatal: Need to specify how to reconcile divergent branches.
The three choices:
| Setting | Divergent pull does | History |
|---|---|---|
pull.rebase false | Merge — creates a merge commit | Shows parallel work, adds "Merge branch 'main' of …" commits |
pull.rebase true | Rebase your local commits on top of the remote's | Straight line; popular for day-to-day pulling |
pull.ff only | Refuse; you decide each time | Nothing happens until you merge or rebase yourself |
Set your preference once (many developers choose rebase), or decide per pull with --rebase / --no-rebase:
git config --global pull.rebase true git pull
Successfully rebased and updated refs/heads/main.
git log --oneline --graph
* 4193a2e (HEAD -> main) Add sugar to pancakes * 604368d (origin/main) Add shakshuka recipe * 6fc79e0 Add granola recipe * de456d3 Add cinnamon to porridge * 8b0160c Add porridge recipe * 6b13d64 Add pancake recipe
Sam's commit was replayed on top of Alex's, and the history stays linear. Sam can now push.
Conflicts while pulling
A pull can hit a merge conflict like any merge or rebase. Resolve it the same way (lesson 25) and finish with git commit for a merge, or git rebase --continue for a rebase. git merge --abort or git rebase --abort backs out.
Pull before you start
A simple habit avoids most trouble: git pull before you begin work and before you push. Pulling with uncommitted changes in files that the incoming commits also changed is refused — commit or stash first. To pull with uncommitted changes in other files, add --autostash, which stashes them, pulls, and restores them.
Try it yourself
Clone the same repository into two folders to act as two people. Commit and push from one; in the other, use git fetch and git log main..origin/main to inspect the new commit before merging it. Then create a divergence and practise git pull --rebase.