Вопрос

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

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

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

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

Это было полезно?

Решение

Согласно Справочная страница 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

Редактировать:

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

git stash show -p | git apply --reverse

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

В последнее время мне это очень пригодилось...

Другие советы

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

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

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

git checkout -f

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

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

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

$ 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

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

git stash [сохранить] сохранит текущие изменения и установит текущую ветку в «чистое состояние»

git stash list выдает что-то вроде: stash @ {0}: В разработке: сохраненный материал для тестирования

git apply stash @ {0} установит текущую ветвь как до stash [сохранить]

git checkout. Устанавливает текущую ветвь как после stash [сохранить]

Код, сохраненный в тайнике, не потерян, его можно найти снова git apply stash @ {0} .

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

В дополнение к ответу @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

Это в дополнение к ответам, приведенным выше, но добавляет поиск 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
}
<Ол>
  • Создать тайник с именем (сообщением) $ git stash save " my stash "
  • Чтобы применить имя $ apply " мой тайник "
  • Чтобы удалить именованный тайник $ remove " my stash "
  • Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top