Programming and IT
git push
Until you run git push, your commits exist only on your own disk. The command sends them to a remote repository and moves the branch pointer there — which is also why it is the command that most often refuses, when someone else got their work in first.
In this article
What goes to the server#
Git sends commits — the ones the server does not have yet — and the new position of the branch pointer. Uncommitted edits, files in your working directory and the contents of the index go nowhere: first git commit, then push.
The server accepts a change only if it continues the history it already has. That kind of continuation is called a fast-forward. If the server branch has moved ahead or your history was rewritten, Git stops and touches nothing — this is the main safeguard against losing other people's work.
Syntax and options#
Most often the remote is called origin, and the branch is the current one. When
a branch is linked to a server branch (its upstream), plain git push is enough.
| Option | What for |
|---|---|
-u, --set-upstream |
push and link the branch to the server branch — needed once |
--force-with-lease |
overwrite the server branch, but only if it has no commits you have not seen |
-f, --force |
overwrite unconditionally; other people's work can disappear |
--tags |
push tags, which an ordinary push does not send |
--delete <branch> |
delete a branch on the server |
-n, --dry-run |
show what would happen without changing anything |
Example: the first push of a new branch#
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 512 bytes | 512.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0)
To https://github.com/example/notes.git
* [new branch] feature/login -> feature/login
branch 'feature/login' set up to track 'origin/feature/login'.
Without -u, Git reminds you itself:
fatal: The current branch feature/login has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin feature/login
From then on, git push with no arguments is enough for this branch.
The non-fast-forward rejection#
The most common picture: while you were working, someone else's commit landed on the server branch.
To https://github.com/example/notes.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/example/notes.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally.
The note may say fetch first or non-fast-forward — the second appears when your
history has diverged from the server's, for example after --amend or a rebase.
The fix is the same: first get their work, then send yours.
The rebase moves your commits on top of theirs, and the push becomes an ordinary
fast-forward. Details are in the article on git pull.
Never answer this rejection with --force: it wipes from the server exactly the
commits that caused the rejection.
When you really do need to rewrite#
There are legitimate cases: you fixed the message of your last commit on a
personal branch nobody else is looking at. Then instead of --force use its
careful relative:
The option checks that the server branch is still where you last saw it. If
someone else's commit has appeared, the push is rejected with stale info, and
you investigate instead of overwriting. On a shared branch like main, do not
rewrite history at all — the reasons are spelled out in
git rebase.
How to take back what you pushed#
The commit is on the server and others have seen it — there is only one safe way:
A new commit appears that cancels the effect of the old one. History stays continuous, and nobody's copy breaks.
A branch created by mistake is removed entirely:
And a tag pushed by accident goes with git push origin --delete v1.4. Remember
that anything pushed to a shared server may already have been downloaded, and a
secret that ended up in a commit counts as compromised whatever you do with the
history: change the password or token, do not try to hide it. The other commands
for talking to a server are in the cheat sheet.
Step-by-step plan
- Make sure everything is committedgit status: uncommitted edits do not go to the server.
- Get other people's workgit pull --rebase so your commits sit on top of the server's.
- Push with trackingThe first time git push -u origin branch, after that just git push.
- Read the server's replyA new branch line or a hash range means accepted; rejected means read the hint.
- Fix with a revert, not with forcegit revert for shared branches, --force-with-lease only for your own.
Start learning this in your own space
The plan goes into your repository: tick off stages, keep notes — the change history shows how far you have come.
Check yourself
1.First push of a new branch: which command both pushes it and links it to the server branch?
2.A push was rejected as non-fast-forward. What do you do first?
3.Why is --force-with-lease better than plain --force?
Sources
-
Pro Git bookThe section “Working with Remotes”free
-
git push referencePush options and what the rejections meanfree
-
GitHub Docs: Removing sensitive dataWhat to do if a secret was pushedfree
Was this helpful?