保存されたコミットされていない変更を復元する方法 質問する

保存されたコミットされていない変更を復元する方法 質問する

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

また、それ以来、保存されたコード ファイルにいくつか変更を加えました。

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

ベストアンサー1

簡単な質問に対する簡単な答えは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スタッシュを削除します。これで完了です。

  1. いくつかの変更を開始し、それらをスタッシュしました。その後、別のブランチに切り替えて、スタッシュしたものがあることを忘れたまま、さらに変更を開始しました。

ここで、これらの変更を保持または移動し、スタッシュも適用する必要があります

実際に、 はgit stash save変更git stashの「スタック」を作成します。その場合、 という名前stash(ただし、 と書くこともできます)のスタッシュと、stash@{0}と綴ったスタッシュの 2 つのスタッシュが作成されます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}? ちょっと待ってください、別のものをプッシュしたばかりなのに、今は 8 と 5 になっています)。個人的には、これらの変更を新しいブランチに転送することを好みます。ブランチには名前があり、cleanup-attempt-in-Decemberよりも私にとってはずっと意味があるからですstash@{12}。(git stashコマンドはオプションの保存メッセージを受け取り、それが役立つこともありますが、どういうわけか、私のスタッシュはすべて という名前になりますWIP on branch。)

  1. (超上級) を使用するgit stash save -pか、を実行する前にコードの特定の部分を慎重にgit add-ed および/または-ed しました。 スタッシュされたインデックス/ステージング領域に 1 つのバージョンがあり、作業ツリーに別の (異なる) バージョンがありました。 これらをすべて保持したいとします。 そのため、 を使用しますが、次のエラーで失敗することがあります。git rmgit stash savegit stash apply --index

    Conflicts in index.  Try without --index.
    
  2. 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 a 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 merge を実行することは推奨されません。実行は可能ですが、競合が発生した場合に元に戻すのが困難な状態になる可能性があります。

クリーンなツリーから始めて、いくつかの操作だけを実行する場合は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の説明は簡単ですが、内部的には少々複雑です。

  • 変更がある場合は、 -ing するgit add前に変更をステージングする必要がありますcommit
  • したがって、 を実行したときにgit stash、ファイルと の両方を編集したが、そのうちの 1 つだけがステージングされた可能性があります。foozorg
  • したがって、スタッシュを戻すように要求する場合、追加した内容は戻し、追加しなかった内容は戻さない方がよいでしょうgit addaddedつまり、 を実行する前に -ed されたが戻されていない場合は まったく同じ設定にしておくとよいかもしれません。ステージングされたものは再度ステージングする必要があります。変更されたがステージングされなかったものは再度変更されたがステージングされない必要があります。git addaddfoozorgstash

フラグ--indexは、applyこのように設定しようとします。作業ツリーがクリーンな場合、これは通常うまく機能します。addただし、作業ツリーにすでに stuff が含まれている場合は、ここで問題が発生する可能性があります。 を省略すると--indexapply操作はステージング/未ステージング設定全体を保存しようとしません。代わりに、Gitのマージ機構を呼び出し、「隠し袋」ステージング済み/未ステージング済みの保存を気にしない場合は、 を省略すると、 が処理するのがはるか--indexに簡単になります。git stash apply

おすすめ記事