Pushing Changes (git push)
git push uploads your local commits to a remote repository, making them visible to everyone who has access to the remote. Until you push, your work lives only on your machine. Pushing is also how you publish a brand-new branch — typically the step right before opening a Pull Request.
The basic push
Push the current branch to its upstream
git push # Sends your local commits on the current branch to origin/<branch>
First push of a new branch
-u sets up tracking
git push -u origin feature-x # Creates origin/feature-x and links your local feature-x to it. # Future pushes can be just 'git push' with no arguments.
The -u flag (or --set-upstream) is the one most beginners miss. Without it, the first git push works but the second one complains that there’s no upstream configured.
Automatic upstream
Skip the -u flag forever
git config --global push.autoSetupRemote true # Now 'git push' on a new branch sets up tracking automatically
Pushing to a specific remote/branch
git push origin feature-x git push origin main:production # push local main to remote 'production' branch git push upstream feature-x
Common scenarios
Successful fast-forward push
git push # Counting objects: 5, done. # Writing objects: 100% (5/5), 632 bytes. # To github.com:you/repo.git # c204c1d..1f9ab2c main -> main
Rejected: remote has commits you don’t
git push # To github.com:you/repo.git # ! [rejected] main -> main (fetch first) # error: failed to push some refs to 'github.com:you/repo.git' # hint: Updates were rejected because the remote contains work that you do # hint: not have locally. # Fix: git pull # or git pull --rebase git push
Force push (rewritten history)
After a rebase or amend
# Safer git push --force-with-lease # Dangerous git push --force
Pushing all branches
# Push every branch with a matching name on origin git push origin --all # Push every tag too git push origin --tags # Both: git push origin --all && git push origin --tags
Pushing a tag
git push origin v1.0 # one tag git push origin --tags # all tags git push origin --follow-tags # tags reachable from pushed commits
Deleting a remote branch
git push origin --delete feature-x # Same as the older form: git push origin :feature-x
Dry run
See what would happen
git push --dry-run # Pretend to push; report what would change without actually doing it
Common push errors
"non-fast-forward" — the remote has commits you don’t.
git pullfirst."updates were rejected, remote contains work that you do not have" — same as above.
"refusing to update checked out branch" — pushing to a non-bare remote whose checked-out branch you’re trying to update. Configure
receive.denyCurrentBranch=updateInsteadon the server or push to a bare repo."Permission denied (publickey)" — your SSH key isn’t set up. Either fix the key or switch to HTTPS.
"Repository not found" — wrong URL, or you’re not authenticated, or you don’t have write access.
What push does
Contacts the remote.
Sends every object (commit, tree, blob) the remote does not have.
Updates the remote branch pointers to match yours.
Updates your local
origin/<branch>to match what the remote now says.
What push does NOT do
Does not push every branch automatically — only the ones you ask for (or your default push refspec).
Does not push tags by default. Add
--tagsor--follow-tags.Does not run server-side hooks until the upload is complete (so pushes can be rejected by a pre-receive hook even after the upload).
push.autoSetupRemote true and push.default current in your global config — most pushes become single-word commands and the rest become obvious.