Lesson 4 of 5 in Remotes & Collaboration
A teammate got there first
Story: Someone else has been writing in the archive while you worked. Don't write over them.
You've committed on main, and you run git push. But while you were working, a teammate pushed to main on origin too. Your push is refused:
To https://git.example/team/project.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://git.example/team/project.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.
Nothing has changed, on origin or in your repository. You haven't done anything wrong: git is protecting your teammate's work.
Why git refuses
origin only accepts a push that moves its branch forward. Your main must contain every commit that main on origin already has, and yours doesn't: it has your new commit, but not theirs. If origin took your push, its main would move to your commit, and their commit would be left on no branch at all. Their work would be gone from the shared history.
So before you push, bring their commit into your main.
Pull, then push again
git pull
git push
git pull fetches their commit and merges it into your main, with a merge commit whose parents are your commit and theirs. pull.rebase is set to false here, so the pull merges without asking. Now your main has everything origin has, plus your work, so the push is accepted.
You don't have to wait to be refused. Pulling before you push is a good habit. But a teammate can still push in the moment between your pull and your push. If that happens, do the same again: pull, then push.
When the pull stops with a conflict
If you and your teammate changed the same lines, the merge stops with a conflict, just like a merge between two of your own branches:
...
Auto-merging style.css
CONFLICT (content): Merge conflict in style.css
Automatic merge failed; fix conflicts and then commit the result.
Resolve it the way you learned in Branching & Merging. Open the file with edit, keep what should stay from both sides, and delete the conflict markers. Then git add the file and git commit, or let git commit -a stage it for you. Then push.
If you'd rather back out, git merge --abort puts your branch back the way it was before the pull. Your push is still refused, though, until you've merged their commit.
"fetch first" or "non-fast-forward"
The refusal ends in (fetch first) when your repository has never seen their commit. If you've fetched it but not merged it, the refusal is worded differently:
To https://git.example/team/project.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'https://git.example/team/project.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Either way, the answer is the same: merge their work in, then push.
Don't force it
git push --force makes origin take your branch anyway, and your teammate's commit is lost from main. That's why the Terminal won't run a plain --force in Lessons and Checkpoints. Rewriting History teaches --force-with-lease, the careful way to replace a branch on a remote when you really mean to.
One branch at a time
origin judges a push branch by branch. If a teammate pushed to menu, your push of main still goes through. Only a push of your menu is refused. git pull merges the upstream of the branch you're on, so switch to menu before you pull its changes in.
Explainer: A rejected push, then pull and push again
Graph as text
project: your repo, you are here
- HEAD → main at b243a0b "Merge branch 'main' of https://git.example/team/project"
Branches and tags
- main at b243a0b "Merge branch 'main' of https://git.example/team/project", tracks origin/main
- origin/HEAD at b243a0b "Merge branch 'main' of https://git.example/team/project"
- origin/main at b243a0b "Merge branch 'main' of https://git.example/team/project"
Commits, newest first
- b243a0b "Merge branch 'main' of https://git.example/team/project"; parents de1d2f7 and 19916ce; refs: HEAD → main, origin/HEAD, origin/main
- 19916ce "Add a menu page"; parent 4607830
- de1d2f7 "Add the opening hours"; parent 4607830
- 4607830 "Style the heading"; parent d1c0363
- d1c0363 "Add the home page"; parent 99860cd
- 99860cd "Add a README"; no parent
origin: remote host (bare), https://git.example/team/project.git
Branches and tags
- main at b243a0b "Merge branch 'main' of https://git.example/team/project"
Commits, newest first
- b243a0b "Merge branch 'main' of https://git.example/team/project"; parents de1d2f7 and 19916ce; refs: main
- 19916ce "Add a menu page"; parent 4607830
- de1d2f7 "Add the opening hours"; parent 4607830
- 4607830 "Style the heading"; parent d1c0363
- d1c0363 "Add the home page"; parent 99860cd
- 99860cd "Add a README"; no parent
Not shown: teammate.
Challenge 1 of 3
Story: Your report is ready for the archive. The Partner was just there, though.
You've committed Add the opening hours on main. Push it to main on origin, and keep every commit that's already there.
Unlocks after Branching & Merging.
Terminal
Unlocks after Branching & Merging.
This Lesson can be played once Branching & Merging is complete. Its text and Explainer are open to everyone.