2142

私は頻繁に and を使用git stashgit stash popて、作業ツリーの変更を保存および復元します。昨日、隠してポップした作業ツリーにいくつかの変更を加えてから、作業ツリーにさらに変更を加えました。戻って昨日の隠し変更を確認したいのですがgit stash pop、関連するコミットへのすべての参照が削除されているようです。

git stash使用すると、.git/refs/stash には、スタッシュの作成に使用されたコミットの参照が含まれることを知っています。そして.git/logs/refs/stash には隠し場所全体が含まれています。しかし、それらの参照はgit stash pop. コミットがまだ私のリポジトリのどこかにあることは知っていますが、それが何であったかはわかりません。

昨日の stash コミット参照を復元する簡単な方法はありますか?

私は毎日のバックアップを持っており、昨日の作業ツリーに戻って変更を取得できるため、これは今日の私にとって重要ではないことに注意してください。もっと簡単な方法があるに違いないので、私は尋ねています!

4

24 に答える 24

3433

ドロップした stash コミットのハッシュがわかったら、それを stash として適用できます。

git stash apply $stash_hash

または、別のブランチを作成することもできます

git branch recovered $stash_hash

その後、すべての通常のツールを使用して、必要なことを行うことができます。終わったら、枝を吹き飛ばします。

ハッシュを見つける

ポップしたばかりでターミナルがまだ開いている場合は、ハッシュ値git stash popが画面に表示されます(ありがとう、Dolda)。

それ以外の場合は、Linux、Unix、または Windows の Git Bash でこれを使用して見つけることができます。

git fsck --no-reflog | awk '/dangling commit/ {print $3}'

...または Windows 用の Powershell を使用:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }

これにより、ブランチやタグから参照されなくなったコミット グラフの先端にあるすべてのコミットが表示されます。これまでに作成したすべての stash コミットを含む、失われたすべてのコミットは、そのグラフのどこかに表示されます。

必要な stash コミットを見つける最も簡単な方法は、おそらくそのリストを に渡すことですgitk

gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

...または、Powershell for Windows を使用している場合は emragins からの回答を参照してください。

これにより、リポジトリ ブラウザーが起動し、到達可能かどうかに関係なく、リポジトリ内のすべてのコミットが表示されます。

別の GUI アプリよりもコンソールで素敵なグラフを好む場合は、gitkそこを何かに置き換えることができます。git log --graph --oneline --decorate

stash コミットを見つけるには、次の形式のコミット メッセージを探します。

somebranchの        WIP : commithash Some old commit message

: コミット メッセージは、メッセージを提供したときにメッセージを提供しなかった場合にのみ、この形式 (「WIP on」で始まる) になりますgit stash

于 2008-09-18T11:38:25.550 に答える
770

ターミナルを閉じていない場合は、出力を確認するだけgit stash popで、ドロップされたスタッシュのオブジェクト ID を確認できます。通常は次のようになります。

$ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)

(これgit stash dropも同じ行を生成することに注意してください。)

その隠し場所を取り戻すには、 を実行するだけでgit branch tmp 2cae03e、ブランチとして取得できます。これを stash に変換するには、次を実行します。

git stash apply tmp
git stash

枝として持つことで、自由に操作することもできます。たとえば、チェリーピックまたはマージします。

于 2011-10-21T03:13:24.043 に答える
166

まだリポジトリにあるが、もうアクセスできない stash のリストを取得するには:

git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP

スタッシュにタイトルを付けた場合-grep=WIPは、コマンドの末尾にある "WIP" をメッセージの一部に置き換えます (例: -grep=Tesselation.

stash のデフォルトのコミット メッセージは次の形式であるため、コマンドは「WIP」を grep しています。WIP on mybranch: [previous-commit-hash] Message of the previous commit.

于 2011-05-04T06:42:36.980 に答える
89

失われた stash コミットを見つけるのに役立つコマンドを作成しました。

for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less

これにより、.git/objects ツリー内のすべてのオブジェクトが一覧表示され、コミット タイプのオブジェクトが特定され、各オブジェクトの概要が表示されます。この時点から、適切な「作業中の WIP: 6a9bb2」(「作業」は私のブランチ、619bb2 は最近のコミット) を見つけるためにコミットを調べるだけでした。

「git stash pop」の代わりに「git stash apply」を使用すると、この問題は発生しないことに注意してください。「git stash save message」を使用すると、コミットが見つけやすくなる可能性があります。

更新:ネイサンのアイデアでは、これは短くなります:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
于 2008-09-18T02:10:13.467 に答える
66

gitk を使用した同等の Windows PowerShell:

gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })

1 つのパイプでこれを行うには、おそらくもっと効率的な方法がありますが、これでうまくいきます。

于 2016-01-07T23:22:05.920 に答える
51

git fsck --unreachable | grep commitsha1 を表示する必要がありますが、返されるリストは非常に大きくなる可能性があります。git show <sha1>それがあなたが望むコミットであるかどうかが表示されます。

git cherry-pick -m 1 <sha1>コミットを現在のブランチにマージします。

于 2008-09-18T02:08:15.390 に答える
44

失われた隠し場所を再構築したい場合は、最初に失われた隠し場所のハッシュを見つける必要があります。

アリストテレス・パガルツィスが示唆したように、git fsckあなたを助けるはずです。

個人的にlog-allは、状況をよりよく把握するために、すべてのコミット (回復可能なコミット) を表示するエイリアスを使用しています。

git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)

「WIP on」メッセージのみを探している場合は、さらに高速に検索できます。

sha1 がわかったら、stash reflog を変更して古い stash を追加するだけです。

git update-ref refs/stash ed6721d

関連するメッセージが必要になる場合があります。-m

git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d

また、これをエイリアスとして使用することもできます:

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1
于 2011-06-23T14:20:51.370 に答える
23

私はアリストテレスのアプローチが好きでしたが、コマンド ラインから GIT を使用することに慣れているため、GITK の使用は好きではありませんでした。

代わりに、ダングリング コミットを取得し、コード エディターでレビューするためにコードを DIFF ファイルに出力しました。

git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff

これで、結果の diff/txt ファイル (ホーム フォルダーにある) を txt エディターにロードして、実際のコードと結果の SHA を確認できます。

次に、使用するだけです

git stash apply ad38abbf76e26c803b27a6079348192d32f52219
于 2013-01-07T20:17:34.283 に答える
16

シンプルなコマンド ウィンドウ (私の場合は Windows 7) で Windows で動作するための回答を得ることができませんでした。awk、コマンドとして認識されませんでしたgrepSelect-stringだから私は別のアプローチを試みました:

  • ファーストラン:git fsck --unreachable | findstr "commit"
  • 出力をメモ帳にコピーします
  • 「到達不能なコミット」を置き換えますstart cmd /k git show

次のようになります。

start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e

  • .batファイルとして保存して実行します
  • スクリプトは一連のコマンド ウィンドウを開き、各コミットを表示します
  • 探しているものが見つかったら、次を実行します。git stash apply (your hash)

最善の解決策ではないかもしれませんが、私にとってはうまくいきました

于 2017-02-22T09:05:08.060 に答える
14

gitkが利用できない場合、または出力用のXがない場合に、受け入れられたソリューションにすべての変更を行うための別の良い方法を追加したいと思います。

git fsck --no-reflog | awk '/dangling commit/ {print $3}' > tmp_commits

for h in `cat tmp_commits`; do git show $h | less; done

次に、それらのハッシュのすべての差分が次々に表示されます。'q'を押して、次の差分に移動します。

于 2013-01-04T12:32:19.047 に答える
12

アリストテレスによって受け入れられた回答は、非スタッシュのようなコミットを含む、到達可能なすべてのコミットを表示します。ノイズを除去するには:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3

これには、正確に 3 つの親コミット (スタッシュに含まれる) があり、メッセージに "WIP on" が含まれるコミットのみが含まれます。

stash をメッセージ (例: git stash save "My newly created stash") とともに保存した場合、デフォルトの「WIP on...」メッセージが上書きされることに注意してください。

各コミットに関する詳細情報を表示できます。たとえば、コミット メッセージを表示したり、次のように渡したりできますgit stash show

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3 | \
xargs -n1 -I '{}' bash -c "\
  git log -1 --format=medium --color=always '{}'; echo; \
  git stash show --color=always '{}'; echo; echo" | \
less -R
于 2016-05-17T04:33:50.830 に答える
5

次の手順を使用して回復しました。

  1. 削除された stash ハッシュ コードを特定します。

    gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

  2. 隠し場所のチェリーピック:

    git チェリーピック -m 1 $stash_hash_code

  3. 以下を使用して競合がある場合は解決します。

    gitマージツール

さらに、gerrit を使用している場合、コミット メッセージに問題がある可能性があります。次の代替案に従う前に、変更を隠してください:

  1. 以前のコミットにハード リセットを使用してから、この変更を再コミットします。
  2. 変更を隠し、リベースし、再コミットすることもできます。
于 2015-08-26T02:18:20.407 に答える
5

ターミナルでコミットを表示するには、使用できる重要なもののみをフィルタリングします。

git log --oneline --all --grep="^WIP on .*: [a-f0-9]\+" --grep="^On [^ ]*:" --grep="^index on [^ ]*:" $( env LANG=C git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

これは、アリストテレス・パガルツィの答えに基づいています。

于 2021-02-17T20:07:08.043 に答える
4

私がここに探しに来たのは、チェックアウトしたものに関係なく、実際に隠し場所を取り戻す方法です。特に、私は何かを隠しておき、古いバージョンをチェックアウトしてからポップしましたが、隠し場所はその以前の時点では何もしなかったため、隠し場所は消えました。git stashスタックに押し戻すことはできませんでした。これは私のために働いた:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

振り返ってみると、私はgit stash applynotを使っていたはずgit stash popです。私は を行っていて、すべてのステップbisectで適用したい小さなパッチがありました。bisect今私はこれをやっています:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.
于 2013-11-07T15:00:19.517 に答える