15

最初は次のように (初めて!) git リポジトリをプッシュしようとしました。

$ git push helloworld

しかし、私はこれを取り戻しました:

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'

それで、「修正されたコミット」に関する別の StackOverflow の質問を見つけ、それが私に役立つかどうか本当にわからないまま、そこから提案を試みました。

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

出来た!

しかし、なぜそれが私の問題を解決したのかわかりません:(

git push helloworldこれが機能するのに「 」が機能しない理由を誰か説明できますか?

4

1 に答える 1

26

master ブランチの履歴 (コミットに関連付けられた SHA-1) を書き換えたようです。

つまり、早送りモードを押し込むことはできなくなりました。

+master は強制的にプッシュを実行します:オプションの先頭に + を付けることで、更新が早送りでない場合でも
、git に ref を更新するように指示できます。<dst>

注: 他の誰かが既にリポジトリのクローンを作成している場合、競合が発生することなくマスター ブランチをプルすることができなくなるため、これは問題になる可能性があります。
詳細については、このSO の回答も参照してください。


注: Junio C. Hamanoの言及:

2 つの独立した安全メカニズムがあります。

  • 送信側の安全性は、" git push --force" および/または接頭辞として ' ' を付けた refspec を使用してオーバーライドできます+)。

  • 受信側の安全性は、 receive.denynonfastworwardsプッシュ先のリポジトリの構成変数によってオーバーライドできます。

後者はデフォルトで「unsafe」ですが、安全性がリポジトリで有効化されている場合、送信側から強制しても無効化されません。IOW、安全でない動作を許可するには、両端が同意する必要があります。


Git FAQに記載されているように、考えられる一連のアクションは次のとおりです。

これの最も可能性の高い理由は、最初にリモートからプルする必要があることです。最初に取得してからログを確認することで、リモート側でどのような変更が行われたかを確認できます。例えば、

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

リモート側にあり、あなたの側にはないすべての変更がリストされます。
グラフィカルな表現が必要な場合は、 を使用します gitk --left-right master...origin/master
左の矢印はプッシュしたい変更、右の矢印はリモート側の変更です。

他の解決策(これはあなたがしたことです):

$ git push origin +branchname

これにより、更新が強制されます。許可がない場合、これが機能する場合があります。

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

つまり、最初にブランチをリモートで削除し (これは多くの場合許可されています)、次に「新しい」(または巻き戻された) ブランチを再度プッシュします。

ブランチを巻き戻すと、引っ張ったときに他の人が問題を起こす可能性があることに注意してください。
フェッチしたブランチと、公開した新しいブランチをマージして、取り除こうとしている変更を効果的に保持する可能性があります。
ただし、悪いリビジョンを持つのはそのコピーだけです。このため、ブランチを巻き戻すことは軽度の反社会的行為と見なされます。それにもかかわらず、それはしばしば適切です。

于 2009-09-25T06:19:08.620 に答える