Pushing Changes
git push uploads your new local commits to a remote branch. It only ever adds to the remote's history; if the remote has commits you don't have yet, Git refuses until you've brought them in — so you can't accidentally wipe out a teammate's work.
Pushing new commits
Sam's main is already linked to origin/main from the first push (lesson 30). After making commits, git status shows you're ahead:
echo "Omelette: eggs, butter" > omelette.txt git add . && git commit --quiet -m "Add omelette recipe" echo "Granola: oats, honey" > granola.txt git add . && git commit --quiet -m "Add granola recipe" git status
On branch main Your branch is ahead of 'origin/main' by 2 commits. (use "git push" to publish your local commits) nothing to commit, working tree clean
git push
Enumerating objects: 7, done. Counting objects: 100% (7/7), done. Delta compression using up to 10 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 606 bytes | 606.00 KiB/s, done. Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 To https://github.com/sam-rivera/recipes.git 6b13d64..fa1d869 main -> main
The last line reads: the remote's main moved from one commit to another (a..b is the range of commits that were sent). On GitHub, the output also includes lines starting with remote: — for a new branch, a link to open a pull request.
Upstream branches
A plain git push works because main has an upstream: origin/main. For a new branch, the first push needs the remote and branch name, and -u (--set-upstream) to set up the link:
git switch -c desserts echo "Brownies: chocolate, butter, sugar" > brownies.txt git add . && git commit --quiet -m "Add brownie recipe" git push
Switched to a new branch 'desserts'
fatal: The current branch desserts has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin desserts
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.git push -u origin desserts
Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 10 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 381 bytes | 381.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 To https://github.com/sam-rivera/recipes.git * [new branch] desserts -> desserts branch 'desserts' set up to track 'origin/desserts'.
From then on, git push and git pull on this branch need no arguments. (If you'd like Git to do this automatically for every new branch, set git config --global push.autoSetupRemote true.)
When the push is rejected
Meanwhile Sam's colleague Alex has pushed a commit to main. Sam commits locally and tries to push:
echo "Pancakes: flour, milk, eggs, sugar" > pancakes.txt git commit --quiet -am "Add sugar to pancakes" git push
To https://github.com/sam-rivera/recipes.git ! [rejected] main -> main (fetch first) error: failed to push some refs to 'https://github.com/sam-rivera/recipes.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
The remote has a commit Sam doesn't have, so pushing would throw it away. The fix is to bring Alex's work in first — git pull (lesson 34) — and then push:
git pull --no-rebase --no-edit git push
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), 275 bytes | 91.00 KiB/s, done. From https://github.com/sam-rivera/recipes fa1d869..a2f47b9 main -> origin/main Merge made by the 'ort' strategy. porridge.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 porridge.txt Enumerating objects: 9, done. Counting objects: 100% (8/8), done. Delta compression using up to 10 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (5/5), 585 bytes | 585.00 KiB/s, done. Total 5 (delta 2), reused 0 (delta 0), pack-reused 0 To https://github.com/sam-rivera/recipes.git a2f47b9..192bd15 main -> main
Force pushing
After rewriting commits you've already pushed — with --amend or a rebase — a normal push is rejected for the same reason. You can override the check with a force push, which makes the remote branch match yours exactly. Use the safer form:
git push --force-with-lease
--force-with-lease only overwrites the remote if it's still where you last saw it. If someone pushed in the meantime, it refuses instead of silently deleting their commits — which plain --force would do. Even so, only force-push branches that you alone work on; never force-push main. Many teams protect main on GitHub so that force pushes are blocked entirely.
Other push commands
| Command | Does |
|---|---|
git push origin desserts | Push one branch (no upstream needed) |
git push origin local-name:remote-name | Push to a remote branch with a different name |
git push origin --delete desserts | Delete a branch on the remote |
git push origin v1.0 / --tags | Push a tag / all tags (lesson 39) |
git push --dry-run | Show what would be pushed |
Before pushing, it's worth checking exactly what's about to go out:
echo "Granola: oats, honey, almonds" > granola.txt git commit --quiet -am "Add almonds to granola" git log --oneline origin/main..main
9782050 (HEAD -> main) Add almonds to granola
Try it yourself
Push a new branch with -u, then make two more commits and check git status says you're 2 commits ahead before pushing them. Finally delete the branch on the remote with git push origin --delete.