スタッシュチェンジセットをポップオフせずに、gitスタッシュから単一のファイルまたはファイルの差分を抽出することは可能ですか?
9 に答える
git stashのマンページでは、(「ディスカッション」セクションの「オプション」の説明の直後に)次のように読むことができます。
stashは、ツリーが作業ディレクトリの状態を記録するコミットとして表され、その最初の親は、stashが作成されたときのHEADでのコミットです。
したがって、stash(たとえばstash@{0}
、最初/最上位のstash)をマージコミットとして扱い、次を使用できます。
$ git diff stash@{0}^1 stash@{0} -- <filename>
説明:stash@{0}^1
指定された隠し場所の最初の親を意味します。これは、上記の説明で述べたように、変更が隠されたコミットです。stash@{0}
/はマージコミットであるため、この形式の「git diff」(2つのコミットを含む)を使用しrefs/stash
、どの親に対して差分をとるかをgitに指示する必要があります。もっと謎めいた:
$ git diff stash@{0}^! -- <filename>
動作するはずです(構文の説明については、「範囲の指定」セクションのgit rev-parseのマンページを参照してください)。rev^!
同様に、git checkoutを使用して、スタッシュから1つのファイルをチェックアウトできます。
$ git checkout stash@{0} -- <filename>
または別のファイル名で保存するには:
$ git show stash@{0}:<full filename> > <newfile>
また
$ git show stash@{0}:./<relative filename> > <newfile>
(ここで、<full filename>は、プロジェクトの最上位ディレクトリを基準にしたファイルの絶対パス名であることに注意してください(例:relative to stash@{0}
))。
stash@{0}
シェルの拡張から保護する必要がある場合があります。つまり、"stash@{0}"
またはを使用します'stash@{0}'
。
git stash apply
ではなくを使用するgit stash pop
と、作業ツリーにスタッシュが適用されますが、スタッシュは保持されます。
これが完了すると、add
/必要なcommit
ファイルを作成し、残りの変更をリセットできます。
編集:cambunctiousの回答を参照してください。これは、現在の状態と比較するのではなく、隠し場所の変更のみを使用するため、基本的に私が現在好んでいるものです。これにより、操作が追加され、スタッシュが作成されてから行われた作業を元に戻す可能性がはるかに低くなります。
インタラクティブに行うには、最初に
git diff stash^! -- path/to/relevant/file/in/stash.ext perhaps/another/file.ext > my.patch
...次に、パッチファイルをテキストエディタで開き、必要に応じて変更してから、
git apply < my.patch
cambunctiousの答えは、1つのコマンドを別のコマンドに直接パイプすることによって対話性をバイパスします。これは、隠し場所からすべての変更が必要であることがわかっている場合は問題ありません。を編集しstash^!
て、必要な累積変更を含む任意のコミット範囲にすることができます(ただし、最初にdiffの出力を確認してください)。
patch / diffの適用が失敗した場合は、可能なすべての変更を行う最後のコマンドを変更し、解決できない競合があるファイルgit apply --reject
を残すことができます。ファイルは、次.rej
のようにを使用して適用できます。.rej
wiggle
wiggle --replace path/to/relevant/file/in/stash.ext{,.rej}
これにより、競合が解決されるか、マージから取得する競合マーカーが提供されます。
ディストリビューションにがない場合はwiggle
、ビルドするだけです。
cd /usr/local/src/
git clone git://git.neil.brown.name/wiggle
cd wiggle/
git checkout v1.3
make install
以前の解決策:スタッシュを含む任意のブランチから変更を取得する簡単な方法があります。
$ git checkout --patch stash@{0} path/to/file
多くの部分にパッチを適用する場合は、ファイル仕様を省略できます。または、パッチ(パスではなく)を省略して、すべての変更を1つのファイルに取得します。複数ある場合は0
、のスタッシュ番号に置き換えてください。git stash list
これはのようなものであり、ブランチ間のすべての違いdiff
を適用することを提案していることに注意してください。単一のコミット/スタッシュからのみ変更を取得するには、を参照してください。git cherry-pick --no-commit
$ git checkout stash@{0} -- <filename>
ノート:
「-」とファイル名パラメータの後に必ずスペースを入れてください
zero(0)を特定のスタッシュ番号に置き換えます。スタッシュリストを取得するには、次を使用します。
git stash list
JakubNarębskiの回答に基づく-短いバージョン
短い答え
ファイル全体を表示するには:git show stash@{0}:<filename>
差分を表示するには:git diff stash@{0}^1 stash@{0} -- <filename>
以下を使用して、スタッシュ内のファイルへの変更を作業ツリーに適用します。
git diff stash^! -- <filename> | git apply
git checkout
スタッシュを作成してからファイルに加えた変更が失われることはないため、これは一般的に使用するよりも優れています。
git show stash@{0}
「 」(またはスタッシュの数に関係なく、「git stashlist」を参照)を使用して、スタッシュの差分を取得できます。単一のファイルの差分のセクションを抽出するのは簡単です。
理解するのに最も簡単な概念は、最善ではないかもしれませんが、3つのファイルを変更し、1つのファイルを隠したいというものです。
git stash
それらをすべて隠しておく場合は、git stash apply
それらを元に戻しgit checkout f.c
、問題のファイルで効果的にリセットします。
そのファイルのスタッシュを解除したい場合は、スタッシュスタックからの差分をクリアしないという事実を利用して、を実行してgit reset --hard
から再度実行します。git stash apply
git stash apply
隠しファイルを現在のバージョンとマージする必要がある場合は、diffを使用して以前の方法を使用してください。それ以外の場合はgit pop
、それらをアンスタッシュするgit add fileWantToKeep
ため、ファイルをステージングするため、およびgit stash save --keep-index
ステージ上にあるものを除くすべてをスタッシュするためにを使用する可能性があります。この方法と以前の方法との違いは、ファイルをstashから「ポップ」することです。前の答えはそれを維持するgit checkout stash@{0} -- <filename>
ので、あなたのニーズに応じて進みます。