Git commands
How git push moves origin/main, step by step
git push: sending your commits up
How to use this page
- slider / ▶Drag the slider, or press play, to watch the command happen. Before and After jump to either end.
- ← → · spaceStep through a multi-step command; space toggles Before / After.
- APlay or pause the loop (the page opens playing). Any manual input takes over.
- hoverA commit shows its message, author, date and parents, with its history highlighted.
- clickCopies the commit sha.
- ctrl + wheelZoom around the cursor (pinch on a trackpad). Double-click resets the view.
- EscStop playback, reset the view, close this menu.
- shareThe Share button copies a link to this graph, copies it as an image, downloads PNG/SVG/page, or posts it. #before, #after or #step=N in the link pins the state.
git-sim visually simulates any Git command in your own repos - from your terminal, IDE, or AI.
Table of Contents
- Introduction
- What is git push?
- Watch it happen
- Before and after
- When the remote says no
- Is it safe?
- Useful forms
- How to undo it
- Try it on your repository
- Common questions
- Summary
- Next steps
- Related commands
Introduction
git push is how your commits leave your machine. It sends the commits the remote doesn't have and then asks the remote to move its branch to your tip. Both halves can be seen on a graph, and the second one explains the rejection message everyone eventually gets.
In this article, we'll:
- Watch
git pushsend one commit and moveorigin/main - See what the remote checks before accepting
- Cover the rejected-push case and what to do next
What is git push?
git push (with an upstream set) uploads to the remote every commit reachable from your branch that the remote doesn't already have, then updates the remote's branch to point at your tip. The remote accepts only if the update is a fast-forward, meaning its current tip is an ancestor of yours. Locally, origin/main moves to match, so your view of the remote stays current.
Watch it happen
Our sample repo has one local commit that origin does not have. Here's git push:
- Before:
mainandHEADare one commit ahead oforigin/main, which is still at8c02d5b. - Git sends
80fd5fdto origin and moves origin'smainto it.origin/mainmoves to80fd5fdto match. mainandHEADdon't move, and no local commits are created. Push changes the remote, not your branch.
Before and after
Before, git status says main is ahead of origin/main by 1. After, the two labels share a commit and status says nothing about being ahead. Git reports the range it pushed:
The raw git output, if you want to read along in text
git log --oneline --graph --all
before
* 80fd5fd (HEAD -> main) Add contact page
* 8c02d5b (origin/main, origin/HEAD) Update dependencies
* a0b2db3 Add user settings page
| * 1117a34 (origin/feature, feature) Add search tests
| * e5869f0 Fix typo in search box
| * fc19889 Add search box
|/
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commitafter
* 80fd5fd (HEAD -> main, origin/main, origin/HEAD) Add contact page
* 8c02d5b Update dependencies
* a0b2db3 Add user settings page
| * 1117a34 (origin/feature, feature) Add search tests
| * e5869f0 Fix typo in search box
| * fc19889 Add search box
|/
* 96c4fc2 Fix header layout
* ae65976 Add login page
* 3e1ffe4 Add project skeleton
* 4114b2c Initial commitwhat git printed
To ../your_project.git
8c02d5b..80fd5fd main -> mainWhen the remote says no
If someone else pushed to main since your last fetch, the remote's tip is no longer an ancestor of yours, and the push is rejected:
! [rejected] main -> main (fetch first)
The remote is refusing to throw away their commit. The fix is to bring their work in first, with git pull (or git fetch then merge or rebase), and push again. --force overrides the check, and is its own page because of what it can overwrite.
Is it safe?
Safe git-sim pre-flight
Pushes 1 commit(s) to origin/main.
A normal push adds commits to the remote and fast-forwards its branch. The remote's own check refuses anything that would drop commits, so a plain push can't lose work on either side.
Useful forms
git push -u origin <branch>pushes a new branch and sets it as upstream.git push origin <tag>orgit push --tagssends tags, which plainpushskips.git push origin --delete <branch>removes a remote branch.git push --force-with-leaseoverrides a rejection, but only if the remote is where you last saw it. Its own page.
How to undo it
If the pushed commit shouldn't be there, git revert it and push again. That's the honest undo once a commit is public. Rewinding the remote with a force push works only if nobody has pulled yet.
Try it on your repository
pip install git-sim
git-sim push
git-sim shows which commits would be sent and where the remote branch would end up, and tells you if the push would be rejected.
Common questions
What does git push do?
It uploads the commits your branch has that the remote lacks, then moves the remote's branch to your tip, provided that's a fast-forward.
Why was my push rejected?
The remote branch has commits you don't have, so moving it to your tip would drop them. Pull first, then push.
Does git push send all branches?
No, only the current branch by default (with push.default = simple). git push --all sends every branch, and the git push documentation covers the other push.default modes and flags.
Does git push send tags?
No. git push origin <tag> or git push --tags.
Summary
In this article, we watched git push send one commit and move origin/main while main stayed put, and covered why the remote rejects a push when it has moved and what to do about it.
Next steps
git push --force covers overriding a rejection and what that costs. git pull is the usual way to resolve one.
Related commands
- git pull, to bring the remote's work in first
- git fetch, to see what the remote has
- git push --force, to override the check
- git push --force-with-lease, the safer override
- git branch, the thing being published
- git commit, what gets pushed
- git push --delete, to delete a branch on the remote
- git push --tags, to publish your tags, which plain push leaves behind
