Gitリセット-ハードにしてリモートリポジトリにプッシュ


200

私はいくつかの悪いコミット(この例ではD、E、F)があったリポジトリを持っていました。

ABCDEFマスターとオリジン/マスター

ローカルリポジトリを特にで変更しましたgit reset --hard。リセット前にブランチを作成したので、次のようなレポができました。

A-B-C master  
     \ D-E-F old_master

A-B-C-D-E-F origin/master

今、私はそれらの悪いコミットのいくつかの部分が必要だったので、私は必要なビットを選び、いくつかの新しいコミットを作成したので、ローカルに次のようになりました:

A-B-C-G-H master
     \ D-E-F old_master

次に、この状態をリモートリポジトリにプッシュします。ただし、git pushGitを丁寧に実行しようとすると、ブラシが無効になります。

$ git push origin +master:master --force  
Total 0 (delta 0), reused 0 (delta 0)  
error: denying non-fast forward refs/heads/master (you should pull first)  
To git@git.example.com:myrepo.git  
! [remote rejected] master -> master (non-fast forward)  
error: failed to push some refs to 'git@git.example.com:myrepo.git'  

リモートリポジトリでローカルリポジトリの現在の状態を取得するにはどうすればよいですか?


2
これは、いくつかの「修正された履歴の質問をどのようにプッシュするか」の「ほぼ」重複です。たとえば、こちらの回答をご覧ください。stackoverflow.com/ questions/ 253055/…
CB Bailey

2
それは本当であり、投稿する前にStackOverflowで回答を検索しました。しかし、私の検索ではgit push --forceが問題を修正した回答しか見つかりませんでした。投稿へのリンクをありがとう:)
robertpostill

2
間もなく(git1.8.5、2013年第4四半期)git push -forceより慎重実行できるようになります
VonC

回答:


287

プッシュを強制しても効果がない場合( "git push --force origin "または " git push --force origin master"で十分です)、リモートサーバーがreceive.denyNonFastForwards構成変数(説明についてはgit configのマンページを参照)を介して非早送りプッシュを拒否している可能性があります。または更新/事前受信フック経由。

古いGitでは、「git push origin :master」(ブランチ名の前の「:」を参照)を削除してから、「」のブランチを再作成することで、この制限を回避できますgit push origin master

これを変更できない場合、唯一の解決策は、履歴を次のように書き換えるのではなく、 、DEFで変更を元に戻すコミット作成するためにです。

ABCDEF-[(DEF)^-1]マスター

ABCDEFオリジン/マスター

2
@JakubNarębski、ありがとう。get revert HEAD~N助けた。Nコミット数です。たとえば、前のコミットが必要な場合は、次を使用しますgit revert HEAD~1
Maksim Dmitriev 2013

1
そして、あなたがこれを行うことによって、他のすべてのローカルマスターを壊すことに注意してください。
Tom Brito

24

Jakubの答えを補足するために、sshでリモートgitサーバーにアクセスできる場合は、gitリモートディレクトリに移動して次のように設定できます。

user@remote$ git config receive.denyNonFastforwards false

次に、ローカルリポジトリに戻り、次のコマンドでコミットを再試行します--force

user@local$ git push origin +master:master --force

最後に、サーバーの設定を元の保護状態に戻します。

user@remote$ git config receive.denyNonFastforwards true

これに関するsourceforge調整情報については、pete.akeo.ie / 2011/02 / denying-non-fast-forward-and.htmlも参照してください。
hlovdal 2014年

詳細な手順どのように使用して無効にdenyNonFastForwardsにviこのSOポストの上に提供されています。stackoverflow.com/a/43721579/2073804
ron190


1

gitリセットビジネス全体が、私を複雑にしているように見えました。

だから私はいくつかのコミットをしていた状態で私のsrcフォルダーを取得するために線に沿って何かをしました

# reset the local state
git reset <somecommit> --hard 
# copy the relevant part e.g. src (exclude is only needed if you specify .)
tar cvfz /tmp/current.tgz --exclude .git  src
# get the current state of git
git pull
# remove what you don't like anymore
rm -rf src
# restore from the tar file
tar xvfz /tmp/current.tgz
# commit everything back to git
git commit -a
# now you can properly push
git push

このように、srcの状態はtarファイルに保持され、gitは基本的にsrcディレクトリを何度も変更せずに強制的にこの状態を受け入れるように強制されます。


0

GitHubのユーザーにとって、これは私にとってはうまくいきました:

  1. 変更するブランチ保護ルールで、[強制プッシュを許可]が有効になっていることを確認します
  2. git reset --hard <full_hash_of_commit_to_reset_to>
  3. git push --force

これにより、ローカルマシンとGitHubサーバーのブランチ履歴が「修正」されますが、不正なコミット以降にこのブランチをサーバーと同期した人は、ローカルマシンの履歴を保持します。ブランチに直接プッシュする権限がある場合、これらのコミットは同期時にすぐに表示されます。

他のすべての人が行う必要があるのは、git resetローカルマシンのブランチを「修正」するための上記のコマンドです。もちろん、ターゲットハッシュのにこのブランチに対して行われたローカルコミットに注意する必要があります。Cherryの選択/バックアップを行い、必要に応じてそれらを再適用しますが、保護されたブランチにいる場合は、直接コミットできる人の数が制限される可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.