隠し場所を逆に適用する方法は?


233

小さなパッチをgit stashに保存しました。を使用して作業コピーに適用しましたgit stash apply。今、私はパッチを逆に適用することによってそれらの変更を取り消すことをgit revert望みます(何かのようなものですが、隠蔽に対して)。

誰でもこれを行う方法を知っていますか?

明確化:私の作業コピーには他の変更があります。私の特定のケースは説明するのが難しいですが、隠し場所にあるデバッグまたは実験的なコードを想像できます。今、それは私の作業コピーに他のいくつかの変更と混在しています。スタッシュからの変更がある場合とない場合の効果を確認したいと思います。

stashは現在これをサポートしているようには見えませんgit stash apply --reverseが、素晴らしい機能です。


1
現在のリビジョンと以前のリビジョンを比較して、リバースパッチを作成するだけでは不十分ですか?そしてそれを適用しますか?
ラルフテニンジャ2009年

適用されたスタッシュ以外に作業ツリーに変更はありますか?
グレッグベーコン

ここにこれを追加し、...よくある質問ない質問...になるはずだったstackoverflow.com/questions/59973103/...
ドン・トーマス・ボイル

回答:


188

よるとのgit -スタッシュマニュアルページ、「隠しは、その木の作業ディレクトリの状態を記録し、その最初の親がにコミットされコミットとして表されるHEADと、スタッシュを作成したときに」git stash show -p「私たちに記録された変更を与えますstashされた状態とその元の親との差分としてstashします。

他の変更をそのまま維持するにgit stash show -p | patch --reverseは、次のように使用します。

$ git init
Initialized empty Git repository in /tmp/repo/.git/

$ echo Hello, world >messages

$ git add messages

$ git commit -am 'Initial commit'
[master (root-commit)]: created 1ff2478: "Initial commit"
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 messages

$ echo Hello again >>messages

$ git stash

$ git status
# On branch master
nothing to commit (working directory clean)

$ git stash apply
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   messages
#
no changes added to commit (use "git add" and/or "git commit -a")

$ echo Howdy all >>messages

$ git diff
diff --git a/messages b/messages
index a5c1966..eade523 100644
--- a/messages
+++ b/messages
@@ -1 +1,3 @@
 Hello, world
+Hello again
+Howdy all

$ git stash show -p | patch --reverse
patching file messages
Hunk #1 succeeded at 1 with fuzz 1.

$ git diff
diff --git a/messages b/messages
index a5c1966..364fc91 100644
--- a/messages
+++ b/messages
@@ -1 +1,2 @@
 Hello, world
+Howdy all

編集:

これに対する軽い改善git applyはパッチの代わりに使用することです:

git stash show -p | git apply --reverse

または、のgit apply -R省略形として使用することもできますgit apply --reverse

最近これが本当に重宝しています...


2
素晴らしいです、ありがとう。これはstashの優れた機能のようです。
Pat Notz

5
はい、git apply -R改善です。少なくとも、私がgit bash patch --reverseを使用している私のWindowsボックスで、パッチを適用するファイルを見つけるのに問題があったためです(代替が機能した理由は本当の意味ではありません)。+1と良い説明
2013

--indexこのように追加した方がいいでしょうgit stash show -p | git apply --reverse --index。元に戻された変更をインデックスに追加する必要がなくなったためです。
theUnknown777 2015

3
@Greg Bacon、ねえ、私はあなたが概説したスクリプトを調べようとしましたgit stash show -p | git apply -R -vが、メッセージで実行するとパッチは失敗しました:Checking patch messages... error: while searching for: Hello, world Hello again error: patch failed: messages:1。何が悪いのか知っていますか?
Max Koretskyi 2015

5
エラー発生しました:パッチが失敗しました:/src/filename.java:46 エラー:src / filename.javaパッチが適用されません
Tim Boland

83

git stash[save]作業ディレクトリの状態とインデックスの状態を取り、それらを隠して、インデックスと作業領域をHEADバージョンに設定します。

git stash applyこれらの変更を元に戻すので、git reset --hard再び削除します。

git stash popこれらの変更を元に戻し、隠しておいた一番上の変更を削除するためgit stash [save]、この場合は以前の(ポップ前の)状態に戻ります。


82
git checkout -f

コミットされていない変更はすべて削除されます。


4
おかげで、あなたは私が適用されなかった段階的な変更から私を助けます。
Fa.Shapouri 2017年

1
これははるかに簡単でした
Mark A

これは最高でした!
キランSkの

22

V1 gitのmanページには、スタッシュの適用解除に関するリファレンスがありました。以下はその抜粋です。

新しいV2 gitのmanページには、スタッシュの適用を解除するための参照が含まれていませんが、以下は引き続き正常に機能します

スタッシュを解除し適用し 、あなたが隠した変更を適用したい場合がありますいくつかのユースケースのシナリオでいくつかの作業を行うが、その後もともとスタッシュから来たそれらの変更を非適用します。Gitはそのようなstash un-applyコマンドを提供していませんが、stashに関連付けられているパッチを取得して逆に適用するだけで効果を得ることができます。

$ git stash show -p stash@{0} | git apply -R

繰り返しますが、スタッシュを指定しない場合、Gitは最新のスタッシュを想定します。

$ git stash show -p | git apply -R

エイリアスを作成して、stash-unapplyコマンドをGitに効果的に追加することができます。例えば:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply

1
何らかの理由で、「スタッシュの適用解除」にリンクしたこの役立つセクションは、この本の第2版から削除されました- 最新バージョンは2.1.146、2019-04-15-この本V2- Git Tools-Stashing and Cleaning。これを行うには私が見つけられないように見えるより良い方法があると著者が考えているためかもしれません。
Nad Alaba、

@NadAlabaに感謝します。v1とv2の違いに注意するために回答を更新しました...奇妙なgitの作成者が隠し場所の解除に関するセクションを削除しました
Choco Smith

13

これは長い間待たされていましたが、問題を正しく解釈すると、簡単な解決策が見つかりました、これは私の独自の用語での説明です:

git stash [save] 現在の変更を保存し、現在のブランチを「クリーンな状態」に設定します

git stash list 次のようなものを与えます: stash@{0}: On develop: saved testing-stuff

git apply stash@{0}以前のよう現在のブランチを設定します stash [save]

git checkout .現在のブランチを後のよう設定します stash [save]

スタッシュに保存されているコードは失われませんgit apply stash@{0}。もう一度見つけることができます。

とにかく、これは私のために働いた!


念のために、私はgit stash apply --reverse最初に適用し、その後、git stash apply stash@{x}あなたが言うように単純に戻った。問題なく動作しました。
カルロスガルシア

3

隠し場所を逆に適用する方法は?

他の人が言ったことを除いて、最も簡単な方法は最初にすることです

git reset HEAD

ローカルの変更をすべてチェックアウトします

git checkout . 

保存したいローカルの作業がまったくない限り、これははるかに簡単な方法です。間違ったstashをブランチに適用したり、解決したくないマージ競合にヒットした場合、これは、ワーキングセットをブランチの最新のコミットに完全に戻すことで、すばやく簡単に元に戻すことができます。
Shadoninja

2

@Greg Baconの回答に加えて、バイナリファイルがインデックスに追加され、以下を使用してstashの一部である場合

git stash show -p | git apply --reverse

結果として

error: cannot apply binary patch to '<YOUR_NEW_FILE>' without full index line
error: <YOUR_NEW_FILE>: patch does not apply

追加--binaryすると問題は解決しますが、残念ながらまだその理由がわかりません。

 git stash show -p --binary | git apply --reverse


0

これは上記の回答に追加されますが、新しいスタッシュが保存されるとスタッシュ番号が変更される可能性があるため、メッセージに基づいてgitスタッシュの検索が追加されます。私はいくつかのbash関数を書きました:

apply(){
  if [ "$1" ]; then
    git stash apply `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"`
  fi
}
remove(){
  if [ "$1" ]; then
    git stash show -p `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"` | git apply -R
    git status
  fi
}
  1. 名前でスタッシュを作成(メッセージ) $ git stash save "my stash"
  2. 名前を付けて $ apply "my stash"
  3. 名前付きスタッシュを削除するには $ remove "my stash"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.