web-dev-qa-db-ja.com

元に戻すgit reset --hardステージング領域のコミットされていないファイル

仕事を取り戻そうとしています。私は愚かでした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この状況では?

102
eistrati

git reset --hardを行ったところ、1つのコミットが失われました。しかし、私はコミットハッシュを知っていたので、git cherry-pick COMMIT_HASHを実行して復元できました。

コミットを失ってから数分以内にこれを行ったので、一部の人にとってはうまくいくかもしれません。

58

Mark Longairのおかげで、自分のものを取り戻しました!

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

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

次に、それらすべてをリストに入れて(「到達不能なブロブ」を削除します)データをすべて新しいファイルに入れます...ファイルを選択して、必要な名前を再度変更する必要があります... files ..これが誰かを助けることを願っています...

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
13
Boy

コメントの@ Ajedi32のソリューションは、まさにこの状況で私にとってはうまくいきました。

git reset --hard @{1}

これらのすべてのソリューションはgit gcがないことに依存しており、そのうちのいくつかはgit gcを引き起こす可能性があることに注意してください。あなたのために働きません。

5
Duncan McGregor

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

上記のすべての詳細な答えの後、これは素朴なヒントですが、私がしたように、最初にそれについて考えなかった誰かを救うかもしれません。

絶望の中で、開いているタブごとに1回、エディター(LightTable)でCTRL-Zを押してみました。これにより、そのタブのファイルが幸運にもgit reset --hardの前の最新の状態に回復しました。 HTH。

3
olange

これはgitの専門家にはおそらく明らかですが、必死の検索ではこれが表示されなかったので、私はそれを付けたかったのです。

いくつかのファイルをステージングし、git reset --hardを実行し、少しおかしくなりました。その後、ステータスがすべてのファイルがステージングされていることと、すべての削除がステージングされていないことに気付きました。

この時点で、削除をステージングしない限り、ステージングされた変更をコミットできます。この後、もう一度 "git reset --hard"を実行するだけで、ステージングしてコミットしたばかりの変更に戻ることができます。

繰り返しますが、これはおそらくほとんど新しいことではありませんが、それが私を助け、私がこれを示唆するものを見つけなかったので、それが他の誰かを助けるかもしれないことを願っています。

1
ddoty

いいですね、この質問とその答えに出くわすまで髪を引っ張りました。質問に対する正しい簡潔な回答は、上記のコメントのうち2つをまとめた場合にのみ利用できると考えているため、ここではすべてを1か所にまとめています。

  1. Chilicuilで述べたように、「git reflog」を実行して、そこに戻すコミットハッシュを特定します

  2. Akimskoで述べたように、コミットを1つだけ失った場合を除き、チェリーピックをしたくないので、 'git reset --hardを実行する必要があります。

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

1
Lolo

私はIntelliJを使用しており、各ファイルを簡単に確認して実行できました:

Edit -> reload from disk

幸いなことに、私はgit status作業中の変更を消去する直前に、リロードする必要があるものを正確に把握しました。

0
Forrest

上記の解決策は機能する可能性がありますが、git- sの複雑な取り消しを実行する代わりに、これから回復する簡単な方法があります。ほとんどのgit-resetsは少数のファイルで発生すると思います。すでにVIMを使用している場合は、これが最も時間効率の良いソリューションかもしれません。ただし、無制限の数の変更を取り消すことができるため、どちらの方法でも使用する必要がある_ViM's_ persistent-undoをすでに使用している必要があります。

手順は次のとおりです。

  1. Vimで_:_を押し、コマンド_set undodir_を入力します。 _persistent undo_で_.vimrc_を有効にしている場合、_undodir=~/.vim_runtime/temp_dirs/undodir_に似た結果が表示されます。

  2. リポジトリで_git log_を使用して、最後にコミットした最後の日付/時刻を見つけます

  3. シェルで_cd ~/.vim_runtime/temp_dirs/undodir_を使用してundodirに移動します。

  4. このディレクトリでこのコマンドを使用して、最後のコミット以降に変更したすべてのファイルを検索します

    find . -newermt "2018-03-20 11:24:44" \! -newermt "2018-03-23" \( -type f -regextype posix-extended -regex '.*' \) \-not -path "*/env/*" -not -path "*/.git/*"

    ここで、「2018-03-20 11:24:44」は最後のコミットの日時です。 _git reset --hard_を実行した日付が「2018-03-22」の場合、「2018-03-22」を使用してから、「2018-03-23」を使用します。これは、下限が包括的で、上限が排他的である検索の癖のためです。 https://unix.stackexchange.com/a/70404/24298

  5. 次に、各ファイルに移動し、vimでそれらを開き、「20m前」を実行します。 「hlier」を使用すると、「earlier」の詳細を確認できます。ここで_earlier 20m_は、20分前に_git hard --reset_を実行したと仮定して、20分前にファイルの状態に戻ることを意味します。 findコマンドから出力されたすべてのファイルに対してこれを繰り返します。誰かがこれらのことを組み合わせるスクリプトを書くことができると確信しています。

0
alpha_989