Why "git push helloworld +master:master" instead of just "git push helloworld"?

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

$ git push helloworld

But I got this back:

To git-smichaels@free5.projectlocker.com:helloworld.git
 ! [rejected]        HEAD -> master (non-fast forward) error:
 failed to push some refs to 'git-smichaels@free5.projectlocker.com: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?


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
    

    ie, 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.

    链接地址: http://www.djcxy.com/p/7558.html

    上一篇: 克隆和原始远程存储库之间的git diff

    下一篇: 为什么“git push helloworld + master:master”而不是“git push helloworld”?