15
votes

I tried to push my (first ever!) git repo like this initially:

$ git push helloworld

But I got this back:

To [email protected]:helloworld.git
 ! [rejected]        HEAD -> master (non-fast forward) error:
 failed to push some refs to '[email protected]:helloworld
git'

So I found another StackOverflow question about "amended commits" and tried a suggestion from there without really knowing whether it would help me:

KaiserSosa@SMICHAELS /c/test/helloworld (master)
$ git push helloworld +master:master

It worked!

But I don't know why it fixed my problem :(

Could someone explain why this works but "git push helloworld" doesn't?

1
Added another solution, in response to your comment.VonC

1 Answers

26
votes

It appears you have rewritten your history (SHA-1 associated with your commit) in your master branch.

That means, you can no longer push in a fast-forward mode.

the +master forces the push to take place:
By having the optional leading +, you can tell git to update the <dst> ref even when the update is not a fast forward.

Note: this could be bad if anyone else has already cloned your repository, since they will no longer be able to just pull your master branch without having some conflict.
See also this SO answer for more.


Note: as mentioned by Junio C. Hamano:

There are two independent safety mechanisms:

  • the sending end safety can be overridden by "git push --force" and/or by using a refspec prefixed with a '+');

  • the receiving end safety can be overridden by the config variable receive.denynonfastworwards of the repository you are pushing into.

The latter defaults to "unsafe", but if the safety is activated in the repository, forcing from the sending side will not deactivate it. IOW, both ends need to agree to allow the unsafe behavior.


As mentioned in the Git FAQ, a possible course of action is:

The most likely reason for this is that you need to pull from the remote first. You can see what changes the remote side has by fetching first and then checking the log. For example,

 $ git fetch origin
 $ git log master..origin/master

will list all the changes the remote side has that your side doesn't.
If you want a graphical representation, use gitk --left-right master...origin/master.
The arrows to the left are changes you want to push, the arrows to the right are changes on the remote side.

Other solution (which is what you did):

$ git push origin +branchname

This will force the update. If you don't have permission, then sometimes this will work:

$ git push origin :branchname
$ git push origin +branchname

i.e., delete the branch remotely first (this is often permitted), then re-push the "new" (or perhaps rewound) branch.

Be warned that if you rewind branches, others might get into problem when pulling.
There is the chance that they will merge in the branch that they fetched with the new one that you've published, effectively keeping the changes that you are trying to get rid of.
However, it will only be their copies that have the bad revisions. For this reason, rewinding branches is considered mildly antisocial. Nonetheless, it is often appropriate.