gitリセットを元に戻す - ステージング領域のコミットされていないファイルを備えたハード

StackOverflow https://stackoverflow.com/questions/7374069

質問

私は自分の仕事を回復しようとしています。私は愚かにしました 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 この状況で?

役に立ちましたか?

解決

インデックスに追加したファイルを戻すことができるはずです(たとえば、あなたの状況のように、 git add .)少し作業かもしれませんが。インデックスにファイルを追加するために、Gitはオブジェクトデータベースに追加します。つまり、ガベージコレクションがまだ発生していない限り、回復できます。これを行う方法の例があります ヤクブ・ナルブスキの答え ここ:

しかし、私はそれをテストリポジトリで試しましたが、いくつかの問題がありました - --cached あるべきです --cache, 、そして私はそれが実際には作成しなかったことがわかりました .git/lost-found ディレクトリ。しかし、次の手順は私のために機能しました:

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

これにより、ref、インデックス、またはリフェログを介してrefで到達できないオブジェクトデータベースにすべてのオブジェクトを出力する必要があります。出力は次のようになります:

unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03

...そしてそれらの塊のそれぞれについて、あなたはできます:

git show 907b308

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


出力が多すぎますか?

応答した更新 sehe以下のコメント:

そのコマンドから出力に多くのコミットとツリーがリストされていることがわかった場合、リファレンスされていないcommitsから参照されているオブジェクトを出力から削除することをお勧めします。 (通常、リフログを介してこれらのコミットに戻ることができます - 私たちはインデックスに追加されたが、コミットで見つけることができないオブジェクトに興味があります。)

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

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)

それは、あなたが考慮しなければならないオブジェクトの数を大幅に削減します。


アップデート: フィリップ・オークリー 以下は、考慮すべきオブジェクトの数を削減する別の方法を示唆しています。 .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

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

他のヒント

私はちょうどしました gitリセット - ハード そして、1つのコミットを失いました。しかし、私はコミットハッシュを知っていたので、私はできました gitcherry-pick commit_hash それを復元するために。

私はコミットを失ってから数分以内にこれをしたので、それはあなたの何人かのために働くかもしれません。

マーク・ロングアのおかげで、私は自分のものを取り戻しました!

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

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

@Ajedi32のコメントのソリューションは、まさにこの状況で私のために機能しました。

git reset --hard @{1}

これらすべてのソリューションはGit GCがないことに依存しており、それらのいくつかは1つを引き起こす可能性があるため、何かを試す前に.gitディレクトリの内容をジップアップして、スナップショットが必要な場合は戻ることができないことに注意してください。あなたのために働きます。

同じ問題に遭遇しましたが、インデックスに変更を追加していませんでした。したがって、上記のすべてのコマンドは、私に望ましい変更を取り戻しませんでした。

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

絶望的に、私は編集者(Lighttable)でCtrl-Zを押しようとしました。1回、すべてのオープンタブに1回 - このタブのファイルを幸運にも、その前の最新の状態に回復しました。 git reset --hard. 。 Hth。

良さ、私はこの質問とその答えに出くわすまで髪を引っ張りました。質問に対する正確で簡潔な答えは、上記の2つのコメントを一緒に引っ張った場合にのみ利用できると思います。

  1. Chilicuilが述べたように、「Git Reflog」を実行して、そこに戻りたいコミットハッシュを識別します

  2. Akimskoが述べたように、1つのコミットしか失わない限り、選択したくないでしょう。

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

これはおそらくGITの専門家にとっては明らかですが、必死の検索でこれが育っていなかったので、私はそれを立てたかったのです。

私はいくつかのファイルをステージングし、gitリセットを行いました - ハード、少しびっくりして、私のステータスが私のすべてのファイルとそのすべての削除がステージングされていないことを示していることに気付きました。

この時点で、それらの削除をステージングしない限り、これらの段階的な変更を犯すことができます。この後、あなたは「Git Reset - Hard」をもう一度行う勇気を上げる必要があります。

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

上記のソリューションは機能する可能性がありますが、これを通過する代わりにこれから回復する簡単な方法があります git-S複雑な元に戻します。ほとんどのgit-resetは少数のファイルで発生すると思います。すでにVIMを使用している場合、これが最も時間効率の良いソリューションかもしれません。警告は、すでに使用している必要があるということです ViM's Persistent-Undo。どちらの方法でも使用する必要があります。これは、無制限の数の変更を取り消す機能を提供するためです。

ここにステップがあります:

  1. Vim Pressで : コマンドを入力します set undodir. 。あなたが持っている場合 persistent undo あなたの中でオンになりました .vimrc, 、それはと同様の結果を示しますundodir=~/.vim_runtime/temp_dirs/undodir.

  2. レポで使用します git log 最後の日付/時間を見つけるために、あなたは最後のコミットをしました

  3. あなたのシェルであなたに移動します undodir 使用cd ~/.vim_runtime/temp_dirs/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/242983

  5. 次に、各ファイルをVIMで開き、「早期20m」を実行します。 「Hearte」を使用して、「以前」の詳細を見つけることができます。ここearlier 20m 20分前にファイルの状態に戻ることを意味します。 git hard --reset, 、20分前。から吐き出されたすべてのファイルでこれを繰り返します find 指図。誰かがこれらのことを組み合わせるスクリプトを書くことができると確信しています。

Intellijを使用していて、各ファイルを単純に実行して実行することができました。

Edit -> reload from disk

幸いなことに、私はちょうどしました git status 作業の変更を一掃する直前に、リロードしなければならなかったものを正確に知っていました。

ファイルの階層を覚えていて、Mark Longairの手法をPhil Oakleyの変更で使用すると、劇的な結果が得られます。

基本的に、少なくともリポジトリにファイルを追加したがコミットしていない場合は、「git show」を使用してインタラクティブに復元し、ログを検査し、各ファイルを作成するためにシェルリダイレクトを使用できます(関心のあるパスを思い出します)。

hth!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top