誰かが簡単にgit rebaseを元に戻す方法を知っていますか?
頭に浮かぶ唯一の方法はそれを手動で調べることです:
私の現在の状況では、両方のブランチからコミットを簡単に見つけることができるので、これはうまくいきます(1つは私のもの、もう1つは私の同僚のもの)。
しかし、私のアプローチでは、最適ではなく、エラーが発生しやすいものになってしまいました(2つのブランチでリベースしたばかりの場合を考えてみましょう)。
何か案は?
明確化:私はたくさんのコミットがリプレイされたリベースについて話しています。一つだけではありません。
最も簡単な方法は、 reflog ...でリベースが開始される直前のブランチのヘッドコミットを見つけることです。
git reflog
現在のブランチをリセットします(--hard
オプションでリセットする前に絶対に確実であることについての通常の警告付きで)。
参照ログで古いコミットがHEAD@{5}
であったとします。
git reset --hard HEAD@{5}
Windowsでは、参照を引用する必要があるかもしれません:
git reset --hard "HEAD@{5}"
git log HEAD@{5}
( Windows: git log "HEAD@{5}"
)を実行するだけで、候補の古いヘッドの履歴を確認できます。
ブランチごとの再ログを無効にしていないのであれば、最後のヘッドに再アタッチする前に、リベースがブランチのヘッドをデタッチするので、単にgit reflog branchname@{1}
を実行できるはずです。私は最近これを確認していないので私はこれを二重点検する。
デフォルトでは、すべてのreflogは非ベアリポジトリに対してアクティブにされます。
[core]
logAllRefUpdates = true
実際、rebaseは開始点をORIG_HEAD
に保存するので、これは通常次のように単純です。
git reset --hard ORIG_HEAD
ただし、reset
、rebase
、merge
はすべて元のHEAD
ポインタをORIG_HEAD
に保存するため、元に戻そうとしているリベース以降にこれらのコマンドを実行した場合は、reflogを使用する必要があります。
チャールズの答えはうまくいくが、あなたはこれをしたいかもしれない:
git rebase --abort
reset
の後にクリーンアップします。
そうでなければ、メッセージ「Interactive rebase already started
」を受け取るかもしれません。
git reflog
は、リベース前後のすべての変更を表示し、リセットする正しい変更を見つけることを可能にします。しかし、私は誰もここでこの他の超単純な方法をまだ言及していないことに驚いています。
Rebaseは古い状態をORIG_HEAD
のままにするので、最後のリベースを元に戻すには、次のコマンドを実行します。
git reset --hard ORIG_HEAD
ブランチを古いtipのdangling commitオブジェクトにリセットすることは、もちろん最善の解決策です。何の手間もかけずに以前の状態を復元するからです。しかし、たまたまコミットを失ってしまった場合(その間にリポジトリをガベージコレクションしたため、またはこれが新しいクローンであるため)、いつでもブランチをリベースすることができます。その鍵は--onto
スイッチです。
topic
の先端が0deadbeef
コミットであったときにmaster
から分岐したと想像的にmaster
と呼ばれるトピックブランチがあったとしましょう。 topic
ブランチにいる間のある時点で、あなたはgit rebase master
をしました。今、あなたはこれを元に戻したいです。方法は次のとおりです。
git rebase --onto 0deadbeef master topic
これは、topic
にない全てのmaster
に対するコミットを取り、それらを0deadbeef
の上で再生します。
--onto
を使えば、あなたの歴史をほぼどんな形のものでもに再編成することができます。
楽しむ。 :-)
重要な操作を行う前に、実際にブランチにbackupタグを付けます(ほとんどのリベースは簡単ですが、複雑な場合はそうします)。
その後、復元はgit reset --hard BACKUP
と同じくらい簡単です。
ブランチをリモートリポジトリにプッシュした(通常はOrigin)で、成功したリベース(マージなし)を実行した場合(git rebase --abort
は「リベース中にリベースなし」) reset branchコマンドを使用して簡単にできます:
git reset --hard Origin/{branchName}
例:
$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'Origin/{branchName}' by 135 commits.
(use "git Push" to publish your local commits)
nothing to commit, working directory clean
$ ~/work/projects/{ProjectName} $ git reset --hard Origin/{branchName}
HEAD is now at 6df5719 "Commit message".
$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'Origin/{branchName}.
nothing to commit, working directory clean
あなたがリベースを完了しておらず、その途中であれば、以下のように動作します。
git rebase --abort
reflog
を使ってもうまくいきませんでした。
私にとってうまくいったことは here の説明と似ていました。リベースされたブランチにちなんで名付けられた.git/logs/refsにあるファイルを開き、 "rebase finsihed"を含む行を見つけてください。
5fce6b51 88552c8f Kris Leech <[email protected]> 1329744625 +0000 rebase finished: refs/heads/integrate onto 9e460878
行にリストされている2番目のコミットをチェックアウトしてください。
git checkout 88552c8f
これが確認されたら、これは私が分岐して安心のため息をついた私の失われた変更を含んでいました。
git log
git checkout -b lost_changes
複数のコミットの場合、コミットはそのコミットまでのすべての履歴を参照します。チャールズの答えでは、「古いコミット」を「最も古いコミットのうちの最新のもの」と読んでください。そのコミットにリセットすると、そのコミットまでのすべての履歴が再表示されます。これはあなたが望むことをするはずです。
@Allanと@Zearinの解決策に従って、単にコメントを書くことができればいいのですが評判が足りないので、次のコマンドを使用しました。
git rebase -i --abort
(-iに注意)の代わりに、単にgit rebase --abort
(without the -i)をしなければなりませんでした。
-i
と--abort
の両方を同時に使用すると、Gitは使用法/オプションのリストを表示します。
そのため、このソリューションでの私の以前および現在のブランチのステータスは次のとおりです。
matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort
matbhz@myPc /my/project/environment (branch-123)
$
リモートブランチに対してリベースに成功し、git rebase --abort
できない場合でも、作業を保存するためのいくつかのトリックを実行でき、プッシュを強制しません。誤ってリベースされた現在のブランチがyour-branch
と呼ばれ、Origin/your-branch
を追跡しているとします
git branch -m your-branch-rebased
#現在のブランチの名前を変更git checkout Origin/your-branch
#Originが認識している最新の状態にチェックアウトするgit checkout -b your-branch
git log your-branch-rebased
を確認し、git log your-branch
と比較して、your-branch
にないコミットを定義しますgit cherry-pick COMMIT_HASH
のすべてのコミットに対してyour-branch-rebased
remote/your-branch
に関連付けられており、your-branch
のみをプッシュする必要があることに注意してくださいマスターを私の機能ブランチにリベースしたところ、30の新しいコミットが発生して何かが壊れたとしましょう。悪いコミットを削除するのが最も簡単なことがよくあります。
git rebase -i HEAD~31
最後の31のコミットのための対話型リベース(あなたがあまりにも多くの方法を選んでもそれは害はありません)。
単にあなたが取り除きたいコミットを取り、それらを "pick"の代わりに "d"でマークしてください。これでコミットはリベースを元に戻すために効果的に削除されます(リベース時に取得したコミットのみを削除した場合)。
私が普段やっていることはgit reset #commit_hash
リベースは効果がないと思う最後のコミットまで。
次にgit pull
これで、ブランチはマスターとまったく同じように一致し、リベースされたコミットはその中にないはずです。
これで、このブランチのコミットをチェリーピックすることができます。
あなたが枝にいるなら、あなたは使うことができます:
git reset --hard @{1}
HEADの参照ログ(git reflog
によって取得)だけでなく、各ブランチの参照ログ(git reflog <branch>
によって取得)もあります。ですから、もしあなたがmaster
を使っているなら、git reflog master
はそのブランチへのすべての変更をリストします。その変更はmaster@{1}
、master@{2}
などで参照できます。
git rebase
は通常HEADを複数回変更しますが、現在のブランチは一度だけ更新されます。
@{1}
は単に現在のブランチの ショートカット なので、あなたがmaster
を使用している場合はmaster@{1}
と同じです。
対話的なrebase
中にgit reset --hard ORIG_HEAD
を使用した場合、git reset
は機能しません。
初心者や誰かがハードリセットをするのを怖がっているなら、reflogからコミットをチェックアウトして、それを新しいブランチとして保存することができます。
git reflog
リベースを開始する直前にコミットを見つけます。それを見つけるためにさらに下にスクロールする必要があるかもしれません(EnterまたはPageDownを押します)。 HEAD番号を書き留めて、57を置き換えます。
git checkout HEAD@{57}
このHEADを使用して新しいブランチを作成し、問題がなければブランチ/コミットを確認してください。
git checkout -b new_branch_name
git reset - ハードオリジン/ {branchName}
リベースによって行われたすべてのローカルの変更をリセットするための正しい解決策です。