1. ホーム
  2. git

[解決済み] コミットされていない変更を保存したまま復元する方法

2022-03-20 11:12:14

質問

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

また、その後、隠したコードファイルの上にいくつかの変更を加えています。

可能であれば、隠した変更を新しいブランチに回収することはできないでしょうか?

解決方法は?

簡単な質問に対する答えは 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 の初心者にとっては同じ程度のことであるはずです。 (そして、この続きはすべて読み飛ばして構いません!)


より高度なこと、より複雑なことをする場合はどうすればいいのでしょうか?

git stashの使い方には、少なくとも3つか4つの異なる方法があります。 上記はそのうちの1つ、「簡単な方法」です。

  1. クリーンブランチで作業を開始し、いくつかの変更を行っていたところ、間違ったブランチで作業を行っていることに気づいたとします。 今ある変更を、別のブランチに "移動" したいだけなのです。

これは、上記のような簡単なケースです。 実行 git stash save (または、プレーンな git stash 同じことです)。 他のブランチをチェックアウトして git stash apply . これは、Git の強力なマージ・メカニズムによって、あなたの以前の変更をマージさせるものです。 結果をよく確認する (を使用)。 git diff ) を使って、気に入ったものがあるかどうか確認し、気に入ったものがあれば git stash drop を入力して、隠し場所を落とします。 これで完了です。

  1. あなたはいくつかの変更を開始し、それを隠した。 そして別のブランチに移ってさらに変更を加えましたが、隠した変更があることを忘れていました。

今度は、そのまま、あるいは移動したいのですね。 これら を変更しました。 は、あなたの隠し場所も適用します。

実際にできること git stash save として、再び git stash は、変更の "スタック" を作ります。 このようにすると、2つのスタッシュができ、1つは単に stash -と書くこともできますが stash@{0} -と綴られたものがあります。 stash@{1} . 使用方法 git stash list (いつでも)全部見ることができます。 最新のものは常に番号の小さいものです。 このとき git stash drop の場合、一番新しいものを落とし、その後に stash@{1} はスタックの一番上に移動します。 もし、さらに、その中の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 -または git rm -を実行する前に、コードの特定のビットを編集します。 git stash save . あなたは、あるバージョンを隠したインデックス/ステージング・エリアに置き、別の(異なる)バージョンを作業ツリーに置いていました。 これをすべて保存しておきたい。 そこで、今度は git stash apply --index で失敗することがある。

    Conflicts in index.  Try without --index.
    
    
  2. あなたが使っているのは git stash save --keep-index をテストするために、quot;何がコミットされるのか"。 これはこの回答の範囲を超えています。 この他の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

これで、"clean"のスタート地点に立てました。 あるいは、もっとこうかもしれません。

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

主に、"stash" これはコミットではなく、ブランチ上ではない、ちょっとおかしな、変なコミットです。 その apply 操作は、コミットが何を変更したかを調べ、あなたが今いる場所でそれを繰り返そうとします。 隠し場所はまだそこにあります ( apply が保持する) ので、それをもっと見たり、ここが間違った場所だったと判断したりすることができます。 apply を追加し、別の方法で再試行する、など。


隠し場所があれば、いつでも git stash show -p をクリックすると、スタッシュの中身を簡略化して見ることができます。 (この簡易版は、"final work tree"の変更点のみを見ています。 ではなく 保存されたインデックスの変更 --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

ここで "apply"の順序を選択し、特定の隠し場所を選んで特定の順序で適用することができます。 しかし、基本的には毎回 "git merge" を行うことになるので、マージに関するドキュメントで警告されているとおりです。

非自明な未コミット変更で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 は、説明するのは簡単ですが、内部的には少し複雑です。

  • 変更があった場合は git add (またはステージング)する前に commit -をつける。
  • したがって、あなたが実行したとき git stash を選択した場合、あなたは かもしれない 両方のファイルを編集している foozorg が、そのうちの1つだけを演出しました。
  • だから、スタッシュを返してもらうときに、それがあればいいのかもしれない。 git addadded を行う。 ない git add 付加されないもの。 つまり、もしあなたが add -編 foo ただし zorg を実行する前に戻って stash というように、全く同じ設定にしておくといいかもしれません。 ステージングされたものは、再びステージングされるべきであり、修正されたがステージングされていないものは、再び修正されたがステージングされていないものであるべきです。

その --index フラグを apply はこのように設定しようとします。 作業ツリーがきれいなら、これはたいていうまくいきます。 作業ツリーにすでに add -しかし、ここで問題が発生する可能性があることはおわかりいただけるでしょう。 もし --index は、その apply 操作では、ステージ/アンステージのセットアップ全体を保存しようとはしません。 その代わり、Git のマージ機構を起動し、作業ツリーのコミットを 隠し袋です。 . ステージング/アンステージの保存にこだわらない場合は --index を使用することで、より簡単に git stash apply を実行することができます。