隠されたコミットされていない変更を回復する方法


690

開発ブランチにコミットされていない変更git stashがあり、を使用してそれらを隠しましたが、それらの隠されたものの中で非常に重要な変更がいくつかありました。これらの変更を取り戻す方法はありますか?

また、それ以降、隠されたコードファイルに加えていくつかの変更を加えました。

可能であれば、隠された変更を新しいブランチに取得できる可能性はありますか?


7
「スタッシュポップ」を使ってみましたか?
robert

いいえ。実際、私はgitを初めて使用しています。私はすべてのコマンドを完全には認識していないので、他には何もしませんでした!これらの変更を失いたくない。
Aswathy Pクリシュナン2013

33
隠された変更を失いたくない場合は、「git stash apply」を使用してみてください。これにより、隠しておいた変更を現在のブランチに適用しますが、隠し場所は保持します。すべて問題なければ、スタッシュを適用した後、「git stash drop」を使用してスタッシュをドロップできます
robert

2
@robert非常に複雑な(初心者にとって)受け入れられた回答と比較して、単純な回答をありがとうございます。
Saheel Godhane 14

回答:


1184

簡単な質問に対する簡単な答えは git stash apply

変更したいブランチをチェックアウトし、次にgit stash apply。次に、を使用git diffして結果を確認します。

変更がすべて完了したら(apply見た目はよく、スタッシュはもう必要ないはずです)、次にを使用git stash dropしてそれを取り除きます。

git stash applyではなくを使用することを常にお勧めしgit stash popます。違いは、applyを簡単に再試行しapplyたり、見たりするためにスタッシュを残してpopおくことです。スタッシュを抽出できる場合は、スタッシュもすぐに抽出されdropます。また、突然どこかに抽出したいと思った場合それ以外の場合(別のブランチ内)、または、--indexなどを使用するのは簡単ではありません。もしそうならapplyあなたはいつするかを選ぶことができますdrop

いずれにせよ、それはすべてかなりマイナーであり、初心者がgitを使用する場合、それはほぼ同じになるはずです。(そして、これ以降はすべてスキップできます!)


より高度な、またはより複雑なことをしている場合はどうなりますか?

少なくとも3つまたは4つの「git stashを使用する方法」があります。上記は「ウェイ1」、「イージーウェイ」の場合です。

  1. あなたはクリーンなブランチから始めて、いくつかの変更に取り組んでいて、それからあなたが間違ったブランチでそれらを行っていることに気づきました。現在の変更を取得して、それらを別のブランチに「移動」したいだけです。

    これは、上記の簡単なケースです。実行しますgit stash save(またはプレーンgit stash、同じこと)。他のブランチをチェックアウトして使用してくださいgit stash apply。これにより、gitの強力なマージメカニズムを使用して、以前の変更にgitがマージされます。 結果を慎重に(を使用してgit diff)調べ、気に入ったかどうかを確認します。気に入った場合は、を使用git stash dropしてスタッシュをドロップします。完了です!

  2. あなたはいくつかの変更を開始し、それらを隠しました。次に、別のブランチに切り替えて、隠していたブランチを忘れて、さらに変更を開始しました。

    今、あなたは維持し、あるいは、移動するこれらの変更を、そしてあまりにもあなたのスタッシュを適用します。

    変更の「スタック」を作成するので、実際にはgit stash save再びできgit stashます。その場合、2つの隠し場所があります。1つはたった今呼び出されstashますstash@{0}— しかし、あなたは書くこともできます— 1つは綴られstash@{1}ます。git stash listそれらをすべて表示するには、(いつでも)を使用してください。最新は常に最小番号です。あなたgit stash dropがいるとき、それは最新のものを落とし、そしてあったものstash@{1}はスタックの一番上に移動します。さらに多くある場合は、になったものがにstash@{2}なりstash@{1}ます。

    あなたのことができapply、その後、drop特定のスタッシュ、あまりにも:git stash apply stash@{2}、など。特定のスタッシュをドロップすると、番号の大きいものだけが再番号付けされます。繰り返しますが、番号のないものもstash@{0}です。

    たくさんの隠し場所を重ねると、かなり乱雑になる可能性があります(私が欲しかった隠し場所stash@{7}だったのstash@{4}でしょうか、それともそうでしたか?待って、私はもう1つ押しましたが、今は8と5です)。私は個人的にこれらの変更を新しいブランチに転送することを好みます。ブランチには名前があり、cleanup-attempt-in-December私よりも多くのことを意味するからですstash@{12}。(このgit stashコマンドはオプションの保存メッセージを受け取り、それらは役立ちますが、どういうわけか、私のすべての隠し場所は、という名前で終了しWIP on branchます。)

  3. (追加)実行する前に、コードの特定のビットを使用git stash save -pしたり、注意深くgit add編集したり、git rm特定のビットを使用したgit stash save。隠されたインデックス/ステージング領域に1つのバージョンがあり、作業ツリーに別の(異なる)バージョンがありました。このすべてを保存したい。だから今あなたはを使っていますgit stash apply --index、そしてそれは時々失敗します:

    Conflicts in index.  Try without --index.
    
  4. git stash save --keep-index「何がコミットされるか」をテストするために使用しています。これはこの回答の範囲を超えています。代わりに、この他のStackOverflowの回答を参照してください。

複雑なケースでは、現在の変更を(必要に応じて新しいブランチで)コミットして、まず「クリーン」な作業ディレクトリから開始することをお勧めします。そうすれば、それらを適用する「どこか」に他に何も含まれず、隠された変更を試すだけになります。

git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes

これで「クリーン」な出発点になりました。または多分それはこのようになります:

git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

覚えておくべき主なことは、「スタッシュ」コミットであり、「ブランチ上」ではない、ほんの少し「おかしい/奇妙な」コミットであることです。apply変更し、そしてあなたが今どこにいても、それを繰り返すようにしようとどのコミット時の動作ルックス。隠し場所はまだそこにあります(applyそれを保持します)ので、もっと見ることができます。または、これが間違った場所applyであると判断して、別の方法で再試行することもできます。


隠し場所を持っているときはいつでも、隠し場所にgit stash show -pあるものの簡略バージョンを表示するために使用できます。(この簡略化されたバージョンでは、「最終作業ツリー」の変更のみが確認され、個別に復元される保存されたインデックスの変更は確認されません--index。)git stash applyなしのコマンドは、作業ディレクトリに同じ変更を--index加えようとします。

これは、すでにいくつかの変更がある場合でも当てはまります。applyコマンドはにスタッシュを適用させていただき修正(それを適用しようとする、または少なくとも)作業ディレクトリ。たとえば、これを行うことができます:

git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too

ここで「適用」の順序を選択し、特定のスタッシュを選択して特定の順序で適用できます。ただし、基本的には「gitマージ」を実行するたびに、マージのドキュメントに警告があります。

自明ではないコミットされていない変更でgitマージを実行することはお勧めしません。可能な場合は、競合が発生した場合に元に戻せない状態になる可能性があります。

クリーンディレクトリから始めて、いくつかのgit apply操作を実行しているだけであれば、簡単に取り消せgit reset --hardますapply。クリーン状態に戻し、操作を変更するために使用します。(そのため、これらの複雑なケースでは、まずクリーンな作業ディレクトリから開始することをお勧めします。)


最悪のケースはどうですか?

たくさんの高度なGitスタッフを実行していて、スタッシュを作成し、それをしたいとgit stash apply --indexしますが、保存したスタッシュを--indexで適用できなくなったのは、ブランチを保存したときから分岐が多すぎるためです。

これがgit stash branch目的です。

もし、あんたが:

  1. チェックアウト正確なコミットあなたは、元をしたときにあったstash、その後、
  2. 新しいブランチを作成し、最後に
  3. git stash apply --index

変更を再作成する試みは確実機能します。これが何をするかです。(そして、正常に適用されたため、スタッシュをドロップします。)git stash branch newbranch


--index(一体何なのか)についての最後の言葉

--index行うことは説明するのは簡単ですが、少しは内部で複雑:

  • 変更がある場合は、変更git addする前に変更(または「ステージング」)commitする必要があります。
  • あなたが実行したときにこのように、git stashあなたは可能性がある両方のファイルを編集しているfoozorg、だけそれらのいずれかを上演しました。
  • あなたはスタッシュを取り戻すために要求したとき、それがあれば、それはいいことかもしれませんgit addaddエドの事をしてないない git addものを非追加しました。つまり、を実行する前にaddedを実行して戻ってfooいないzorg場合は、stashまったく同じ設定にするとよいでしょう。上演されたものは、再び上演されるべきです。変更されたがステージングされなかったものは、再度変更されたがステージングされるべきではない。

--indexフラグをapplyこのように設定しようとするもの。作業ツリーがクリーンである場合、これは通常は機能します。addただし、作業ツリーに既にed が含まれている場合は、ここで問題が発生する可能性があることを確認できます。省略した場合--indexapply操作はステージングされた/ステージングされていないセットアップ全体を保持しようとはしません。代わりに、「stash bag」のワークツリーコミットを使用して、gitのマージ機構を呼び出すだけです。ステージング/アンステージングを保持する必要がない場合は、除外--indexすることにより、処理が非常に簡単にgit stash applyなります。


2
コメントが理解できません。もしかして:あなたが走ったgit stash pop?あるいは、一部のファイルを編集したが、git stashまだまだ実行していないということですか?それとも完全に別の意味ですか?
torek 2013

1
はい。私の(長い)編集ではapply、隠しておく前に、今あるものをコミットすることをお勧めします。これを行う必要はありません、これにより、物事をより簡単に見ることができます。rebase -i複数のコミットをつぶしたり、特定の変更をチェリーピックしたりするために使用できます。
torek 2013

1
はい:git stash apply --index(2つのダッシュを覚えておいてください)。省略して--indexも大したことはありません。唯一のポイントは--index、段階的/段階的でないセットアップを維持することです。(おそらく、最初に特別な設定を行っていなかったでしょう。)次にgit status、必要に応じて追加/コミットなどを行います。すべてのスタッシュが終了したら(そしてそのときのみ)、を使用git stash dropしてそれを破棄します。
torek 2013

1
stash コミットしているため、stash を保持する(保持しない、dropまたは保持する)限りpop、元のstashされたコードは常にコミットしても安全です。正確に元に戻したいがブランチ上で使用する場合は、上記のセクションを参照するか、Shunyaの回答のPro Gitブックを参照してください。その後、そのブランチ、またはそのブランチからのコミットなどを行うことができますgit stash branchgit checkoutgit cherry-pick
torek

2
@ChuckWolber:Gitの命名規則により、多くのことが望まれます(「リモート」、「トラッキング」、および「ブランチ」という単語に、いくつの異なる意味を割り当てることができますか?)。ただし、元の隠し場所とは関係のないものに隠し場所を適用できることは注目に値します。
torek

57
git stash pop

すべてを元の場所に戻します

コメントで提案されているようにgit stash branch newbranch、スタッシュを新しいブランチに適用するために使用できます。これは実行と同じです。

git checkout -b newbranch
git stash pop

助けてくれてありがとう。それらの変更を新しいブランチに入れることはできますか?現在、私はブランチを開発しています
Aswathy Pクリシュナン2013

3
git stashブランチnewbranchは、変更を隠した新しいブランチを作成します。
ロバート

3
@robert:git stash branch newbranch確かにそうするでしょう。ただし、新しいブランチが作成され、親が設定さHEADれた時点のコミットに設定されていることに注意してstashください。言い換えると、長いハッキングセッションなどの後で戻ってきて、混乱をじっと見て、「隠しておくのではなく、ブランチに置くべきだった」と判断した場合です:-)
torek

質問を編集しました。可能であれば、これらの変更を新しいブランチに適用したいと考えています。
Aswathy Pクリシュナン2013

1
時々、TLDRの回答が欲しいだけです:)
sachinruk

24

これを簡単にするために、スタッシュを再適用する2つのオプションがあります。

  1. git stash pop -保存された状態に復元しますが、一時ストレージからスタッシュを削除します。
  2. git stash apply -保存した状態に復元し、後で再利用できるように隠しリストを残します。

git stashの詳細については、この記事をご覧ください。


19

stashの内容を確認するには:-

git stashリスト

stashリストから特定のstash noを適用します:-

git stash stash @ {2}を適用

または最初の隠し場所のみを適用する場合:

git stash pop

注: git stash popはstashリストからstashを削除しますが、git stashは適用されません。それに応じてそれらを使用してください。


2

Macではこれは私にとってうまくいきました:

git stashリスト(すべてのstashを表示)

git stash list

git stash apply(stashリストから必要な数だけ)

このような:

git stash apply 1

0

「git stash」を使用してコミットされていない変更を隠しておき、「git checkout -b」を使用して新しいブランチにチェックアウトしてから、隠されたコミットを適用することができます「git stash apply」

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.