Как поменять, применить тайник? - PullRequest
195 голосов
/ 20 июня 2009

У меня есть небольшой патч, сохраненный в моем git stash. Я применил его к своей рабочей копии, используя git stash apply. Теперь я хотел бы отменить эти изменения, применив патч в обратном порядке (вроде того, что бы сделал git revert, но против тайника).

Кто-нибудь знает, как это сделать?

Уточнение: В моей рабочей копии есть другие изменения. Мой конкретный случай трудно описать, но вы можете представить некоторый отладочный или экспериментальный код, который находится в тайнике. Теперь он смешан в моей рабочей копии с некоторыми другими изменениями, и я хотел бы видеть эффект с изменениями из хранилища и без них.

Не похоже, что stash поддерживает это в настоящее время, но git stash apply --reverse была бы хорошей функцией.

Ответы [ 7 ]

164 голосов
/ 20 июня 2009

Согласно справочной странице git-stash , «хранилище представляется в виде коммита, дерево которого записывает состояние рабочего каталога, а его первым родителем является коммит в HEAD, когда был сохранен создал, "и git stash show -p дает нам" изменения, записанные в тайнике в виде различий между сохраненным состоянием и его исходным родителем.

Чтобы сохранить другие изменения без изменений, используйте 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

Edit:

Легким улучшением является использование git apply вместо патча:

git stash show -p | git apply --reverse

В качестве альтернативы, вы также можете использовать git apply -R как сокращение к git apply --reverse.

В последнее время я находил это очень удобным ...

71 голосов
/ 20 июня 2009

git stash[save] принимает ваше рабочее состояние каталога и состояние вашего индекса и сохраняет их, устанавливая индекс и рабочую область на HEAD версию.

git stash apply возвращает эти изменения, поэтому git reset --hard удаляет их снова.

git stash pop возвращает эти изменения и удаляет изменение, сохраненное сверху, поэтому в этом случае git stash [save] вернется в предыдущее состояние (до появления).

55 голосов
/ 06 ноября 2016
git checkout -f

удалит все не зафиксированные изменения.

18 голосов
/ 23 апреля 2015

Прямая нарезка n пасты из справочной страницы git Это ясно сформулировано и даже включает псевдоним;

Отмена применения тайника В некоторых сценариях использования вы можете применить скрытые изменения, выполнить некоторую работу, но затем отменить те изменения, которые изначально были получены из хранилища. Git не предоставляет такой команды stash unapply, но добиться эффекта можно, просто извлекая патч, связанный с 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
13 голосов
/ 22 апреля 2014

Это давно истекло, но если я правильно истолковал проблему, я нашел простое решение, обратите внимание, это объяснение в моей собственной терминологии:

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}.

В любом случае, это сработало для меня!

1 голос
/ 17 октября 2017

Помимо ответа @Greg Bacon, в случае, если двоичные файлы были добавлены в индекс и были частью тайника с использованием

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 голосов
/ 05 июня 2018

Это в дополнение к ответам, приведенным выше, но добавляет поиск git stash на основе сообщения, так как номер stash может измениться при сохранении новых stash. Я написал пару функций 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"
...