Почему `` w20> stash -p` иногда терпит неудачу?

I ♥ git stash -p. Но иногда, после удовлетворительного сеанса y, n и s, я получаю следующее:

Saved working directory and index state WIP on foo: 9794c1a lorum ipsum
error: patch failed: spec/models/thing_spec.rb:65
error: spec/models/thing_spec.rb: patch does not apply
Cannot remove worktree changes

Почему?

Ответ 1

git stash -p должен меньше терпеть неудачу с Git 2.17 (Q2 2018).
До этого " git add -p " (который разделяет логику с git stash) ленился в объединении разделенных патчей перед передачей результата в базовое " git apply ", что приводило к ошибкам в угловых случаях; логика для подготовки патча для применения после выбора фрагментов.

См. Коммит 3a8522f, коммит b3e0fcf, коммит 2b8ea7f (05 марта 2018 г.), коммит fecc6f3, коммит 23fea4c, коммит 902f414 (01 мар 2018 г.) и коммит 11489a6, коммит e4d671c, коммит 492e60c (19 февр. 2018) от Филиппа Вуда (phillipwood Wood).
(Объединено Юнио К Хамано - gitster - в коммите 436d18f, 14 марта 2018 г.)

add -p: отрегулировать смещения последующих блоков, когда один из них пропущен

(добавить, но опять же, можно применить к тайнику)

Так как commit 8cbd431 (" git-add--interactive: замените пересчет ханка на apply --recount", 2008-7-2, Git v1.6.0-rc0), если ханк пропущен, мы полагаемся на строки контекста, чтобы применить последующие сиськи в нужном месте.

Хотя это работает большую часть времени, возможно, что клочья в конечном итоге будут применены не в том месте.

Чтобы исправить это, отрегулируйте смещение последующих блоков, чтобы исправить любые изменения в количестве вставок или удалений из-за пропущенного блока. Изменение смещения из-за отредактированных фрагментов, у которых изменилось количество вставок или удалений, здесь игнорируется, оно будет исправлено в следующем коммите.

Вы можете увидеть некоторые тесты здесь.


Git 2.19 улучшает git add -p: когда пользователь редактирует патч в " git add -p ", а пользовательский редактор настроен на беспорядочную git add -p пробелов, пустая строка, которая не изменяется в патче, становится полностью пустой (вместо линия с единственным ИП на нем).
Код, введенный в таймфрейме Git 2.17, не смог разобрать такой патч, но теперь он научился замечать ситуацию и справляться с ней.

См. Коммит f4d35a6 (11 июня 2018 г.) Филиппа Вуда (phillipwood).
(Объединено Junio C Hamano - gitster - в коммите 5eb8da8, 28 июня 2018 г.)

add -p: исправить подсчет пустых строк контекста в отредактированных патчах

recount_edited_hunk() представленная в коммите 2b8ea7f ("add -p: вычислить дельту смещения для отредактированных патчей", 2018-03-05, Git v2.17.0), требует, чтобы все строки контекста начинались с пробела, пустые строки не учитываются.
Это было сделано для того, чтобы избежать каких-либо проблем с пересчетом, если пользователь вводил пустые строки в конце при редактировании патча.

Однако это ввело регрессию в ' git add -p ', так как кажется, что редакторы git add -p завершающий пробел из пустых строк контекста, когда исправления редактируются, тем самым вводя пустые строки, которые должны учитываться.
"git apply" знает, как обращаться с такими пустыми строками, и POSIX заявляет, что наличие или отсутствие пробела в пустой контекстной строке определяется реализацией (см. команду diff).

Исправьте регрессию, считая строки, состоящие исключительно из новой строки, а также строк, начинающихся с пробела в качестве строк контекста, и добавьте тест для предотвращения будущих регрессий.


Git 2.23 (Q3 2019) улучшает git add -p, используемый " git checkout -p ", который должен выборочно применять патч в обратном порядке: раньше он не работал git checkout -p.

См. Коммит 2bd69b9 (12 июня 2019 г.) Филиппа Вуда (phillipwood).
(Объединено Junio C Hamano - gitster - в коммите 1b074e1, 09 июля 2019 г.)

add -p: исправить checkout -p с патологическим контекстом

Фиксация fecc6f3 (" add -p: корректировать смещения последующих блоков, когда один из них пропущен", 2018-03-01, Git v2.17.0-rc0) исправила добавление блоков в правильном месте, когда предыдущий блок был пропущен.

Однако это не относится к патчам, которые применяются в обратном порядке.

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

Ответ 2

Это происходит для меня в любое время, когда я пытаюсь разбить кусок на более мелкие куски, которые слишком близко друг к другу (менее трех строк между изменениями). Краткое объяснение заключается в том, что в патче есть контекстные строки, которые конфликтуют с вашими локальными изменениями. Более полное объяснение ниже.


Предположим, что у меня есть репозиторий git с этими незафиксированными изменениями:

--- a/pangram
+++ b/pangram
@@ -1,8 +1,8 @@
 The
-quick
+relatively quick
 brown
 fox
-jumps
+walks
 over
 the
 lazy

Если я задержу первое изменение, я получаю:

--- a/pangram
+++ b/pangram
@@ -1,5 +1,5 @@
 The
-quick
+relatively quick
 brown
 fox
 jumps

Команде git stash действительно удается сохранить патч (проверьте git stash list), но затем git использует этот патч в обратном порядке, чтобы удалить спрятанные изменения из моего рабочего каталога. Контекст после того, как ханк имеет "прыжки", который не соответствует "прогулкам", все еще в моем рабочем директории. Таким образом, git с помощью

error: patch failed: pangram:1
error: pangram: patch does not apply
Cannot remove worktree changes

и оставляет все изменения в моей рабочей директории, и приставка становится практически бесполезной.


Я бы назвал это ошибкой в ​​поддержке git поддержки разбиения на куски. Если он знает, что он слишком сильно сменяет изменения, он может сбрить несколько строк контекста из патча, или jimmy патч, чтобы иметь измененные строки контекста вместо девственных. В качестве альтернативы, если расщеплять куски, это закрытие официально не поддерживается, оно должно фактически отказаться от разделения блоков, которые закрываются.

Ответ 3

После того, как при этом git stash -p завершится неудачно, мне повезло с этим обходным решением (git 2.0.2):

  • git add -p, разделяя те же самые куски, но с обратными ответами ( "y" до add "сохраняет" изменения, "n" - stash сохраняет изменения.)
  • git stash -k сохранить индекс и оставить все остальное
  • git reset продолжить работу над моими файлами

Я не уверен, почему git add -p не сработал так же, как это делал git stash -p. Я думаю, потому что добавление работает с индексом вместо создания файла патча?

Ответ 4

Принятый ответ на данный момент может, к сожалению, потерпеть неудачу, даже в Git 2.17.

Если, как и я, вы потратили много усилий на создание идеального тайника и не хотите отбрасывать это усилие, все равно возможно получить в основном то, что вы хотите:

git stash show -p | patch -p1 -R

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

Ответ 5

Применение состояния может привести к сбою с конфликтами; в этом случае он не удаляется из списка закладок. Вам необходимо разрешить конфликты вручную и вызывать git кавычки вручную вручную