web-dev-qa-db-ja.com

Git Stashから単一のファイル(またはファイルへの変更)を抽出する方法を教えてください。

Stashチェンジセットをポップすることなく、git stashから単一のファイルまたはファイルの差分を抽出することが可能かどうかを知りたいです。

誰もがこれについていくつかの提案/アイデアを提供することができますか?

652
Danny

git stash のマンページで、それを読むことができます(「ディスカッション」セクションの「オプション」の説明の直後)。

隠し場所は、作業ディレクトリの状態をツリーが記録するコミットとして表され、その最初の親は、隠し場所が作成されたときのHEADでのコミットです。

ですから、stash(例えばstash@{0}が最初の/一番上のstash)をマージコミットとして扱うことができます。

$ git diff stash@{0}^1 stash@{0} -- <filename>

説明:stash@{0}^1ショートカットは与えられた隠し場所の最初の親を意味します。これは上の説明で述べたように変更が隠されたときのコミットです。 stash@{0}/refs/stashはマージコミットなので、この形式の "git diff"(2つのコミット)を使用します。また、gitにどの親に対してdiffを適用するかを指定する必要があります。もっと不可解:

$ git diff stash@{0}^! -- <filename>

rev^!構文の説明については、(範囲の指定の節の git rev-parse のマンページを参照してください)も動作するはずです。

同様に、 git checkout を使用して、隠しファイルから単一のファイルをチェックアウトできます。

$ git checkout stash@{0} -- <filename>

または別のファイル名で保存するには

$ git show stash@{0}:<full filename>  >  <newfile>

または

$ git show stash@{0}:./<relative filename> > <newfile>

ここで<full filename>は、プロジェクトの最上位ディレクトリを基準としたファイルの絶対パス名です(think:stash@{0}を基準とした相対パス))。


stash@{0}をシェルの展開から保護する必要があるかもしれません、すなわち"stash@{0}"または'stash@{0}'を使用してください。

965
Jakub Narębski

git stash applyではなくgit stash popを使用すると、作業用ツリーに隠し場所が適用されますが、それでも隠し場所は残ります。

これで、必要なファイルをadd/commitにして、残りの変更をリセットすることができます。

37
Tim Henigan

短い答え

ファイル全体を見るには:git show stash@{0}:<filename>

差分を見るには:git diff stash@{0}^1 stash@{0} -- <filename>

19
Luboš Turek

隠し場所を含め、どのブランチからでも変更を加える簡単な方法があります。

$ git checkout --patch stash@{0} path/to/file

多くの部分にパッチを当てたい場合は、ファイルの指定を省略することができます。 1つのファイルに対するすべての変更を取得するには、patchを省略します(パスは省略します)。 0git stash listの隠し番号に置き換えます(複数ある場合)。これはdiffに似ており、ブランチ間でallの違いを適用することを提案しています。単一のコミット/隠し場所だけから変更を得るには、git cherry-pick --no-commitを見てください。

16
Walf
$ git checkout stash@{0} -- <filename>

ノート:

  1. を " - "とファイル名パラメータの後にスペースを入れてください。

  2. ゼロ(0)を特定の隠し番号に置き換えます。隠しリストを取得するには、次のようにします。

    git stash list
    

JakubNarębskiの回答に基づく - より短いバージョン

12
Ram

あなたは "git show stash@{0}"を使って隠し場所の差分を得ることができます(あるいは隠し場所の数がいくらでも。 "git stashリスト"を見てください)。単一ファイルの差分のセクションを抽出するのは簡単です。

10
Nathan Kitchen

理解するための最も簡単な概念は、おそらく最善ではないかもしれませんが、3つのファイルを変更し、1つのファイルを隠したいということです。

それらすべてを隠すためにgit stashを実行する場合は、それらを再び元に戻すためにgit stash applyを実行してから、効果的にリセットするために問題のファイルにgit checkout f.cを実行します。

そのファイルを隠したくない場合は、git reset --hardを実行し、次にgit stash applyを再度実行します。これは、git stash applyがstashスタックから差分を消去しないことを利用したものです。

5
Philluminati

隠しファイルを現在のバージョンとマージする必要がある場合は、以前の方法でdiffを使用してください。それ以外の場合は、git popを使用してファイルを隠し、git add fileWantToKeepを使用してファイルをステージングし、git stash save --keep-indexを実行して、ステージ上にあるもの以外のすべてを隠します。これまでの方法との違いは、ファイルがstashから「ポップ」されることです。これまでの答えはgit checkout stash@{0} -- <filename>ですので、あなたのニーズに合わせています。