Як змінити застосувати приховану скриньку?


233

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

Хтось знає, як це зробити?

Пояснення. У моїй робочій копії є інші зміни. Мій конкретний випадок важко описати, але ви можете уявити собі налагодження або експериментальний код, який знаходиться в скрині. Тепер він змішується в моїй робочій копії з деякими іншими змінами, і я хотів би побачити ефект із змінами та без них.

Наразі це не схоже на приховану підтримку, але це git stash apply --reverseбуло б приємною особливістю.


1
Не можна просто створити зворотний патч, відрізняючи поточну та попередню версію? А потім застосувати це?
ralphtheninja

Чи є зміни в робочому дереві, крім застосованого сховища?
Грег Бекон

Додаючи це сюди, ... повинен був бути питання не питанням ... stackoverflow.com/questions/59973103/…
Дон Томас Бойл

Відповіді:


188

Відповідно до сторінки " 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.

Я знайшов це дуже зручно останнім часом ...


2
Дивовижне, спасибі Схоже, це може бути гарною особливістю для сховища.
Пат Нотз

5
Так, git apply -Rце покращення, принаймні для мене на моєму вікні вікна з git bash, оскільки patch --reverseвиникли проблеми з пошуку файлу для виправлення (немає реальної підказки, чому альтернатива працювала). +1 та гарне пояснення
hakre

не було б краще додати --indexпросто так git stash show -p | git apply --reverse --index. Тому що вам більше не потрібно додавати в індекс зміни, які повертаються назад.
theNorknown777

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. Ви знаєте, що може бути не так?
Макс Корецький

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

1
Це було набагато простіше
Марк А

Це було приголомшливо!
Кіран Ск

22

На сторінці V1 git man було посилання про неприйняття сховища. Уривок нижче.

Новіша сторінка Vit git man не містить жодних посилань на неприкладення скрині, але нижче все ще працює добре

Скасування застосування скриньки У деяких сценаріях використання випадків, можливо, ви захочете застосувати приховані зміни, виконати певну роботу, але потім скасувати застосування цих змін, які спочатку з’явилися з папки. Git не забезпечує таку команду приховування un-apply, але досягти ефекту можна, просто витягнувши патч, пов’язаний із сховищем, та застосувавши його у зворотному порядку:

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

Знову ж таки, якщо ви не вказали скриньку, Git передбачає останню скриньку:

$ git stash show -p | git apply -R

Ви можете створити псевдонім і ефективно додати команду приховування-неприкладності до свого 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 - прибирання та чистка . Можливо, тому, що автори думають, що є кращий спосіб зробити це, що я, здається, не можу знайти.
Над Алаба

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

Це, безумовно, найпростіший спосіб, якщо у вас абсолютно немає місцевої роботи, яку ви хочете зберегти. Якщо ви застосували неправильну скриньку до гілки або потрапили в конфлікти злиття, які ви не хочете вирішити, це швидкий і простий спосіб скасувати її, повністю повернувши свій робочий набір до останньої фіксації вашої філії.
Шадоніня

2

Окрім відповіді @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

Це на додаток до вищезазначених відповідей, але додає пошук сховища 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"

0

Ви можете слідкувати за зображенням, яким я поділився, щоб зняти знімок, якщо ви випадково натиснули на призупинення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.