私は頻繁に git stash
と git stash pop
を使って自分の作業ツリーの変更を保存したり復元したりしています。昨日、作業ツリーに隠した変更をポップし、その後さらに作業ツリーに変更を加えました。昨日隠した変更をもう一度確認したいのですが、git stash pop
は関連するコミットへの参照をすべて削除してしまうようです。
git stashを使うと、*.git/refs/stash に stash を作成したコミットへの参照が含まれる*ことがわかっています。そして *.git/logs/refs/stash には stash 全体が含まれています。しかし、これらの参照は
git stash pop` の後に消えてしまいます。そのコミットがまだ私のリポジトリのどこかにあることは知っていますが、それが何であったかはわかりません。
昨日のstashコミットの参照を簡単に復元する方法はありますか?
なぜなら、私は毎日バックアップをとっており、昨日の作業ツリーに戻って変更を取得することができるからです。私はもっと簡単な方法があるはずだと思い、質問しています。
落としたスタッシュコミットのハッシュが分かれば、スタッシュとして適用することができます。
git stash apply $stash_hash
あるいは、そのコミット用の別のブランチを
git branch recovered $stash_hash
その後は、通常のツールで好きなことを何でもできます。終わったら、そのブランチを吹き飛ばせばいいのです。
ハッシュをポップした直後でターミナルが開いている場合は、git stash pop
が出力したハッシュの値が画面に表示されます]1 (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 { $bits = $_ -split ' '; echo $bits[2];}
これは、コミットグラフの先端にある、どのブランチやタグからも参照されなくなったコミットをすべて表示します。これまで作成したすべての隠しコミットを含め、失われたすべてのコミットがこのグラフのどこかにあることになります。
必要な stash コミットを見つける最も簡単な方法は、おそらくこのリストを gitk
に渡すことでしょう。
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
...または、Windows用のPowershellを使用している場合は、emraginsからの回答を参照してください。
これはリポジトリブラウザを起動し、到達可能かどうかにかかわらず、リポジトリ内の これまでの すべてのコミットを表示します。
GUIアプリよりもコンソールに表示されるグラフが好きな場合は、gitk
を git log --graph --oneline --decorate
などに置き換えることができます。
stash のコミットを見つけるには、このようなコミットメッセージを探します。
WIP on somebranch: commithash Some old commit message</i>.のような形のコミットメッセージを探します。
注:注*:コミットメッセージは、git stash
を実行したときにメッセージを指定しなかった場合のみ、この形式("WIP on"で始まる形式)になります。
端末を閉じていない場合は、「git stash pop」からの出力を見てください。ドロップした隠し場所のオブジェクトIDが表示されます。 通常はこのように見えます。
$ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)
(「git stash drop」も同じラインを生成することに注意してください。)。
隠し場所に戻すには、「git branch tmp 2cae03e」を実行するだけで、ブランチとして入手できます。 これを隠し場所に変換するには、次を実行します。
git stash apply tmp
git stash
ブランチとして持つと、自由に操作することもできます。たとえば、チェリーピックまたはマージします。
受け入れられたソリューションへのこの追加について言及したかっただけです。 初めてこの方法を試したときは、すぐにはわかりませんでした(おそらくそうだったはずです)が、ハッシュ値からスタッシュを適用するには、「git stash apply< hash>」:を使用します。
$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219
私がgitに慣れていないとき、これは私にははっきりしていませんでした、そして私は「git show」、「git pul」、「patch」などの異なる組み合わせを試みていました。
リポジトリに残っているが、もう到達できないスタッシュのリストを取得するには:
git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP
---。
隠し場所にタイトルを付けた場合は、コマンドの最後にある -grep = WIP
の "WIP"をメッセージの一部に置き換えます。 -grep = Tesselation
。
[WIP]の場合、コマンドはgreppingします。これは、スタッシュのデフォルトのコミットメッセージが mybranchのWIP:[previous-commit-hash]以前のコミットのメッセージであるためです。
。
失われたスタッシュコミットを見つけるのに役立つコマンドを構築したところです。
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 ツリーにあるすべてのオブジェクトをリストアップし、commit タイプのオブジェクトを探し出し、それぞれのオブジェクトの概要を表示します。ここから先は、コミットに目を通して適切な "作業中の WIP を見つけるだけのことです。6a9bb2" ("work" は私のブランチで、619bb2 は最近のコミットです)。
もし私が "git stash pop" の代わりに "git stash apply" を使っていればこの問題は発生しなかったでしょうし、もし "git stash save message" を使えば、コミットを見つけるのが簡単になったかもしれません。
更新:Nathan'のアイデアで、これはより短くなりました。
for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
紛失した隠し場所を交換したい場合は、まず紛失した隠し場所のハッシュを見つける必要があります。
アリストテレス・パガルツィスが示唆したように、「git fsck」はあなたを助けるはずです。
個人的には、すべてのコミット(回復可能なコミット)を示す「log-all」エイリアスを使用して、状況をよりよく把握します。
git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)
「WIPオン」メッセージのみを探している場合は、さらに高速な検索を実行できます。
sha1がわかったら、隠し場所のリフログを変更して、古い隠し場所を追加します。
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
私はアリストテレスのアプローチが好きでしたが、GITKを使用するのは好きではありませんでした。. コマンドラインからGITを使用することに慣れているので。
代わりに、ぶら下がっているコミットを採用し、コードをDIFFファイルに出力して、コードエディターで確認します。
git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff
これで、結果のdiff / txtファイル(ホームフォルダー内のファイル)をtxtエディターにロードして、実際のコードと結果のSHAを確認できます。
次に使用します。
git stash apply ad38abbf76e26c803b27a6079348192d32f52219
なぜ人々はこの質問をするのですか?? 彼らはまだreflogについて知らないか理解していないからです。
この質問へのほとんどの答えは、誰も覚えていないオプションを備えた長いコマンドを与えます。 したがって、人々はこの質問に入り、必要と思われるものをコピーして貼り付け、ほぼ直後にそれを忘れます。
この質問があれば、reflog(git reflog)を確認することをお勧めします。 すべてのコミットのリストが表示されたら、探しているコミットを調べて、それをチェリーピックするか、そこからブランチを作成する方法が100あります。 このプロセスでは、さまざまな基本的なgitコマンドのreflogと便利なオプションについて学習します。
git v2.6.4を搭載したOSXでは、git stash dropを誤って実行しただけで、手順の下をトラフして見つけました。
隠し場所の名前を知っている場合は、以下を使用します。
$ git fsck --unreachable | grep commit | cut -c 20-| xargs git show | grep -B 6 -A 2< stash>
の名前。
それ以外の場合は、手動で結果からIDを見つけます。
``` $ git fsck --unreachable | grep commit | cut -c 20- | xargs git show````。
次に、コミットIDを見つけたときに、git stashを押すだけで{commit-id}が適用されます。
これが誰かをすぐに助けることを願っています。
単純なコマンドウィンドウ(私の場合はWindows 7)でWindowsで作業するための回答が得られませんでした。 awk
、 grep
、および Select-string
はコマンドとして認識されませんでした。 だから私は別のアプローチを試しました:
-最初の実行: git fsck --unreachable | findstr "commit"
。
-出力をメモ帳にコピーします。
-「到達不可能なコミット」を「開始cmd / k gitショー」に置き換えます。
このようなものになります:
start cmd / k git show 44078733e1b36962571019126243782421fcd8ae。
start cmd / k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1。
start cmd / k git show d00aab9198e8b81d052d90720165e48b287c302e``````。
-.batファイルとして保存して実行します。
-スクリプトは、各コミットを示すコマンドウィンドウの束を開きます。
-探しているものが見つかった場合は、次のように実行します: `git stash pully(your hash)`。
最善の解決策ではないかもしれませんが、私にとってはうまくいきました。
アリストテレスが認めた回答は、非スタッシュのようなコミットを含むすべての到達可能なコミットを表示します。 ノイズをフィルターするには:
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オン」が含まれるコミットのみが含まれます。
隠し場所をメッセージで保存した場合(例:. git stash save "My new 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
私のお気に入りは、このワンライナーです。
git log --oneline $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )
これは基本的にこの回答と同じ考えですが、はるかに短いです。 もちろん、「--graph」を追加して、ツリーのような表示を取得することもできます。
リストでコミットが見つかったら、一緒に申請してください。
git stash apply THE_COMMIT_HASH_FOUND
私にとって、「--no-reflogs」を使用すると、失われた隠し場所が明らかになりましたが、「--到達不可能」(他の多くの回答にあるように)は明らかになりませんでした。
Windowsを使用している場合は、git bashで実行してください。
クレジット:上記のコマンドの詳細は、https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bfから取得されます。
私が探しにここに来たのは、チェックアウトした内容に関係なく、実際に隠し場所を取り戻す方法です。 特に、何かを隠して、古いバージョンをチェックアウトしてからポップしましたが、その以前の時点では隠し場所はノーオプだったので、隠し場所は消えていました。スタックに戻すために「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 pop」ではなく「git stash pulate」を使用していたはずです。 私は「bisect」を行っていて、すべての「bisect」ステップに適用したい小さなパッチがありました。 今私はこれをやっています:
$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.
次の手順を使用してそれを回復しました。
1。 削除された隠しハッシュコードを特定します。
gitk --all $(git fsck --no-reflog | awk '/ dangling commit / {print $ 3}')。
2。 チェリーピックザスタッシュ:
git cherry-pick -m 1 $ stash_hash_code。
3。 競合がある場合は解決します。
git mergetool。
さらに、gerritを使用している場合、コミットメッセージに問題がある可能性があります。 次の選択肢に従う前に、変更を隠してください。
1。 以前のコミットにハードリセットを使用してから、この変更を再コミットします。 2。 また、変更を隠し、リベースして再コミットすることもできます。