どうすればgit reset --hard HEAD〜1を元に戻すことができますか?


1159

次のコマンドによる変更を元に戻すことはできますか?もしそうなら、どうですか?

git reset --hard HEAD~1

8
gitで失われたコミットを回復するための完全なガイドを書きました。それも、イラストを持っている:-) [fixLink] [fixLink] [それをチェックアウト]:programblings.com/2008/06/07/...
webmat

12
--hardコミットされていない変更を破棄します。これらはgitによって追跡されないため、gitを介して復元する方法はありません。
Zaz 2013


1
これは、ファイルの回復に役立つ優れた記事です。
Jan Swart 2016年

2
これはGithubから直接提供された優れたリソースです
。Git

回答:


1774

パットノッツは正しいです。数日以内であれば、コミットを取り戻すことができます。新しいブロブを削除するように明示的に指示しない限り、約1か月ほど後にgitのみガベージコレクションが行われます。

$ git init
Initialized empty Git repository in .git/

$ echo "testing reset" > file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo "added new file" > file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file

この例では、ハードリセットの結果としてfile2が削除されましたが、reflogを介してリセットすると、file2は元の場所に戻されました。


222
「git reset --hard HEAD @ {1}」を使用できます。SHA1を使用する必要はありません。ほとんどの場合、「git reset --hard ORIG_HEAD」を使用するだけで十分です。
JakubNarębski、2009年

39
git log -gは、reflogを表示するよりも少し良い方法ですgit reflog
Dan Molding、

60
これには非常に重要な警告が1つあります。それが「-難しい」部分です。--hardは、ローカルのコミットされていない変更を吹き飛ばします。そして、あなたは彼らをこのように戻すことはできません(彼らはどこにもコミットされていないので)。私はそれについてあなたができることは何もないと信じています:(
Michael Anderson

3
^リセットを実行する前にローカルの変更を隠しておくことができることを知っているので、それらをポップするだけで何も失うことはありません!gitが大好きです。
Lethjakman、2014

5
sha1ですべての情報を1行で取得し、HEAD情報とコミットメッセージをすべて並べるためgit refloggit log -g単純に私は好みません。はるかに読みやすい。
Snowcrash 2014

371

あなたがしたいことは、あなたが復元したいコミットのsha1を指定することです。reflog(git reflog)を調べてから、sha1を取得できます。

git reset --hard <sha1 of desired commit>

しかし、あまり長く待たないでください...数週間後、gitは最終的にそのコミットを参照されていないものとして認識し、すべてのblobを削除します。


2
数分前の自分への警告:これによりすべての変更がリセットされます。ただし、追跡されていないファイルには影響しません。
aexl

175

答えは上の詳細な応答に隠されています、あなたは単に行うことができます:

$> git reset --hard HEAD@{1}

git reflog showの出力を参照してください)


17
リセット後に他のリポジトリの変更を行った場合、これは解決策ではないことに注意してください。何かを実行する前に、必ずreflogを確認してください。
フォレストホプキンサ2017年

2
リポジトリを誤ってリセットしました。私の作業が永久に失われたと思っていました。この答えは私の一日を救った。
Zaiyang Li

わぁ!=)
jfcogato

すごい。それは本当に役に立ちました。
Prashant Biradar

117

Gitがまだガベージコレクションを実行していない場合は、回復することができます。

未解決のコミットの概要を取得するにはfsck

$ git fsck --lost-found
dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

リベースで未解決のコミットを回復します。

$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

1
それは素晴らしいものです。
Mohhamad Hasham 2017

詳細な説明は、medium.com / @ CarrieGuss / …にあります。命を救うもの。
tuan.dinh

49

私のように本当に運が良ければ、テキストエディターに戻って[元に戻す]を押すことができます。

私はそれが適切な答えではないことを知っていますが、それは私が半日の仕事を節約したので、うまくいけば他の誰かのために同じことをするでしょう!


3
)とのgitで何をやってよりも簡単にその方法...;これは実際には非常に良いヒントです、私に多くの時間を保存
SEVERIN

3
そして、この全世界で優雅なすべての良さに感謝します。ありがとうございました。ありがとうございました。ありがとうございました。
旅行

9
これは、ハードリセット後にステージングされていないファイルの変更を回復する唯一の方法です。私も救った;)
Czarek Tomczak 2013

4
追加のヒントとして、Eclipseとしての一部のIDEにも最近のファイル履歴が保存されています。そうすれば、エディターを閉じた後に古い変更を回復できる場合もあります。それは私にとって不思議に働きました。
火曜日2014

1
神はあなたにクリスを祝福します
アダム・ウェイト

45

私が知る限り、--hardコミットされていない変更は破棄されます。これらはgitによって追跡されないためです。ただし、元に戻すことができますdiscarded commit

$ git reflog

表示されます:

b0d059c HEAD@{0}: reset: moving to HEAD~1
4bac331 HEAD@{1}: commit: added level introduction....
....

どこ4bac331ですdiscarded commit

頭をそのコミットに移動します::

$ git reset --hard 4bac331

34

IRLケースの例:

$ git fsck --lost-found

Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob 025cab9725ccc00fbd7202da543f556c146cb119
dangling blob 84e9af799c2f5f08fb50874e5be7fb5cb7aa7c1b
dangling blob 85f4d1a289e094012819d9732f017c7805ee85b4
dangling blob 8f654d1cd425da7389d12c17dd2d88d318496d98
dangling blob 9183b84bbd292dcc238ca546dab896e073432933
dangling blob 1448ee51d0ea16f259371b32a557b60f908d15ee
dangling blob 95372cef6148d980ab1d7539ee6fbb44f5e87e22
dangling blob 9b3bf9fb1ee82c6d6d5ec9149e38fe53d4151fbd
dangling blob 2b21002ca449a9e30dbb87e535fbd4e65bac18f7
dangling blob 2fff2f8e4ea6408ac84a8560477aa00583002e66
dangling blob 333e76340b59a944456b4befd0e007c2e23ab37b
dangling blob b87163c8def315d40721e592f15c2192a33816bb
dangling blob c22aafb90358f6bf22577d1ae077ad89d9eea0a7
dangling blob c6ef78dd64c886e9c9895e2fc4556e69e4fbb133
dangling blob 4a71f9ff8262701171d42559a283c751fea6a201
dangling blob 6b762d368f44ddd441e5b8eae6a7b611335b49a2
dangling blob 724d23914b48443b19eada79c3eb1813c3c67fed
dangling blob 749ffc9a412e7584245af5106e78167b9480a27b
dangling commit f6ce1a403399772d4146d306d5763f3f5715cb5a    <- it's this one

$ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

commit f6ce1a403399772d4146d306d5763f3f5715cb5a
Author: Stian Gudmundsen Høiland <stian@Stians-Mac-mini.local>
Date:   Wed Aug 15 08:41:30 2012 +0200

    *MY COMMIT MESSAGE IS DISPLAYED HERE*

diff --git a/Some.file b/Some.file
new file mode 100644
index 0000000..15baeba
--- /dev/null
+++ b/Some.file
*THE WHOLE COMMIT IS DISPLAYED HERE*

$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

First, rewinding head to replay your work on top of it...
Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.

2
ぶら下がりブロブはAD&Dモンスターのように聞こえます!
sbichenko 2014

ありがとう@Stianよく説明しました!この回答を見つけた他の人に追加したいと思います。複数の「ぶら下がり」コミットがある場合、最後の行でリベースする必要があるかどうかは
わかり

git showは私のファイルの一部を保存しました。ありがとうございました。
ウィリアム

32

ほとんどの場合、そうです。

コマンドを実行したときのリポジトリの状態に応じて、の影響はgit reset --hard、些細なものから元に戻すものから、基本的に不可能なものまでさまざまです。

以下に、考えられるさまざまなシナリオと、それらからどのように回復するかを示します。

すべての変更はコミットされましたが、コミットはなくなりました!

この状況は通常git reset、のように引数を指定して実行すると発生しますgit reset --hard HEAD~。心配しないでください。これは簡単に回復できます。

実行しただけでgit reset他に何もしていない場合は、このワンライナーで以前の場所に戻ることができます。

git reset --hard @{1}

これにより、最後に変更された前の現在のブランチがリセットされます(この場合、ブランチに対する最新の変更は、元に戻そうとしているハードリセットになります)。

しかし、あなたがいる場合しているのリセット以降、あなたの枝に他の変更を加え、ワンライナーは、上記動作しません。代わりに、実行して、ブランチに加えられた最近のすべての変更(リセットを含む)のリストを確認してください。そのリストは次のようになります。git reflog <branchname>

7c169bd master@{0}: reset: moving to HEAD~
3ae5027 master@{1}: commit: Changed file2
7c169bd master@{2}: commit: Some change
5eb37ca master@{3}: commit (initial): Initial commit

このリストで「元に戻す」操作を見つけます。上記の例では、「reset:HEAD〜に移動しています」という最初の行になります。次に、その操作の(下)にコミットの表現をコピーします。私たちの場合、それはmaster@{1}(または3ae5027、両方とも同じコミットを表しgit reset --hard <commit>ます)、現在のブランチをそのコミットにリセットするために実行されます。

私は変更をgit addでステージングしましたが、コミットしませんでした。これで私の変更はなくなりました!

これから回復するには少し注意が必要です。gitに追加したファイルのコピーがありますが、これらのコピーは特定のコミットに関連付けられていないため、変更を一度に復元することはできません。代わりに、gitのデータベースで個々のファイルを見つけて、手動で復元する必要があります。あなたはこれを行うことができますgit fsck

これについて詳しくは、ステージング領域でコミットされていないファイル元に戻すgit reset --hardをご覧ください。

でステージングしたgit addこともコミットしたこともない作業ディレクトリ内のファイルに変更を加えました。これで私の変更はなくなりました!

ええとああ。言いたくないのですが、運が悪いでしょう。gitのは、あなたが追加したり、それにコミットしていないことの変更を保存し、かつに従っていないのドキュメントgit reset

- ハード

インデックスと作業ツリーをリセットします。以降の作業ツリーで追跡されているファイルへの変更<commit>は破棄されます。

それはあなたがいる可能性があります可能性があるディスク回復ユーティリティやプロのデータ復旧サービスのいくつかの並べ替えを使用して、変更を回復することができますが、おそらくそれの価値よりも多くのトラブルだこの時点で。


1
ワンライナーはあなたに感謝し、私のために働いたが、私はちょうど「@ {1}」..ないことまさに疑問に思って
スタンBashtavenko

1
@StanBドキュメントはこちらです:git-scm.com/docs/git-rev-parse基本的に、現在のブランチの最初のreflogエントリを参照します。
Ajedi32 2015年

すべてのケースをカバーしていただきありがとうございます。私はコミットも追加もしていません。
xdhmoore

21

リポジトリのガベージコレクションをまだ行っていない場合(git repack -dまたはを使用しますgit gcが、ガベージコレクションも自動的に発生する可能性があることに注意してください)、コミットはまだそこにあり、HEADからは到達できません。

あなたはあなたのコミットを見つけることを試みることができます git fsck --lost-found

新しいバージョンのGitには「reflog」と呼ばれるものがあります。これは、(リポジトリのコンテンツに対して行われた変更ではなく)refに対して行われたすべての変更のログです。したがって、たとえば、HEADを切り替えるたび(つまり、git checkoutブランチを切り替えるために行うたび)にログに記録されます。そしてもちろん、あなたgit resetもHEADを操作したため、ログも記録されました。次のよう@に、の代わりに記号を使用して、リポジトリの古い状態にアクセスできるのと同様の方法で、参照の古い状態にアクセスできます。~git reset HEAD@{1}

HEAD @ {1}とHEAD〜1の違いを理解するのに少し時間がかかったので、ここで少し説明します。

git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog

つまり、HEAD~1「HEADが現在指しているコミットの前にコミットに移動する」という意味です。HEAD@{1}たコミットに移動する」ことを意味します。

これにより、失われたコミットを簡単に見つけて回復することができます。



1
問題は、「履歴」という用語がVCSで実際に過負荷になっていることです。さらに別の表現方法は、〜が逆方向にコミット履歴するのに対し、@は時系列または時間的履歴ですることです。しかし、3つのバージョンのいずれも特に優れているわけではありません。
イェルクWミッターク

@ kizzx2(およびJorg)は、実際にこれらの3つの説明をまとめると、非常に役立ちます-thx
Richard Le Mesurier

14

回答する前に、背景を追加し、これが何であるかを説明しましょう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 HEAD --hard <commit_id>

頭を「動かして」希望のコミットに戻します。

# 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 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ます。

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


あなたのgit reset HEAD --hard <commit_id>例は、stackoverflow.com / questions / 4114095 /… から取られたようです-その場合、属性で編集していただけませんか?
ロブ

12

git reflog

  • リストからcommit shaを見つけて、コピーして次のコマンドに貼り付けます。

git cherry-pick <the sha>


1
git-cherry-pick-既存のコミットによって導入された変更を適用します。このコンテキストでは、シンプルで非常に役立つと思います
Amitesh

1
ハードリセットの変更を元に戻す方法を検索するとき、誰もが実際にこれを探しています。この回答はさらに
賛成票を

@ErenLたぶん考えただけだと思います、人々は余分な仕事をするのが好きです。笑
ScottyBlades

1
これは、あなただけの私の一日🙂保存されている
Sylvernus Akubo

11

私はこれが古いスレッドであることを知っています...しかし、多くの人々がGitでデータを元に戻す方法を探しているので、ここでヒントを提供し続けるのは良い考えだと思います。

「git add」を実行するか、git guiで左上から左下に何かを移動すると、ファイルのコンテンツはblobに保存され、ファイルコンテンツはそのblobから復元できます。

そのため、コミットされていなくても追加されているファイルであっても、ファイルを回復することができます。

git init  
echo hello >> test.txt  
git add test.txt  

これでb​​lobが作成されましたが、インデックスによって参照されているため、リセットするまでgit fsckで一覧表示されません。リセットします...

git reset --hard  
git fsck  

ぶら下がりブロブce013625030ba8dba906f756967f9e9ca394464aを取得します

git show ce01362  

ファイルの内容を "こんにちは"返します

参照されていないコミットを見つけるために、これを示唆するヒントをどこかに見つけました。

gitk --all $(git log -g --pretty=format:%h)  

私はそれをgit guiのツールとして使用しており、非常に便利です。


+1。stackoverflow.com/a/21350689/6309で説明されているように、これgit fsck --lost-foundが役立ちます。
VonC 2014年

7

JetBrains IDE(IntelliJベースのもの)を使用している場合は、「ローカル履歴」機能を使用して、コミットされていない変更も回復できます。

ファイルツリーの最上位ディレクトリを右クリックし、コンテキストメニューで[ローカル履歴]を見つけて、[履歴の表示]を選択します。これにより、最近の編集内容を確認できるビューが開きます。戻りたいリビジョンが見つかったら、それを右クリックして[元に戻す]をクリックします。


4

間違ったプロジェクトでハードリセットを実行しました。私の命を救ったのは、Eclipseのローカルな歴史です。IntelliJ Ideaにも1つあると言われています。編集者もそうだと思います。チェックする価値があります。

  1. ローカル履歴に関するEclipseヘルプトピック
  2. http://wiki.eclipse.org/FAQ_Where_is_the_workspace_local_history_stored%3F

1
Jetbrains CLionのローカルヒストリーはすばらしいもので、私にとって2時間の作業を節約できました:)
Fabian Knapp 2017

3

小さなスクリプトを作成して、探しているコミットを少し簡単に見つけられるようにしました。

git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'

はい、それはawkまたはそれに似たものでかなりきれいにすることができますが、それは簡単で、私はそれを必要としました。他の誰かを30秒節約できるかもしれません。


0

私の問題はほとんど同じです。入力する前にコミットされていないファイルがありますgit reset --hard

ありがたいことに。これらのリソースをすべてスキップすることができました。元に戻すことができることに気付いた後(ctrl-z)。aboveこれを上記のすべての回答に追加したいだけです。

注意。ctrl-z開かれていないファイルは不可能です。


0

これは私の命を救った: https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c

基本的には実行する必要があります:

for blob in $(git fsck --lost-found | awk ‘$2 == “blob” { print $3 }’); do git cat-file -p $blob > $blob.txt; done

次に、手動で苦労して、ファイルを正しい構造に再編成します。

要点:git reset --hard動作を完全に理解していない場合は絶対に使用しないでください。使用しないことをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.