git push synchronizes local branches with a remote repository.
It is the second half of the pull/push pair; without it your work
is invisible to everyone else.
Basic forms
git push # push current branch to its tracking remote
git push origin main # explicit: branch main to remote origin
git push origin feature:main # push local feature to remote main
git push -u origin feature # push and set tracking
The -u flag (--set-upstream) on the first push "links" the local
branch to the remote one. After that, git push with no arguments
knows where to go.
What physically happens
- Git builds a packfile from commits the remote does not have.
- Transfers it over the network (via SSH or HTTPS).
- Asks the remote to move its ref
refs/heads/<branch>to the new SHA. - The remote checks: can it fast-forward? If yes, it moves. If no, it refuses.
Push rejection
The most common error:
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the tip of your current branch is behind
This means the remote has commits you do not have. The fix: either
git pull --rebase (fetch the others' commits, rewrite yours on top),
or git pull without rebase (creates a merge commit). After that the
push will go through.
--force and --force-with-lease
Sometimes you need to overwrite history on the remote, for example
after a local rebase. That is what force push is for.
git push --force # dangerous
git push --force-with-lease # safe
--force blindly overwrites the remote branch, even if someone else
just pushed something there. Their commits will silently vanish.
--force-with-lease checks first: does the SHA of the remote branch
match what Git last saw? If not, someone pushed in the meantime and
the force is cancelled. This is the variant you should always use
instead of --force.
In main/master, force push is normally blocked by branch protection
rules. That is correct: shared history should not be rewritten.
Deleting a remote branch
git push origin --delete feature
# or equivalently:
git push origin :feature
The second form is older syntax you will see in scripts. The semantics: "push nothing into feature," which deletes it.
Pitfalls
git pushwithout-uon the first push requires an explicitorigin <branch>. Without it, Git does not know where to push.- If the remote is not named
origin(for example,upstream), you must specify it explicitly or configure tracking. pushsends only the specified branch, not all local branches. To send tags separately:git push --tagsorgit push origin <tag>.