web-dev-qa-db-ja.com

Git rebaseを元に戻す

誰かが簡単にgit rebaseを元に戻す方法を知っていますか?

頭に浮かぶ唯一の方法はそれを手動で調べることです:

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

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

しかし、私のアプローチでは、最適ではなく、エラーが発生しやすいものになってしまいました(2つのブランチでリベースしたばかりの場合を考えてみましょう)。

何か案は?

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

2632
webmat

最も簡単な方法は、 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
3645
CB Bailey

実際、rebaseは開始点をORIG_HEADに保存するので、これは通常次のように単純です。

git reset --hard ORIG_HEAD

ただし、resetrebasemergeはすべて元のHEADポインタをORIG_HEADに保存するため、元に戻そうとしているリベース以降にこれらのコマンドを実行した場合は、reflogを使用する必要があります。

1297
Pat Notz

チャールズの答えはうまくいくが、あなたはこれをしたいかもしれない:

git rebase --abort

resetの後にクリーンアップします。 

そうでなければ、メッセージ「Interactive rebase already started」を受け取るかもしれません。

338
Allan

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

Rebaseは古い状態をORIG_HEADのままにするので、最後のリベースを元に戻すには、次のコマンドを実行します。

git reset --hard ORIG_HEAD
80
Meligy

ブランチを古いtipのdangling commitオブジェクトにリセットすることは、もちろん最善の解決策です。何の手間もかけずに以前の状態を復元するからです。しかし、たまたまコミットを失ってしまった場合(その間にリポジトリをガベージコレクションしたため、またはこれが新しいクローンであるため)、いつでもブランチをリベースすることができます。その鍵は--ontoスイッチです。

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

git rebase --onto 0deadbeef master topic

これは、topicにない全てのmasterに対するコミットを取り、それらを0deadbeefの上で再生します。

--ontoを使えば、あなたの歴史をほぼどんな形のものでもに再編成することができます。

楽しむ。 :-)

79

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

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

64
Alex Gontmakher

ブランチをリモートリポジトリにプッシュした(通常は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
60
Maksym

あなたがリベースを完了しておらず、その途中であれば、以下のように動作します。

git rebase --abort
51
Alex

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
17
Kris

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

15
Greg Hewgill

@Allanと@Zearinの解決策に従って、単にコメントを書くことができればいいのですが評判が足りないので、次のコマンドを使用しました。

git rebase -i --abort-iに注意)の代わりに、単にgit rebase --abortwithout the -i)をしなければなりませんでした。

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

そのため、このソリューションでの私の以前および現在のブランチのステータスは次のとおりです。

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

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

リモートブランチに対してリベースに成功し、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
  • 変更をプッシュします。 2つのローカルブランチがremote/your-branchに関連付けられており、your-branchのみをプッシュする必要があることに注意してください
11

マスターを私の機能ブランチにリベースしたところ、30の新しいコミットが発生して何かが壊れたとしましょう。悪いコミットを削除するのが最も簡単なことがよくあります。

git rebase -i HEAD~31

最後の31のコミットのための対話型リベース(あなたがあまりにも多くの方法を選んでもそれは害はありません)。

単にあなたが取り除きたいコミットを取り、それらを "pick"の代わりに "d"でマークしてください。これでコミットはリベースを元に戻すために効果的に削除されます(リベース時に取得したコミットのみを削除した場合)。

3
Hardev

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

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

次にgit pull

これで、ブランチはマスターとまったく同じように一致し、リベースされたコミットはその中にないはずです。

これで、このブランチのコミットをチェリーピックすることができます。

1
mrigendra

あなたが枝にいるなら、あなたは使うことができます:

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は機能しません。

1
devconsole

初心者や誰かがハードリセットをするのを怖がっているなら、reflogからコミットをチェックアウトして、それを新しいブランチとして保存することができます。

git reflog

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

git checkout HEAD@{57}

このHEADを使用して新しいブランチを作成し、問題がなければブランチ/コミットを確認してください。

git checkout -b new_branch_name
0
Andrew

git reset - ハードオリジン/ {branchName}

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

0
Damodar P