Gitで失われたコミットを回復するにはどうすればよいですか?


258

最初に、「ブランチが3回のコミットでオリジン/マスターよりも進んでいます」が取得され、その後、私のアプリは以前の変更で以前の状態に戻りました。

過去11時間に費やしたものを元に戻すにはどうすればよいですか?


回答:


587

git reflogあなたの友だちです。そのリストで使用したいコミットを見つけたら、それにコミットできます(例:)git reset --hard e870e41

(変更をコミットしなかった場合...問題が発生する可能性があります-早期にコミットし、頻繁にコミットしてください!)


5
見てくださいgit log HEAD@{1}。それが正しい一連のコミットのように見える場合は、できgit reset HEAD@{1}ます。
アンバー

4
コードがステージングされた場合(git addを使用)、それらはgitに保持され、などのコマンドを使用して簡単に見つけることができますgit fsck --lost-found
ランディーズ2017

2
リベース時に保持しておくべきだったコミットを誤って削除しました。これにより、数時間分の作業をやり直す必要がなくなりました。
1

27
これは私の命を救った。
Lutaaya Huzaifah Idris

6
これは私の正気を救いました:D
フランクファハルド

119

答える前に、背景を追加して、これHEADが何であるかを説明しましょう。

First of all what is HEAD?

HEAD現在のブランチ上の現在のコミット(最新)への参照です。
常に1つしか存在できませんHEAD(を除くgit worktree)。

の内容HEADは内部に格納され.git/HEAD、現在のコミットの40バイトのSHA-1が含まれています。


detached HEAD

最新のコミットを行っていない場合、つまりHEAD、履歴内の以前のコミットを指している場合は、と呼ばれdetached HEADます。

ここに画像の説明を入力してください

コマンドラインでは、次のようになります- HEADは現在のブランチの先端を指していないため、ブランチ名の代わりにSHA-1 :

ここに画像の説明を入力してください

ここに画像の説明を入力してください


切り離されたヘッドから回復する方法に関するいくつかのオプション:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

これにより、目的のコミットを指す新しいブランチがチェックアウトされます。
このコマンドは、特定のコミットにチェックアウトします。
この時点で、ブランチを作成して、この時点から作業を開始できます。

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

いつでも使用できreflogます。
git reflog を更新した変更が表示さHEADれ、目的のreflogエントリをチェックアウトすると、HEADこのコミットに戻ります。

HEADが変更されるたびに、新しいエントリが reflog

git reflog
git checkout HEAD@{...}

これにより、目的のコミットに戻ります

ここに画像の説明を入力してください


git reset --hard <commit_id>

HEADを目的のコミットに「移動」します。

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • 注:(Git 2.7以降)も使用できgit rebase --no-autostashます。

git revert <sha-1>

指定されたコミットまたはコミット範囲を「元に戻す」。
リセットコマンドは、指定されたコミットで行われた変更を「取り消し」ます。
元に戻すコミットを含む新しいコミットはコミットされますが、元のコミットも履歴に残ります。

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

このスキーマは、どのコマンドが何を実行するかを示しています。
ご覧のとおり、をreset && checkout変更しHEADます。

ここに画像の説明を入力してください


2
あなたはヒーローです、サー
dylanh724

4
それだけで多くの時間を節約できました。「git reflog --date = iso」を使用して、各エントリの日付/時刻を確認しました。これは、タイムスタンプがないと確実に判断できないためです。
MetalMikester 2018

1
私にとって、でgit reset --hard <commit_id>、削除HEADはうまくいきました!グラフィカル表現の+1 !!
reverie_ss 2018

ちょうど言及します:ブランチ名がわかっている場合:git reflog <branchname>1つのブランチの変更のみが表示されるため、非常に便利です。
Markus Schreiber

35

削除されたコミットを取得する別の方法は、git fsckコマンドを使用することです。

git fsck --lost-found

これは最終行のようなものを出力します:

dangling commit xyz

reflog他の回答で提案されているのと同じコミットであることを確認できます。今、私たちはすることができますgit merge

git merge xyz

注:ダングリングコミットへの参照を削除するコマンドをすでに実行している場合は
、コミットを取り戻すことはできません。fsckgit gc


3
これは、ブランチをフェッチしてからそのブランチを誤って別の場所にリセットした場合など、問題のコミットを最近指していない場合に機能する唯一の回答です。
TamaMcGlinn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.