123

私は自分の仕事を回復しようとしています。私はばかげてやったがgit reset --hard、それ以前はやっただけget add .で、やらなかったgit commit。助けてください!これが私のログです:

MacBookPro:api user$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)

#   modified:   .gitignore
...


MacBookPro:api user$ git reset --hard
HEAD is now at ff546fa added new strucuture for api

git reset --hardこの状態で元に戻すことは可能でしょうか?

4

13 に答える 13

193

git add .少し手間がかかるかもしれませんが、インデックスに追加したすべてのファイルを元に戻すことができるはずです (たとえば、あなたの状況のように)。ファイルをインデックスに追加するために、git はそのファイルをオブジェクト データベースに追加します。つまり、ガベージ コレクションがまだ行われていない限り、そのファイルを復元できます。Jakub Narębski's answer hereに、これを行う方法の例があります。

ただし、テスト リポジトリでそれを試してみたところ、いくつかの問題があり--cachedまし--cache.git/lost-found。ただし、次の手順でうまくいきました。

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)")

これにより、参照、インデックス、またはreflogを介して到達できないオブジェクトデータベース内のすべてのオブジェクトが出力されます。出力は次のようになります。

unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03

...そして、これらのブロブごとに、次のことができます。

git show 907b308

ファイルの内容を出力します。


出力が多すぎますか?

以下のseheのコメントに応じて更新します。

そのコマンドの出力に多くのコミットとツリーがリストされていることがわかった場合は、参照されていないコミットから参照されているオブジェクトを出力から削除することをお勧めします。(通常、とにかくreflog経由でこれらのコミットに戻ることができます.インデックスに追加されたオブジェクトに興味があるだけですが、コミット経由では決して見つけることができません.)

まず、コマンドの出力を次のように保存します。

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > all

これらの到達不能なコミットのオブジェクト名は、次の方法で見つけることができます。

egrep commit all | cut -d ' ' -f 3

したがって、インデックスに追加されたが、どの時点でもコミットされていないツリーとオブジェクトだけを見つけることができます。

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") \
  $(egrep commit all | cut -d ' ' -f 3)

これにより、考慮しなければならないオブジェクトの数が大幅に削減されます。


更新:以下の Philip Oakleyは、考慮すべきオブジェクトの数を削減する別の方法を提案しています.git/objects。これらは次の方法で見つけることができます。

find .git/objects/ -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort

(私はそのfind呼び出しをここで見つけました。) そのリストの最後は次のようになります:

2011-08-22 11:43:43.0234896770 .git/objects/b2/1700b09c0bc0fc848f67dd751a9e4ea5b4133b
2011-09-13 07:36:37.5868133260 .git/objects/de/629830603289ef159268f443da79968360913a

その場合、これらのオブジェクトを次のように表示できます。

git show b21700b09c0bc0fc848f67dd751a9e4ea5b4133b
git show de629830603289ef159268f443da79968360913a

/(オブジェクト名を取得するには、パスの末尾にあるを削除する必要があることに注意してください。)

于 2011-09-11T07:44:37.950 に答える
18

Mark Longair のおかげで荷物が戻ってきました!

まず、すべてのハッシュをファイルに保存しました。

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > allhashes

次に、それらすべてをリストに入れ(「到達不能なブロブ」のものを削除します)、データをすべて新しいファイルに入れます...ファイルを選択して、必要に応じて名前を変更する必要があります...しかし、必要なものはいくつかだけでしたファイル..これが誰かに役立つことを願っています...

commits = ["c2520e04839c05505ef17f985a49ffd42809f",
    "41901be74651829d97f29934f190055ae4e93",
    "50f078c937f07b508a1a73d3566a822927a57",
    "51077d43a3ed6333c8a3616412c9b3b0fb6d4",
    "56e290dc0aaa20e64702357b340d397213cb",
    "5b731d988cfb24500842ec5df84d3e1950c87",
    "9c438e09cf759bf84e109a2f0c18520",
    ...
    ]

from subprocess import call
filename = "file"
i = 1
for c in commits:
    f = open(filename + str(i),"wb")
    call(["git", "show", c],stdout=f)
    i+=1
于 2014-01-08T13:52:01.467 に答える
6

コメントの@ Ajedi32の解決策は、まさにこの状況でうまくいきました。

git reset --hard @{1}

これらの解決策はすべて git gc がないことに依存しており、それらのいくつかはそれを引き起こす可能性があることに注意してください.あなたのために働かない。

于 2016-01-11T19:14:36.763 に答える
4

同じ問題に遭遇しましたが、インデックスに変更を追加していませんでした。したがって、上記のすべてのコマンドでは、目的の変更が返されませんでした。

上記のすべての精巧な答えの後で、これは素朴なヒントですが、私のように最初に考えなかった人を救うかもしれません.

絶望的に、開いているすべてのタブで 1 回、エディター (LightTable) で CTRL-Z を押してみましたgit reset --hard。HTH。

于 2016-09-30T10:59:49.367 に答える
2

IDE でファイルを編集している場合、Git とは別に独自の履歴を保持している可能性もあります。状況によっては、Git を完全にバイパスして IDE を使用する方がはるかに簡単です。たとえば、IntelliJ IDEA と Eclipse はどちらも、この種の自動化されたローカル バージョン管理を備えており、これを「ローカル履歴」と呼んでいます。IntelliJ では、多くのファイルにわたって失われた変更のバッチ全体を簡単に取得できます。[プロジェクト] ペインで、プロジェクト全体またはディレクトリ ツリーを右クリックし、[ローカル履歴] サブメニューで [履歴を表示] を選択できます。はgit reset --hard「外部変更」としてリストに表示されます (つまり、IDE の外部からトリガーされます)。元に戻すボタンまたはコンテキスト メニュー項目を使用して、外部変更が発生する直前の状態にすべてを戻すことができます。

于 2020-08-26T04:11:09.453 に答える
2

よかった、この質問とその答えに出くわすまで、私は髪を引っ張った。尋ねられた質問に対する正確で簡潔な答えは、上記の 2 つのコメントをまとめた場合にのみ利用できると思います。

  1. chilicuil で述べたようにgit reflog、そこに戻りたいコミット ハッシュを特定するために実行します。

  2. akimsko が述べたように、コミットを 1 つだけ失った場合を除き、チェリー ピックを使用したくない可能性が高いため、実行する必要があります。git reset --hard <hash-commit-you-want>

egit Eclipse ユーザーへの注意: egit を使用して Eclipse 内でこれらの手順を実行する方法が見つかりませんでした。Eclipse を閉じ、ターミナル ウィンドウから上記のコマンドを実行してから、Eclipse を再度開くと、問題なく動作しました。

于 2014-12-03T05:50:46.690 に答える
0

私は IntelliJ を使用しており、各ファイルを単純に調べて次のことを行うことができました。

Edit -> reload from disk

幸いなことにgit status、作業中の変更を消去する直前に作業を行ったばかりだったので、何をリロードする必要があるかが正確にわかりました。

于 2019-05-07T18:09:33.340 に答える