838

When I've worked a bit with my source code, I did my usual thing commit and then I pushed to a remote repository. But then I noticed I forgot to organize my imports in the source code. So I do the amend command to replace the previous commit:

> git commit --amend

Unfortunately the commit can't be pushed back to the repository. It is rejected like this:

> git push origin
To //my.remote.repo.com/stuff.git/
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to '//my.remote.repo.com/stuff.git/'

What should I do? (I can access the remote repository.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Spoike
  • 119,724
  • 44
  • 140
  • 158
  • 2
    What if my --amend was only to change the commit message? Any way to edit the last commit message alone, if it was already pushed to remote? I did that on Github and got the same message about non fast forward. Then I applied a solution below but the merge just added more commit messages on top.. –  Mar 06 '10 at 23:17
  • 9
    @faB: I think that is a FAQ. A commit message is hashed along with the commit, so chaning _it_ changes the revid (hash). If it isn't clear: no you cannot. IIRC can store out-of-band info in notes (so you can annotate existing commits without altering them). To label specific commits, use tags – sehe Mar 21 '11 at 22:06
  • 1
    You will soon (git1.8.5, Q4 2013) be able to [do a `git push -force` more carefully](http://stackoverflow.com/a/18505634/6309). – VonC Sep 10 '13 at 08:42
  • 3
    Here is the cowboy style. Don't learn any further or don't hunt ways to undo the previous git amend. Just add some placeholder code, I mean, Add some comment, Cleanup a bit of code or simply added few dash dash dash.... Now make a real commit and push it to remote. Done ! – nehem Nov 19 '15 at 11:49
  • @user58777 If your -amend was only to change the commit message and you haven't made any additional local commits since then, you can reset your local branch to the remote commit that you pushed before amending the commit message. – Scott Ahten Jan 15 '19 at 23:40
  • 1
    *If nobody else is using the `remote`* and you wish just force `push` the amended commit to replace the previous one, you can `delete` the remote and push the amended commit right after to recreate the remote. – Ricardo Jan 17 '20 at 04:01

21 Answers21

621

I actually once pushed with --force and .git repository and got scolded by Linus BIG TIME. In general this will create a lot of problems for other people. A simple answer is "Don't do it".

I see others gave the recipe for doing so anyway, so I won't repeat them here. But here is a tip to recover from the situation after you have pushed out the amended commit with --force (or +master).

  1. Use git reflog to find the old commit that you amended (call it old, and we'll call the new commit you created by amending new).
  2. Create a merge between old and new, recording the tree of new, like git checkout new && git merge -s ours old.
  3. Merge that to your master with git merge master
  4. Update your master with the result with git push . HEAD:master
  5. Push the result out.

Then people who were unfortunate enough to have based their work on the commit you obliterated by amending and forcing a push will see the resulting merge will see that you favor new over old. Their later merges will not see the conflicts between old and new that resulted from your amending, so they do not have to suffer.

João Pimentel Ferreira
  • 14,289
  • 10
  • 80
  • 109
  • 34
    I'm very well aware what happens when you force push an amended commit (by destroying history). Luckily enough, I was the only developer on the project with the remote repo being on a network drive so it wasn't that big of a deal. I never thought about merging an amend commit, so I'll upvote this. – Spoike Jan 11 '09 at 12:06
  • 109
    In our company, we force-push quite regularly... on feature branches developed by individuals. – Ondra Žižka Mar 23 '12 at 06:57
  • 3
    The scolding from Linus was because you erased history with the force option, not because you shouldn't do it. GabrielleV's solution works fine, because it doesn't change history. – Adam Cataldo Oct 24 '13 at 14:41
  • @OndraŽižka we do the same, it keeps the git history much cleaner – ioleo Feb 15 '14 at 15:35
  • 2
    Regarding the force push to a feature branch, shouldn't this be considered OK if you're working off a personal feature branch? The history that you're overwriting is only your own, which you're fully aware of. For instance, my team members and I name personal branches accordingly, e.g. develop__. That's the whole point of distributed revision management, we can do whatever want in on our own sandbox, just don't mess with history in the mainline. – Joey Carson Mar 10 '14 at 21:23
  • 1
    Now Linus can use [one of github's features](http://readwrite.com/2015/09/04/github-protected-branches) and protect master from force push. – John_West Oct 24 '15 at 23:29
  • 2
    Please, since the author (gitster) of this answer seems to not exist anymore, could anyone help to clarify the item number 1: find the old commit. If you don't have a backup, where would you find it? Amend and force push wouldn't have it destroyed? Maybe he is referring to get it from a friend/collaborator that still have it in the tree? – DrBeco Jun 20 '16 at 02:41
  • 2
    Dr Breco you can use `git reflog` to find it – Simon Zyx Aug 11 '16 at 10:26
  • 3
    @Linus should have scolded himself for not figuring out a way to automatically reattach detached heads. – theMayer Dec 12 '17 at 17:30
  • 3
    Others noted, but just want to add more emphasis on it: if you are developing on a feature branch - then in most cases rewriting history of that branch has no impact to anybody or anything else. In fact, during a separate work on a feature branch, one might use force push quite often. – 2beens Jun 24 '20 at 07:24
  • is it still bad when you are doing that in the Github PR ?! i think that doesn't creates side-effects ?! – ME-ON1 Jun 24 '22 at 07:59
  • 1
    @ME-ON1 Do *not* force push when your previous commits were merged in to main branch or when someone uses your personal develop branch as a base branch. As long as your commits are not used by others, you're safe to force push. – Louis Go Aug 30 '22 at 01:59
  • What about the case when you *know* that no-one else has pulled that commit? I find these "just don't do it" directives counter-productive. We're trying to obtain nuanced disciplined control of our systems and there are different circumstances that can be identified with certainty for which to choose different approaches. There should never be vehement blanket unexplained directives to say "don't do it". If the tool has the facility why is it there? Explain the consequences so the technician can choose when it's appropriate and when it isn't. – NeilG Jun 09 '23 at 06:45
320

You are seeing a Git safety feature. Git refuses to update the remote branch with your branch, because your branch's head commit is not a direct descendent of the current head commit of the branch that you are pushing to.

If this were not the case, then two people pushing to the same repository at about the same time would not know that there was a new commit coming in at the same time and whoever pushed last would lose the work of the previous pusher without either of them realising this.

If you know that you are the only person pushing and you want to push an amended commit or push a commit that winds back the branch, you can 'force' Git to update the remote branch by using the -f switch.

git push -f origin master

Even this may not work as Git allows remote repositories to refuse non-fastforward pushes at the far end by using the configuration variable receive.denynonfastforwards. If this is the case the rejection reason will look like this (note the 'remote rejected' part):

 ! [remote rejected] master -> master (non-fast forward)

To get around this, you either need to change the remote repository's configuration or as a dirty hack you can delete and recreate the branch thus:

git push origin :master
git push origin master

In general the last parameter to git push uses the format <local_ref>:<remote_ref>, where local_ref is the name of the branch on the local repository and remote_ref is the name of the branch on the remote repository. This command pair uses two shorthands. :master has a null local_ref which means push a null branch to the remote side master, i.e. delete the remote branch. A branch name with no : means push the local branch with the given name to the remote branch with the same name. master in this situation is short for master:master.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 2
    this did not work with github, it gave me the following message: [remote rejected] master (deletion of current branch prohibited) – vedang Nov 12 '10 at 13:12
  • I didn't want to force push (which i knew would solve the issue), but now I guess I have no choice. – vedang Nov 12 '10 at 13:14
  • 1
    deleting the remote master branch will free the space in the remote repo ? – Mr_and_Mrs_D Apr 29 '12 at 13:55
  • 1
    @Mr_and_Mrs_D: Not immediately, but after a `git gc` once the reflogs have expired old objects will be pruned. Nobody who clones the repository will get any objects that are no longer reachable as soon as the branch has been updated. – CB Bailey Apr 29 '12 at 13:59
  • 1
    This worked for me, and shows as 1 (properly amended) commit in git-log and in Bitbucket. However, my Jira ticket shows two commits. The first one has a different SHA than what I see in Bitbucket and has the unamended commit. The second one has the same SHA with the amended commit. So I guess the unamended commit never goes away it is just hidden by `git` and other clients. How can I see the unamended commits with git-log? – Jesse Hogan Aug 22 '16 at 22:43
  • This is the simple solution (in some cases). I understand other people's concerns about different users accessing the repository, however not all projects have a large number of contributors: I am the only active contributor to my projects, so there is no risk of conflicts, this works perfectly for me. – Vincenzooo Jun 12 '20 at 10:11
248

Quick rant: The fact that no one has posted the simple answer here demonstrates the desperate user-hostility exhibited by the Git CLI.

Anyway, the "obvious" way to do this, assuming you haven't tried to force the push, is to pull first. This pulls the change that you amended (and so no longer have) so that you have it again.

Once you have resolved any conflicts, you can push again.

So:

git pull

If you get errors in pull, maybe something is wrong in your local repository configuration (I had a wrong ref in the .git/config branch section).

And after

git push

Maybe you will get an extra commit with the subject telling about a "Trivial merge".

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 2
    Yes, I wrote about this, see http://stackoverflow.com/questions/253055/how-do-i-push-amended-commit-to-the-remote-git-repo/1459351#1459351 ;) – Spoike Sep 22 '09 at 10:58
  • 13
    This doesnt really work like I expected it to. It creates two new commits. One that is a replica of the old one, but with the amended changes. And one merge commit with an empty diff. Still leaving the old commit unchanged, revealing possibly sensitive data that I was trying to amend away. I believe `git push -f` or `git reset` is the only way to go here. – thnee Nov 05 '13 at 11:53
  • 62
    While technically answering the problem, it doesn't really address the issue. As you said, it will generate an extra commit, but the main reason people amend a commit is to avoid creating a new one. So if the poster were to follow your instructions, he wouldn't get the desired result. It would make just as much sense to not amend the commit in the first place. – Dan Jones Jul 30 '14 at 17:36
  • This should be the accepted answer giving the fact that it resolves the issue right away !!! Thanks – HanniBaL90 Mar 01 '21 at 15:35
  • After reading a lot of scary posts, this answer is the right one for me (`commit` => `push` => `commit --amend` => unable to push). Thank you? – Byscripts Jun 04 '21 at 08:34
124

Short answer: Don't push amended commits to a public repo.

Long answer: A few Git commands, like git commit --amend and git rebase, actually rewrite the history graph. This is fine as long as you haven't published your changes, but once you do, you really shouldn't be mucking around with the history, because if someone already got your changes, then when they try to pull again, it might fail. Instead of amending a commit, you should just make a new commit with the changes.

However, if you really, really want to push an amended commit, you can do so like this:

$ git push origin +master:master

The leading + sign will force the push to occur, even if it doesn't result in a "fast-forward" commit. (A fast-forward commit occurs when the changes you are pushing are a direct descendant of the changes already in the public repo.)

mipadi
  • 398,885
  • 90
  • 523
  • 479
74

Here is a very simple and clean way to push your changes after you have already made a commit --amend:

git reset --soft HEAD^
git stash
git push -f origin master
git stash pop
git commit -a
git push origin master

Which does the following:

  • Reset branch head to parent commit.
  • Stash this last commit.
  • Force push to remote. The remote now doesn't have the last commit.
  • Pop your stash.
  • Commit cleanly.
  • Push to remote.

Remember to change origin and master if applying this to a different branch or remote.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Faiza
  • 751
  • 5
  • 5
  • 3
    2 remarks : - make sure to change the name of the branch if your are working on another one - I had to use `git add` before my commit to include the changes. – SylvainB Feb 20 '17 at 17:04
  • 1
    In Windows CMD, the first command should be escaped: `git reset --soft "HEAD^"`. The rest works fine. – MrMister Sep 13 '17 at 15:59
  • 3
    "a very simple and clean way.." cit. This procedure includes forced push. In lights of all the critisims in Answers above I am not sure if this procedure is in fact a clean one. –  Jun 05 '19 at 15:03
36

I have solved it by discarding my local amended commit and adding the new changes on top:

# Rewind to commit before conflicting
git reset --soft HEAD~1

# Pull the remote version
git pull

# Add the new commit on top
git add ...
git commit
git push
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bara
  • 2,964
  • 2
  • 26
  • 24
13

If the message to be changed is for the latest commit to the repository, then the following commands are to be executed:

git commit --amend -m "New message"

git push --force repository-name branch-name

Note: using --force is not recommended unless you are absolutely sure that no one else has cloned your repository after the latest commit.

A safer alternative is to use:

git push --force-with-lease repository-name branch-name

Unlike --force, which will destroy any changes someone else has pushed to the branch, --force-with-lease will abort if there was an upstream change to the repository.

M-Razavi
  • 3,327
  • 2
  • 34
  • 46
  • 1
    I knew there had to be a somewhat smart option in order no to erase other people's work while letting you get away with it if no else committed anything in the meantime. Thanks for digging this one out ! – cassepipe Aug 10 '23 at 09:44
11

I had the same problem.

  • Accidentally amended the last commit that was already pushed
  • Done a lot of changes locally, committed some five times
  • Tried to push, got an error, panicked, merged remote, got a lot of not-my-files, pushed, failed, etc.

As a Git-newbie, I thought it was complete FUBAR.

Solution: Somewhat like @bara suggested + created a local backup branch

# Rewind to commit just before the pushed-and-amended one.
# Replace <hash> with the needed hash.
# --soft means: leave all the changes there, so nothing is lost.
git reset --soft <hash>

# Create new branch, just for a backup, still having all changes in it.
# The branch was feature/1234, new one - feature/1234-gone-bad
git checkout -b feature/1234-gone-bad

# Commit all the changes (all the mess) not to lose it & not to carry around
git commit -a -m "feature/1234 backup"

# Switch back to the original branch
git checkout feature/1234

# Pull the from remote (named 'origin'), thus 'repairing' our main problem
git pull origin/feature/1234

# Now you have a clean-and-non-diverged branch and a backup of the local changes.
# Check the needed files from the backup branch
git checkout feature/1234-gone-bad -- the/path/to/file.php

Maybe it's not a fast and clean solution, and I lost my history (1 commit instead of 5), but it saved a day's work.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
davisca
  • 1,104
  • 10
  • 18
10

If you have not pushed the code to your remote branch (GitHub/Bitbucket) you can change the commit message on the command line as below.

 git commit --amend -m "Your new message"

If you're working on a specific branch, do this:

git commit --amend -m "BRANCH-NAME: new message"

If you've already pushed the code with a wrong message then you need to be careful when changing the message. i.e after you change the commit message and try pushing it again you end up with having issues. To make it smooth follow the following steps.

Please read the entire answer before doing it

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

Important note: When you use the force push directly you might end up with code issues that other developers are working on the same branch. So to avoid those conflicts you need to pull the code from your branch before making the force push:

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

This is the best practice when changing the commit message, if it was already pushed.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Prabhakar
  • 6,458
  • 2
  • 40
  • 51
  • 1
    If you've successfully pulled back the commit in your last example, why do you need to force push? Wouldn't a standard push suffice? Thanks – Thomas Jan 23 '15 at 05:32
  • Question asked by Thomas is in fact very valid. Myself didn't need to force the push following pull. –  Jun 05 '19 at 14:59
  • Please don't call it "the best practice" because there is a way to work around `--force`, see the accepted answer – Farid Oct 08 '19 at 11:14
  • `git pull` overwrites my amended commit. – Cees Timmerman Sep 15 '22 at 11:19
8

You can do it in a simple and safe way by doing:

  1. Amend your last commit with git commit --amend and whatever options you need to add
  2. git pull to sync your local repo with your remote repo.
  3. After pull, you will have conflicts between local and remote. You just have to solve them by accepting current changes and commit again.
  4. git push

Now your local and remote repo are updated with no need to change your repo history.

6

If you know nobody has pulled your un-amended commit, use the --force-with-lease option of git push.

In TortoiseGit, you can do the same thing under "Push..." options "Force: May discard" and checking "known changes".

Force (May discard known changes) allows the remote repository to accept a safer non-fast-forward push. This can cause the remote repository to lose commits; use it with care. This can prevent from losing unknown changes from other people on the remote. It checks if the server branch points to the same commit as the remote-tracking branch (known changes). If yes, a force push will be performed. Otherwise it will be rejected. Since git does not have remote-tracking tags, tags cannot be overwritten using this option.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ShawnFeatherly
  • 2,470
  • 27
  • 20
6

If you are using Visual Studio Code, you can try this extension to make it easier.

https://marketplace.visualstudio.com/items?itemName=cimdalli.git-commit-amend-push-force

As you can understand from its name, it executes commands consecutively

  • git commit --amend
  • git push --force
Okan Cetin
  • 167
  • 3
  • 4
5

You are getting this error because the Git remote already has these commit files. You have to force push the branch for this to work:

git push -f origin branch_name

Also make sure you pull the code from remote as someone else on your team might have pushed to the same branch.

git pull origin branch_name

This is one of the cases where we have to force push the commit to remote.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Praveen Dhawan
  • 300
  • 4
  • 9
  • Why not this answer be accounting for major comments raised in previous answers? –  Jun 05 '19 at 15:06
4

In this case, you should --force.

Based on:

If it is an individual project, I would do this: git push origin <branch-name> -f

If you are working with your team, or other peers are reviewing and using your code the force flag is not recommended. Mainly because you always want a clean git history.

What I would do?

  1. If more people are working in the same branch or others reviewing your code, I would git commit --amend, then git push -f ... and let people know that they need to git pull --rebase to be able to see your changes.
  2. If something like this happens while reviewing a PR or MR, add new clean commit and at the end squash to clean up history.
Hunter8
  • 111
  • 3
2

Here is a very simple and clean way to push your changes after you have already made a git add "your files" and git commit --amend:

git push origin master -f

or:

git push origin master --force
kenorb
  • 155,785
  • 88
  • 678
  • 743
craken
  • 1,411
  • 11
  • 16
  • I hear that's bad, and I'm sure it is. There is a (good) reason for git to fail by default (and require --force), I am sure. – Rolf Dec 02 '16 at 16:30
1

I had to fix this problem with pulling from the remote repo and deal with the merge conflicts that arose, commit and then push. But I feel like there is a better way.

Spoike
  • 119,724
  • 44
  • 140
  • 158
  • Not really. The issue might be that you haven't updated your local copy from the remote repo. Git won't push to it because you may have to deal with merges manually. In my other reply, I have a command (and explanation) that will force a push -- but beware that is may delete changes in the remote. – mipadi Oct 31 '08 at 18:14
1

I just kept doing what Git told me to do. So:

  • Can't push because of amended commit.
  • I do a pull as suggested.
  • Merge fails. so I fix it manually.
  • Create a new commit (labeled "merge") and push it.
  • It seems to work!

Note: The amended commit was the latest one.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rolf
  • 5,550
  • 5
  • 41
  • 61
  • 1
    I'd downvote, if I'd have more reputation points, so I'll just ask here politely, that which one was you of the sufferers? The one who amended? The one, who pulled and worked on a branch with amended commit? Before the amend, or after it? I just cleared every modification of mine because I misunderstood you... Fortunately there was not much... – Bartis Áron Aug 25 '17 at 16:06
1

The following worked for me when changing Author and Committer of a commit.

git push -f origin master

Git was smart enough to figure out that these were commits of identical deltas which only differed in the meta information section.

Both the local and remote heads pointed to the commits in question.

MadPhysicist
  • 5,401
  • 11
  • 42
  • 107
0

Here, How I fixed an edit in a previous commit:

  1. Save your work so far.

  2. Stash your changes away for now if made: git stash Now your working copy is clean at the state of your last commit.

  3. Make the edits and fixes.

  4. Commit the changes in "amend" mode: git commit --all --amend

  5. Your editor will come up asking for a log message (by default, the old log message). Save and quit the editor when you're happy with it.

    The new changes are added on to the old commit. See for yourself with git log and git diff HEAD^

  6. Re-apply your stashed changes, if made: git stash apply

Community
  • 1
  • 1
Harshal Wani
  • 2,249
  • 2
  • 26
  • 41
0

To avoid forced push, in the remote bare repository remove the last commit (the one to be amended) using:

git update-ref HEAD HEAD^

then push the amended commit with no conflict.

Note: This assumes no one has pulled the wrong commit in the meantime. If they have, they will have to similarly rewind and pull again, possibly merging their own changes.

FNia
  • 173
  • 6
0

Just delete the remote branch

git push --delete origin <your-branch>

and then push your amended branch.

  • In the context of collaborative work that woul erase changes made by others and pushed in the meantime so you may just as well not bother and use `git push --force` – cassepipe Aug 10 '23 at 09:42