修正されたコミットをリモートGitリポジトリにプッシュするにはどうすればよいですか?
-
05-07-2019 - |
質問
ソースコードを少し使用して、通常のコミットを行った後、リモートリポジトリにプッシュしました。しかし、その後、インポートをソースコードで整理するのを忘れていました。したがって、前のコミットを置き換えるために修正コマンドを実行します。
> git commit --amend
残念ながら、コミットをリポジトリにプッシュバックすることはできません。次のように拒否されます:
> 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/'
どうすればよいですか? (リモートリポジトリにアクセスできます。)
解決
実際に一度--force
と.git
リポジトリでプッシュし、Linus BIG TIME にscられました。一般的に、これは他の人にとって多くの問題を作成します。簡単な答えは<!> quot;しないでください<!> quot;。
とにかくそうするためのレシピを他の人がくれたので、ここでは繰り返しません。しかし、-force(または+ master)を使用して修正されたコミットをプッシュした後、 状況から回復するためのヒントがあります。
-
git reflog
を使用して、修正した古いコミットを見つけます(old
と呼びます。new
を修正して作成した新しいコミットを呼び出します)。 -
git checkout new && git merge -s ours old
とgit merge master
の間にマージを作成し、git push . HEAD:master
のような<=>のツリーを記録します。 - <=> でそれをマスターにマージします
- <=> の結果でマスターを更新します
- 結果をプッシュします。
その後、プッシュを修正および強制することで削除されたコミットに基づいて作業を行うことができなかった人々は、マージの結果、<=>よりも<=>が優先されることがわかります。後のマージでは、修正によって生じた<=>と<=>の間の競合は見られないため、それらを苦労する必要はありません。
他のヒント
Gitの安全機能が表示されています。ブランチのヘッドコミットはプッシュ先のブランチの現在のヘッドコミットの直接の子孫ではないため、Gitはブランチでリモートブランチを更新することを拒否します。
これが当てはまらない場合、ほぼ同時に同じリポジトリにプッシュする2人は、新しいコミットが同時に入っていることを知らず、最後にプッシュした人は前のプッシャーの作業を失いますどちらもこれに気付かないで。
自分がプッシュする唯一の人物であり、修正されたコミットをプッシュするか、ブランチを巻き戻すコミットをプッシュする場合、-f
スイッチを使用してGitを強制的にリモートブランチを更新できます。
git push -f origin master
Gitではリモートリポジトリが設定変数receive.denynonfastforwards
を使用して遠端での非早送りプッシュを拒否できるため、これでも機能しない場合があります。この場合、拒否理由は次のようになります(「リモート拒否」部分に注意してください):
! [remote rejected] master -> master (non-fast forward)
これを回避するには、リモートリポジトリの構成を変更するか、ダーティハックとしてブランチを削除して再作成する必要があります。
git push origin :master
git push origin master
一般に、git push
の最後のパラメーターは<local_ref>:<remote_ref>
の形式を使用します。ここで、local_ref
はローカルリポジトリのブランチの名前で、remote_ref
はリモートリポジトリのブランチの名前です。このコマンドペアは、2つの略記法を使用します。 :master
にはnull local_refがあります。これは、nullブランチをリモート側master
にプッシュする、つまりリモートブランチを削除することを意味します。 :
のないブランチ名は、指定された名前のローカルブランチを同じ名前のリモートブランチにプッシュすることを意味します。 master:master
この状況では<=>の略です。
簡単な暴言:誰もここに簡単な答えを投稿していないという事実は、Git CLIが示す絶望的なユーザーの敵意を示しています。
とにかく、<!> quot;明白な<!> quot;これを行う方法は、プッシュを強制しようとしていないと仮定して、最初にプルすることです。これにより、変更した変更がプルされるため、変更はなくなります。
競合を解決したら、もう一度プッシュできます。
だから:
git pull
プルでエラーが発生した場合、ローカルリポジトリの設定に問題がある可能性があります(.git / configブランチセクションの参照が間違っていました)。
その後
git push
たぶん、サブジェクトが<!> quot; Trivial merge <!> quot;について言っている追加のコミットを受け取るでしょう。
簡単な答え:修正されたコミットを公開リポジトリにプッシュしないでください。
長答:git commit --amend
やgit rebase
などのいくつかのGitコマンドは、実際に履歴グラフを書き換えます。変更を公開していない限りこれは問題ありませんが、一度変更したら、履歴をいじってはいけません。なぜなら、誰かが既に変更を取得している場合、再度プルしようとすると失敗する可能性があるからです。 。コミットを修正する代わりに、変更を加えて新しいコミットを作成する必要があります。
ただし、修正されたコミットを本当に本当にプッシュしたい場合は、次のようにすることができます:
$ git push origin +master:master
<!> quot; fast-forward <!> quotにならなくても、先頭の+
記号はプッシュを強制的に発生させます。コミット。 (プッシュする変更が既にパブリックリポジトリにある変更の直接の子孫である場合、早送りコミットが発生します。)
commit --amend
:
を行った後、変更をプッシュする非常にシンプルでクリーンな方法を次に示します。
git reset --soft HEAD^
git stash
git push -f origin master
git stash pop
git commit -a
git push origin master
次のことを行います:
- ブランチヘッドを親コミットにリセットします。
- この最後のコミットを隠してください。
- リモートへの強制プッシュ。リモートには最後のコミットがありません。
- 隠しておく。
- 完全にコミットします。
- リモートにプッシュします。
<!> quot; origin <!> quot;の変更を忘れないでください。および<!> quot; master <!> quot;これを別のブランチまたはリモートに適用する場合。
ローカルの修正されたコミットを破棄し、新しい変更を上に追加することで解決しました:
# 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
同じ問題が発生しました。
- すでにプッシュされた最後のコミットを誤って修正しました
- ローカルで多くの変更を行い、約5回コミットしました
- プッシュしようとした、エラーが発生した、パニックに陥った、リモートをマージした、多くの非my-fileを取得した、プッシュした、失敗したなど。
Git初心者として、完全な FUBAR と思いました。
解決策:@baraが提案した+ローカルバックアップブランチを作成したようなもの
# 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
多分それは速くてきれいな解決策ではなく、履歴を失いました(5ではなく1コミット)が、1日の作業を節約しました。
コードをリモートブランチ(GitHub / Bitbucket)にプッシュしていない場合は、コマンドラインのコミットメッセージを以下のように変更できます。
git commit --amend -m "Your new message"
特定のブランチで作業している場合、これを行います:
git commit --amend -m "BRANCH-NAME: new message"
すでに間違ったメッセージでコードをプッシュしている場合は、メッセージを変更するときに注意する必要があります。つまり、コミットメッセージを変更してからもう一度プッシュしてみると、問題が発生します。スムーズにするには、次の手順を実行します。
回答する前に回答全体を読んでください
git commit --amend -m "BRANCH-NAME : your new message"
git push -f origin BRANCH-NAME # Not a best practice. Read below why?
重要な注意:強制プッシュを直接使用すると、他の開発者が同じブランチで作業しているというコードの問題が発生する場合があります。したがって、これらの競合を回避するには、強制プッシュを行う前にブランチからコードをプルする必要があります。
git commit --amend -m "BRANCH-NAME : your new message"
git pull origin BRANCH-NAME
git push -f origin BRANCH-NAME
これは、コミットメッセージが既にプッシュされている場合、コミットメッセージを変更する際のベストプラクティスです。
未修正のコミットを誰もプルしていないことがわかっている場合は、--force-with-lease
のgit push
オプションを使用します。
TortoiseGitでは、<!> quot; Push ... <!> quot;で同じことができます。 options <!> quot; Force:破棄する可能性があります<!> quot; <!> quot;既知の変更<!> quot;をチェックします。
強制(既知の変更を破棄できる)により、リモートリポジトリが許可されます。より安全な非早送りプッシュを受け入れます。これにより、リモートリポジトリのコミットが失われる可能性があります。注意して使用してください。これにより、リモート上の他の人からの不明な変更が失われないようにすることができます。サーバーブランチがリモートトラッキングブランチと同じコミットを指しているかどうかを確認します(既知の変更)。はいの場合、強制プッシュが実行されます。それ以外の場合は拒否されます。 gitにはリモートトラッキングタグがないため、このオプションを使用してタグを上書きすることはできません。
これは、すでにgit add "your files"
およびgit commit --amend
を行った後に変更をプッシュする非常にシンプルでクリーンな方法です。
git push origin master -f
または:
git push origin master --force
Gitリモートにはすでにこれらのコミットファイルがあるため、このエラーが発生しています。これを機能させるには、ブランチを強制的にプッシュする必要があります:
git push -f origin branch_name
また、チームの他の誰かが同じブランチにプッシュした可能性があるため、リモートからコードをプルするようにしてください。
git pull origin branch_name
これは、コミットをリモートに強制的にプッシュする必要がある場合の1つです。
リモートリポジトリからプルしてこの問題を修正し、発生したコミットの競合を処理してから、プッシュしてプッシュする必要がありました。しかし、もっと良い方法があるように感じます。
Gitに指示されたことを実行し続けました。だから:
- コミットが修正されたためプッシュできません。
- 提案どおりにプルします。
- マージは失敗します。手動で修正します。
- 新しいコミットを作成します(ラベル付き <!> quot; merge <!> quot;)プッシュします。
- 機能しているようです!
注:修正されたコミットは最新のものでした。
ここで、以前のコミットで編集を修正した方法:
- これまでの作業を保存します。
- 変更が行われた場合は、今のところ変更を隠してください:
git stash
これで、作業コピーは最後のコミットの状態でクリーンになりました。 - 編集と修正を行います。
- <!> quot; amend <!> quot; モードで変更をコミットします:
git commit --all --amend
-
ログメッセージ(デフォルトでは古いログメッセージ)を求めるエディターが表示されます。満足したらエディタを保存して終了します。
新しい変更は、古いコミットに追加されます。
git log
およびgit diff HEAD^
で自分の目で確かめてください
-
隠された変更を再適用する場合は、再適用します:
git stash apply