Git and GitHub course menu
git clone, fetch and pull: Staying in Sync with GitHub
Copy a repository with git clone, download changes with git fetch, update your branch with git pull, understand the difference between fetch and pull, and fix rejected pushes.
On this page
In this lesson, two people work on the same GitHub repository. To show both sides, we use two folders: asha and ravi.
git clone#
git clone downloads a repository with its full history, and sets up origin for you:
git clone https://github.com/your-name/notes.git asha
git clone https://github.com/your-name/notes.git raviCloning into 'asha'...
Cloning into 'ravi'...The last word is the folder name. Without it, Git uses the repository's name, notes.
cd asha
git log --oneline
git remote -v3b1b8d5 Add shopping note
origin https://github.com/your-name/notes.git (fetch)
origin https://github.com/your-name/notes.git (push)Get a teammate's work#
Ravi commits and pushes. git -C ravi runs the command in the ravi folder, so that we can stay in asha:
git -C ../ravi commit -q --allow-empty -m "Ravi: plan the week"
git -C ../ravi push -q
git statusOn branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree cleanAsha's Git says it is up to date, because origin/main is only updated when you talk to GitHub. It does not check by itself.
git fetch#
git fetch downloads new commits and updates origin/main, but it leaves your branch and files alone. It is always safe.
git fetch
git statusFrom https://github.com/your-name/notes.git
3b1b8d5..c2501d1 main -> origin/main
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree cleanNow you can look at the changes before accepting them:
git log --oneline main..origin/mainc2501d1 Ravi: plan the weekgit pull#
git pull is a git fetch followed by a merge of origin/main into your branch:
git pull
git log --onelineUpdating 3b1b8d5..c2501d1
Fast-forward
c2501d1 Ravi: plan the week
3b1b8d5 Add shopping noteWhen a push is rejected#
If someone pushed while you were working, GitHub refuses your push, so that their work is not overwritten:
echo "Pay rent" >> notes.txt
git commit -q -am "Asha: add rent"
echo "Water plants" > ../ravi/plants.txt
git -C ../ravi add .
git -C ../ravi commit -q -m "Ravi: add plants"
git -C ../ravi push -q
git pushTo https://github.com/your-name/notes.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/your-name/notes.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.Get their work first. Both of you have new commits now, so the branches have diverged, and Git wants you to say how to combine them:
git pullFrom https://github.com/your-name/notes.git
c2501d1..8d22c68 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.There are two choices: merge, or rebase. For now, merge. --no-edit accepts the default message for the merge commit:
git pull --no-rebase --no-edit
git push
git log --oneline --graphMerge made by the 'ort' strategy.
plants.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 plants.txt
To https://github.com/your-name/notes.git
8d22c68..3847148 main -> main
* 3847148 Merge branch 'main' of https://github.com/your-name/notes.git
|\
| * 8d22c68 Ravi: add plants
* | 948566d Asha: add rent
|/
* c2501d1 Ravi: plan the week
* 3b1b8d5 Add shopping noteTo set your choice once, so that plain git pull always works, run git config --global pull.rebase false. If both of you had changed the same lines, you would resolve a conflict at this point.
Pull with rebase#
The merge commit above adds nothing useful to the history. Many teams prefer the other choice, which replays their local commits on top of the new remote commits and keeps history in a straight line:
git pull --rebaseTo make this your default:
git config --global pull.rebase trueYou will learn how this works in the rebase lesson.
Remove deleted remote branches#
When a branch is deleted on GitHub, your origin/ copy remains. Clean up with:
git fetch --pruneCommon mistakes#
Practice#
Practice exercise
Ravi adds a commit and pushes it. From the asha folder, download it without changing the branch, and print how many commits it is behind with git rev-list --count main..origin/main. Then pull.
Show solution
git -C ../ravi commit -q --allow-empty -m "Ravi: update plan"
git -C ../ravi push -q
git fetch -q
git rev-list --count main..origin/main
git pull -q
git log -n 1 --format=%s1
Ravi: update planKey takeaway#
Finished this lesson?