git rebaseを元に戻す


3179

どうすれば簡単に git rebaseを元戻すことができますか?

私の現在のアイデアは手動のアプローチのみです:

  1. git checkout 両方のブランチの親のコミット
  2. そこから一時ブランチを作成します
  3. git cherry-pick すべて手動でコミット
  4. リベースしたブランチを手動で作成したブランチに置き換える

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

しかし、私のアプローチは次善でエラーが発生しやすいと思います(自分の2つのブランチでリベースしたとしましょう)。

明確化:一連のコミットがリプレイされたリベースについて話している。1つだけではありません。


6
また、リベース中にコミットを除外したり、コミットしたりできることに注意してください。これらの変更は、元のノードへのポインターがないか、reflogをふるいにかけなければ元に戻せないため、チェリーピッキングは機能しません。
ANeves、2011

回答:


4337

最も簡単な方法は、リログが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}"ます。

ブランチごとのreflogsを無効にしていない場合はgit reflog branchname@{1}、最終的なヘッドに再接続する前に、リベースがブランチヘッドをデタッチするので、簡単に実行できるはずです。私はこれを最近確認していないので、これを再確認します。

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

[core]
    logAllRefUpdates = true

115
Git reflogは素晴らしいです。git log -g(Scott Chaconのprogit.org/bookからのヒントで)より良いフォーマットの出力を取得できることを覚えておいてください。
カルミ2010

60
@Zach: git rebase --abort-iとは意味がありませんが--abort- ;どちらか競合があったので、またはそれが対話型またはその両方だったので)完了していないリベースを放棄するためのものです 問題は、リベースの成功を取り消すことではありません。どちらかを使用するrebase --abortreset --hard、現在の状況に応じて、どちらかを実行する必要はありません。
CBベイリー2011年

311
念のため、最初にバックアップを作成してくださいgit tag BACKUP。何かがうまくいかない場合は、それに戻ることができます:git reset --hard BACKUP
kolypto

6
多数のコミットを行った場合、探しているHEAD @ {#}の前にはが付けcommit:られrebase:ます。当たり前のように聞こえますが、少し混乱しました。
Warpling

4
誤ってリベースした後にパーティーに参加する:D。git reset --hard ORIG_HEAD偶発的なリベースの直後に、トリックも行うのではないでしょうか?
quaylar 2013

1487

実際、リベースは開始点をに保存するORIG_HEADので、これは通常次のように簡単です。

git reset --hard ORIG_HEAD

しかし、resetrebaseそしてmerge元のセーブすべてHEADのポインタにORIG_HEADあなたが取り消ししようとしているリベースので、これらのコマンドのいずれかを行ってきたのであれば、あなたはREFLOGを使用する必要があります。


34
ORIG_HEAD不要になった場合は、branchName@{n}構文を使用することもできます。ここnで、は、ブランチポインターのn番目前の位置です。したがって、たとえば、featureAブランチをmasterブランチにリベースしたが、リベースの結果が気に入らないgit reset --hard featureA@{1}場合は、リベースを実行する前の状態にブランチをリセットすることができます。リビジョンの公式Gitドキュメント branch @ {n}構文の詳細を読むことができます。

15
これが最も簡単です。でもそれをフォローアップしてくださいgit rebase --abort
SEPH

1
@DaBlickは、で競合することなく完全にリベースが成功した後、私にとってはうまくいきましたgit 2.17.0
dvlsg 2018

4
補足すると、git reset --hard ORIG_HEAD繰り返し使用して何度もロールバックできます。たとえば、A --- rebase to --- B --- rebase to --- Cの場合、今Cにいるので、2回使用してAに戻ることができますgit reset --hard ORIG_HEAD
CalvinChe

5
@Sephフォローアップを提案する理由を説明できますgit rebase --abortか?
UpTheCreek

386

チャールズの答えは機能しますが、これを実行したい場合があります。

git rebase --abort

後の片付けreset

そうしないと、メッセージ「Interactive rebase already started」が表示される場合があります。


4
これにより、プロンプトの「| REBASE」部分が削除されました。+1
Wouter Thielen 14年

62
それは問題ではありませんでした。質問は、完成したリベースを元に戻す方法を尋ねます。
Arunav Sanyal 2017

2
チャールズの回答についてのコメントである必要があります。それは、質問については回答しないためです
Murmel '25

うーん、私はそれをする必要はありませんでした。
ViktorSeč19年

1
私のために働いた唯一のもの!
Alexandre Picard

90

ブランチを古いヒントのダングリングコミットオブジェクトにリセットすることは、最善の解決策です。これは、努力を費やすことなく以前の状態を復元するためです。ただし、これらのコミットを失った場合(たとえば、リポジトリがガベージコレクションされたため、またはこれが新しいクローンである場合など)、ブランチをいつでもリベースできます。これの鍵は--ontoスイッチです。

あなたが想像的に呼ばれたトピックブランチを持っていたとしましょうtopic、それはコミットのmaster先端で分岐したものです。ブランチのある時点で、あなたはそうしました。これを元に戻します。方法は次のとおりです。master0deadbeeftopicgit rebase master

git rebase --onto 0deadbeef master topic

これにより、オンになっtopicていないすべてのコミットが取得されmaster、の上で再生され0deadbeefます。

を使用すると--onto、履歴をほとんどすべての形に再配置できます。

楽しんで。:-)


3
柔軟性があるため、これが最良の選択肢だと思います。b1をマスターから分岐し、b1を新しいブランチb2にリベースしました。次に、b1を再びマスターに基づくように戻したいと思いました。私はgitが大好きです-ありがとう!
ripper234 2011

2
これはここでの最良のオプションです!現在のブランチにあるすべての変更が保持され、不要な変更がすべて削除されました!
Alicia Tang

私はの組み合わせでそれを言うだろう--ontoし、-iあなたはかなりの中にいかなる形状の履歴を並べ替えることができます。gitk(Macではgitx)を使用して、作成した形状を確認します:-)。
rjmunro 2018年

69

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

その後、復元はと同じくらい簡単git reset --hard BACKUPです。


2
私もそうします。意図したとおりに変更したことを確認するためにgit diff BACKUP..HEADをgitすることも役立ちます。
Paul Bone

5
私も以前はそうしていましたが、reflogに慣れたので、もう必要ではないと感じています。REFLOGは、HEADを変更するたびに、基本的にこれを代行しています。
ピートホジソン2012

4
まあ、私は意味のある名前を好む。なぜなら、reflogで適切なアイテムを検索することは時々まったく面白くないからだ。
Alex Gontmakher

12
実際には、バックアップブランチを作成する必要すらありません。branchName@{n}構文を使用するだけで済みnます。これは、ブランチポインターのn番目前の位置です。したがって、たとえば、featureAブランチをmasterブランチにリベースしたが、リベースの結果が気に入らないgit reset --hard featureA@{1}場合は、リベースを実行する前の状態にブランチをリセットすることができます。branch@{n}構文について詳しくは、公式のGitドキュメントのリビジョンをご覧ください。

2
実際、上記の構文を使用する必要すらありません。PatNotzの回答によるとHEAD、ブランチのオリジナルは一時的にに保存されORIG_HEADます。しかし、バックアップブランチラベルを使用する手法も機能します。これは、単なる追加手順です。

68

場合はリモートリポジトリにブランチをプッシュしていた((通常はそれの起源)、その後、あなたは(マージなし)succesfullのリベースを行ってきたgit rebase --abortあなたが簡単にできる「いいえ進行中リベース」を与える)リセット枝のコマンドを使用して:

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

それが正解です。リベース前のリベースとコミットは同じコミットIDを持っていたため、HEAD {1}に戻ってもリベースは元に戻りませんでした。
Bill Kotsias 2017

23

を使用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


3
おっと-そのリンクから、「1つの注意点があります。ブランチの履歴を失いましたが、この場合、それは問題ではありませんでした。変更を取得できてうれしかったです。」?
ruffin 2012

16

複数のコミットの場合、コミットはそのコミットに至るまでのすべての履歴を参照することに注意してください。したがって、チャールズの回答では、「古いコミット」を「最新の古いコミット」と読みます。そのコミットにリセットすると、そのコミットに至るまでのすべての履歴が再表示されます。これはあなたが望むことをするはずです。


11

@Allanと@Zearinの解決策に従って、単にコメントを付けたいと思いますが、評判が足りないため、次のコマンドを使用しました。

代わりにやってのgit rebase -i --abort (注意-iを)私は単純にしなければならなかったgit rebase --abortなし-i)。

両方-i--abort同時に使用すると、Gitに使用法/オプションのリストが表示されます。

したがって、このソリューションでの以前のブランチと現在のブランチのステータスは次のとおりです。

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

11

リモートブランチに基づいて正常にリベースでき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

4

マスターを機能ブランチにリベースし、何かを壊す30の新しいコミットを取得したとしましょう。多くの場合、不良コミットを削除するのが最も簡単です。

git rebase -i HEAD~31

過去31回のコミットのインタラクティブなリベース(選択の数が多すぎても問題ありません)。

単に、取り除きたいコミットを取り、「ピック」ではなく「d」でそれらをマークします。これで、コミットが効果的に削除され、リベースが取り消されました(リベース時に取得したコミットのみを削除した場合)。


3

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

git reflog

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

git checkout HEAD@{57}

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

git checkout -b new_branch_name

2

あなたがブランチにいるなら、あなたは使うことができます:

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_HEADgit resetインタラクティブで使用した場合は機能しませんrebase


1

私が普段していることは git reset #commit_hash

リベースが効果がないと思う最後のコミットまで。

その後 git pull

これで、ブランチはマスターとまったく同じように一致し、リベースされたコミットはそこに含まれてはなりません。

これで、このブランチのコミットを簡単に選択できます。


1

私はすべての提案をリセットとreflogで試みましたが、成功しませんでした。IntelliJのローカル履歴を復元すると、ファイルが失われる問題が解決しました


ありがとう!以前にローカル履歴を使用したことはありませんが、これは、誤ってリベースしたコードを回復するための最も簡単なオプションであることがわかりました。とても素敵ですが、やや隠された機能です。
マグナスW

0

git reset --hard origin / {branchName}

リベースによって行われたすべてのローカル変更をリセットする正しいソリューションです。


1
ハードリセットするorigin/branchと、HEADとそのポイントの間の変更が失われる可能性があります。あなたはそれを一般的に言って欲しくない。
bluesmonk

これはまさに私の場合に欲しかったものです。とても賛成です。
Mandar Vaze、

-4

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


5
git rebase --abortアクティブなリベースを中止し、リベースを取り消すことはありません。また、2つのVCSを同時に使用することはお勧めできません。Jetbrainsソフトウェアの優れた機能ですが、両方を使用しないでください。特にGitに関するStack Overflowの質問に答える場合は、Gitを学ぶだけの方が良いでしょう。
dudewad
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.