GitPushing Changes (git push)

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

Bash
git push
# Sends your local commits on the current branch to origin/<branch>
First push of a new branch

-u sets up tracking

Bash
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

Bash
git config --global push.autoSetupRemote true
# Now 'git push' on a new branch sets up tracking automatically
Pushing to a specific remote/branch

Bash
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

Bash
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

Bash
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

Bash
# Safer
git push --force-with-lease

# Dangerous
git push --force
Warning
`--force` overwrites remote commits without checking who else has them. Always prefer `--force-with-lease` — it refuses if the remote moved unexpectedly, preventing accidental destruction of teammates’ work.
Pushing all branches

Bash
# 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

Bash
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

Bash
git push origin --delete feature-x
# Same as the older form: git push origin :feature-x
Dry run

See what would happen

Bash
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 pull first.

  • "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=updateInstead on 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 --tags or --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).

Pushing is the moment of sharing
Until you push, your work is invisible to anyone else and not backed up off your machine. Make a habit of pushing feature branches at the end of every day, even if they aren’t ready for review. Cheap insurance.
Tip
Set push.autoSetupRemote true and push.default current in your global config — most pushes become single-word commands and the rest become obvious.