質問

gitリベースを簡単に元に戻す方法を知っている人はいますか?

思いつく唯一の方法は、手動で実行することです。

  • git checkout 両方のブランチの親をコミットします
  • そこから一時ブランチを作成します
  • すべてのコミットを手動でチェリーピックする
  • リベースしたブランチを手動で作成したブランチに置き換えます

私の現在の状況では、両方のブランチからのコミットを簡単に見つけることができるので、これはうまくいきます(1つは私のもので、もう1つは同僚のものでした)。

ただし、私のアプローチは最適ではなく、エラーが発生しやすいように思えます (自分のブランチ 2 つをリベースしたばかりだとします)。

何か案は?

説明:私は、大量のコミットが再実行されるリベースについて話しています。一つだけではありません。

役に立ちましたか?

解決

最も簡単な方法は、リベースが開始される直前のブランチのヘッド コミットを見つけることです。 レフログ...

git reflog

そして、現在のブランチをそこにリセットします (リセットする前に絶対に確実であることについての通常の注意事項があります) --hard オプション)。

古いコミットが HEAD@{5} 参照ログ内:

git reset --hard HEAD@{5}

Windows では、参照を引用する必要がある場合があります。

git reset --hard "HEAD@{5}"

を実行するだけで、旧ヘッド候補の履歴を確認できます。 git log HEAD@{5} (ウィンドウズ: git log "HEAD@{5}").

ブランチごとの reflog を無効にしていない場合は、次のようにするだけで済みます。 git reflog branchname@{1} リベースでは、最終ヘッドに再アタッチする前にブランチ ヘッドがデタッチされるためです。最近確認していないので再度確認してみます。

デフォルトでは、すべての reflog が非ベア リポジトリに対してアクティブ化されます。

[core]
    logAllRefUpdates = true

他のヒント

実際、リベースにより開始点が保存されます。 ORIG_HEAD したがって、これは通常次のように単純です。

git reset --hard ORIG_HEAD

しかし reset, rebase そして merge すべてオリジナルを保存してください HEAD へのポインタ ORIG_HEAD したがって、リベース以降にこれらのコマンドのいずれかを実行して元に戻そうとしている場合は、reflog を使用する必要があります。

Charles の答えは機能しますが、次のようにすることもできます。

git rebase --abort

後片付けをする reset.

そうしないと、「Interactive rebase already started”.

git reflog リベース前後のすべての変更が表示され、リセットする適切な変更を見つけることができます。しかし、ここでこの他の超簡単な方法についてまだ誰も言及していないことに私は驚きました。

リベースでは古い状態がそのまま残ります ORIG_HEAD, したがって、次を実行することで最後のリベースを元に戻すことができます。

git reset --hard ORIG_HEAD

もちろん、ブランチを古いチップのダングリングコミットオブジェクトにリセットするのが最善の解決策です。これにより、労力を費やすことなく以前の状態が復元されます。しかし、それらのコミットをたまたま紛失してしまった場合 (f.ex.その間にリポジトリをガベージ コレクションしたため、またはこれが新しいクローンであるため)、いつでもブランチを再度リベースできます。この鍵となるのは、 --onto スイッチ。

想像的に次のようなトピック ブランチがあるとします。 topic, 、分岐したこと master の先端のとき master でした 0deadbeef 専念。ある時点で topic 支店、やったね git rebase master. 。ここで、これを元に戻したいとします。その方法は次のとおりです。

git rebase --onto 0deadbeef master topic

これにより、すべてのコミットが取得されます topic オンになっていないもの master そしてそれらを上に再生します 0deadbeef.

--onto, 、自分の歴史をかなり並べ替えることができます どんな形でも.

楽しむ。:-)

実際、重要な操作を実行する前に、ブランチにバックアップ タグを置きます (ほとんどのリベースは簡単ですが、複雑に見える場合はそうします)。

その後、復元は次のように簡単です git reset --hard BACKUP.

万一に備えて ブランチをリモート リポジトリにプッシュしました (通常はオリジンです)そして、(マージなしで)リベースが成功しました(git rebase --abort 「進行中のリベースはありません」と表示されます) ブランチをリセットする コマンドの使用:

git restart --hardorigin/{ブランチ名}

例:

$ ~/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 私にはうまくいきませんでした。

私にとってうまくいったのは説明と同様でした ここ. 。リベースされたブランチにちなんで名付けられた .git/logs/refs 内のファイルを開き、次のような「rebase finsihed」を含む行を見つけます。

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

その行にリストされている 2 番目のコミットをチェックアウトします。

git checkout 88552c8f

これに失われた変更が含まれていることを確認すると、分岐して安堵のため息をつきました。

git log
git checkout -b lost_changes

複数のコミットの場合、どのコミットもそのコミットに至るまでのすべての履歴を参照することに注意してください。したがって、Charles の答えでは、「古いコミット」を「古いコミットの最新のもの」と読み替えてください。そのコミットにリセットすると、そのコミットに至るまでのすべての履歴が再び表示されます。これで希望通りのことができるはずです。

@Allan と @Zearin の解決策に従って、単純にコメントできればよかったのですが、十分な評判がないので、次のコマンドを使用しました。

する代わりに git rebase -i --abort (注意してください -私)私はただそうする必要がありました git rebase --abort (それなし-私).

両方を使用する -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 # オリジンが認識している最新の状態にチェックアウトします
  • git checkout -b your-branch
  • チェック git log your-branch-rebased, 、と比較してください git log your-branch 欠落しているコミットを定義します your-branch
  • git cherry-pick COMMIT_HASH コミットごとに your-branch-rebased
  • 変更をプッシュします。2 つのローカル支店が関連付けられていることに注意してください。 remote/your-branch そしてあなたはプッシュするだけでいいです your-branch

master を自分の feature ブランチにリベースし、何かを壊す新しいコミットが 30 個得られたとします。多くの場合、不正なコミットを削除するのが最も簡単であることがわかりました。

git rebase -i HEAD~31

最新の 31 コミットの対話型リベース (選択しすぎても問題ありません)。

削除したいコミットを選択し、「pick」の代わりに「d」でマークを付けるだけです。これで、コミットが削除され、事実上リベースが取り消されます (リベース時に取得したばかりのコミットのみを削除した場合)。

ブランチにいる場合は、以下を使用できます。

git reset --hard @{1}

HEAD の参照ログだけが存在するわけではありません(によって取得されます) git reflog)、各ブランチの reflog もあります (次によって取得されます)。 git reflog <branch>)。それで、あなたがオンの場合は、 master それから git reflog master そのブランチに対するすべての変更をリストします。変更内容を参照できます。 master@{1}, master@{2}, 、など。

git rebase 通常、HEAD は複数回変更されますが、現在のブランチは 1 回だけ更新されます。

@{1} は単に 現在のブランチのショートカット, したがって、次と等しいです。 master@{1} あなたがオンなら master.

git reset --hard ORIG_HEAD 使用した場合は機能しません git reset インタラクティブ中に rebase.

初心者やハード リセットを行うのが怖い人は、reflog からコミットをチェックアウトして、新しいブランチとして保存できます。

git reflog

リベースを開始する直前のコミットを見つけます。見つけるには、さらに下にスクロールする必要がある場合があります (Enter キーまたは PageDown キーを押します)。HEAD 番号をメモし、57 を置き​​換えます。

git checkout HEAD@{57}

ブランチ/コミットを確認し、問題がないようであれば、この HEAD を使用して新しいブランチを作成します。

git checkout -b new_branch_name

git restart --hardorigin/{ブランチ名}

これは、リベースによって行われたすべてのローカル変更をリセットするための正しい解決策です。

私が普段やっていることは、git reset #commit_hash

リベースが効果がなかったと思われる最後のコミットまで。

それから git pull

これで、ブランチはマスターと完全に一致し、リベースされたコミットがブランチ内に存在しないはずです。

これで、このブランチ上のコミットを厳選することができます。

git rebase 内で何かを台無しにした場合、たとえば git rebase --abort, コミットされていないファイルがある間は、それらは失われ、 git reflog 役に立ちません。これは私に起こったことであり、ここでは既成概念にとらわれずに考える必要があります。私のように幸運で IntelliJ Webstorm を使用している場合は、次のことができます。 right-click->local history また、バージョン管理ソフトウェアでどんな間違いを犯したとしても、ファイル/フォルダーを以前の状態に戻すことができます。別のフェールセーフを実行しておくことは常に良いことです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top