Git add --interactive "Ваш отредактированный кусок не применяется"

Я пытаюсь использовать git add --interactive для выборочного добавления некоторых изменений в мой индекс, но я постоянно получаю сообщение "Ваш отредактированный hunk не применяется. Изменить снова...". Я получаю это сообщение, даже если я выбираю вариант e, и немедленно сохраняю/закрываю свой редактор. Другими словами, без редактирования куска вообще, патч не применяется.

Вот точный пример, который я использую (я пытаюсь собрать небольшую демонстрацию):

Исходный файл:

first change
second change off branch
third change off branch
second change
third change
fourth change

Новый файл:

Change supporting feature 1
first change
second change off branch
third change off branch
second change
third change
fourth change
bug fix 1
change supporting feature 1

Я пытаюсь показать, как использовать git add --interactive, чтобы добавить строку индекса "ошибка 1" в индекс. Запуск интерактивного добавления в файл, я выбираю режим патча. Он представляет мне

diff --git a/newfile b/newfile
index 6d501a3..8b81ae9 100644
--- a/newfile
+++ b/newfile
@@ -1,6 +1,9 @@
+Change supporting feature 1
 first change
 second change off branch
 third change off branch
 second change
 third change
 fourth change
+bug fix 1
+change supporting feature 1

Я отвечаю расколом, а затем "нет", чтобы применить первый кусок. Второй кусок, я пытаюсь отредактировать. Сначала я попытался удалить нижнюю строку - это не сработало. Оставляя один только кусок, тоже не работает, и я не могу понять, почему.

Ответ 1

Для этого конкретного примера вам нужно настроить номера строк в hunk. Измените строку:

@@ -1,6 +2,8 @@

чтобы вместо этого он читал:

@@ -2,7 +2,8 @@

Ответ 2

Это как в этом посте?

Ручное редактирование блока очень мощно, но также немного сложно, если вы никогда не делали этого раньше.
Самое важное, что нужно иметь в виду: разница всегда имеет один символ в дополнение к любому другому отступу.
Персонаж может быть:

  • пробел (указывает на неизмененную строку),
  • а - указывает, что линия была удалена,
  • или + указывающий, что строка была добавлена.

Ничего больше. Это должен быть пробел, - или +. Что-нибудь еще, и вы получите ошибки
(для измененной строки нет символа, поскольку они обрабатываются путем удаления старой строки и добавления измененной строки как новой).

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

И в этом заключается хитрость. Если вы никогда не делали этого раньше, Git скажет вам: "Ваш отредактированный кусок не применяется. Редактировать снова?" так часто вы начнете ненавидеть себя за неспособность понять это, даже если это кажется таким простым (или Git, потому что он не может понять, чего вы хотите).

Одна вещь, которая часто приводила меня в замешательство, заключалась в том, что я забыл один отступ персонажа.
Я бы пометил строку с -, чтобы удалить, но в большинстве текстовых редакторов, которые вставляют -, он не перезаписывает пространство, которое было там раньше. Это означает, что вы добавляете дополнительный пробел ко всей строке, что, в свою очередь, означает, что алгоритм diff не может найти/сопоставить строку в исходном файле, что, в свою очередь, означает, что Git будет кричать на вас.

Другое дело, что разница должна иметь смысл. "Смысл" означает, что его можно наносить аккуратно. Точно то, как вы создаете разумный дифференциал, кажется немного темным искусством (по крайней мере, для меня сейчас), но вы всегда должны помнить, как выглядел оригинальный файл, а затем планировать свои -s и +s соответственно. Если вы будете редактировать свои фрагменты достаточно часто, вы в конечном итоге освоите их.

Смотрите также этот коммит на git add -p.

Ortomala Lokni ответ относится к Хоакин Windmüller блоге " Избирательно выбрать изменения для совершения с мерзавцем (или Имма редактировать ломоть) "

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

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

Ответ 3

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

Эта конкретная проблема связана с расщеплением и попыткой редактирования одного и того же лома. Анализ, как первоначально написал Джефф Кинг, основной проблемой является:

Hm. Хорошо, я вижу. "Использует ли этот diff" контрольные каналы обеих частей разделить патч на git -apply. Но, конечно, вторая часть никогда не будет правильно применять, поскольку его контекст перекрывается с первой частью, но не принимает его во внимание.

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

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

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

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

Ответ 4

Если вы хотите не удалять строку, поставленную для удаления, как в

 first line
-second line
 third line

где вы хотите сохранить вторую строку, убедитесь, что вы заменили - пробелом, а не удаляете всю строку (как вы могли бы избавиться от добавленной строки). Git будет использовать строку для контекста.

Ответ 5

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

Трюк, который я использовал, состоял в том, что если у меня есть diff, как это.

+ Line to add
+ Line to add
+ Line I dont want to include
+ Line I dont want to include

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

+ Line to add
+ Line to add

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

Ответ 6

Также важно правильно изменить заголовок @@-1,6 +1,9 @@ (например, @@-1,6 +1,9 @@). Хоакин Виндмюллер раскрывает секрет редактирования заголовка куска в одном из своих постов в блоге.

Секреты редактирования гунков

Поначалу редактирование фрагментов может сбивать с толку, инструкции, которые git дает вам помощь, но их недостаточно для начала работы.

# —||

# To remove ‘- lines, make them   lines (context).

# To remove ‘+ lines, delete them.

# Lines starting with # will be removed.

#

# If the patch applies cleanly, the edited hunk will immediately be

# marked for staging. If it does not apply cleanly, you will be given

# an opportunity to edit again. If all lines of the hunk are removed,

# then the edit is aborted and the hunk is left unchanged.

Секретный соус это... подсчет строк:

  • Если вы удалите строку, которая начинается с +, то вычтите одну из них на счетчик новой строки (последняя цифра заголовка фрагмента).
  • Если вы удалите строку, начинающуюся с -, то добавьте ее к новому количеству строк (последняя цифра заголовка фрагментов).
  • Не удаляйте другие строки (опорные линии).

Это должно позволить вам быстро изменить фрагменты, чтобы выбрать части, которые вы хотите.

Ответ 7

Я пришел к этому вопросу в поисках решения той же проблемы и не мог понять, как изменить номера строк (как предложено выше) в блоке, чтобы git принял его в моем случае. Я нашел гораздо лучший способ сделать это, используя git gui. Там вы можете выбрать строки в diff, которые хотите поставить, затем щелкните правой кнопкой мыши и выберите "Stage lines from commit". Я помню, что у git-cola такая же функциональность.

Ответ 8

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

Если вы видите, что вам, вероятно, придется немного что-то редактировать в hunk, который автоматически выбирается Git, лучше всего просто отредактировать весь ханк, а не раскалывать, составлять половину, а затем редактировать другую половину. Git будет лучше справляться с этим.

Ответ 9

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

Я использовал Windows и использовал "Блокнот" для моих изменений (только сохраняет с линейными окончаниями Windows). Мой код был написан с помощью Notepad ++, и я настроил его на окончание строк стиля Unix/Linux.

Когда я изменил свои настройки, чтобы иметь Notepad ++ в качестве редактора по умолчанию git, я смог внести свои изменения в hunk.

git config --global core.editor "notepad++"

Ответ 10

Одной из причин странных сообщений "Ваш отредактированный ханк не применяется" (вероятно, сопровождаемых чем-то вроде "ошибка: фрагмент патча без заголовка в строке...") может быть ваш редактор, если он настроен на удаление конечных пробелов. Это, очевидно, приведет к серьезным проблемам, так как патчи кодируют пустые строки, так как строки с одним пробелом не могут быть применены любым блоком, содержащим пустые строки, если они сохранены в таком редакторе. Таким образом, фактически любой блок, содержащий любые неизмененные пустые строки, не сможет быть применен после редактирования, если включен конечный пробел для удаления.

Ответ 11

К вашему сведению, я получаю слегка взаимосвязанную ошибку... когда я добавляю заплатку, следуя предложенной выше инструкции... Однако она не показала ошибки. Я получал его несколько раз с просьбой поставить тот же кусок... Я заметил, что у меня установлена более старая версия Vim 7.4... Я обновил vim, и теперь он работает, как и ожидалось. Надеюсь, это поможет кому-то..