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

85

Я пытаюсь использовать его git add --interactiveдля выборочного добавления некоторых изменений в свой индекс, но постоянно получаю сообщение «Ваш отредактированный фрагмент не применяется. Отредактируйте снова ...». Я получаю это сообщение, даже если выберу опцию 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

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

Джош
источник
Здесь следует убедиться, что вы не добавляете -символы в начале строк, которых нет в файле; это разница, и он не может удалять строки, которых еще нет. Итак, если строка в diff начинается с, +а вы измените ее на -git, идет WTF? потому что теперь строка, отмеченная для удаления, не существует с самого начала (вместо этого эта строка была отмечена для добавления, и когда строка, отмеченная для добавления, отмечена для удаления, git не может удалить строку, которой еще нет в файле) .
leeand00 05
1
Проверьте также окончания строк (LF, CRLF), в моем случае он не применялся для одного LF вместо CRLF!
Альберто Ривелли

Ответы:

37

В этом конкретном примере вам нужно настроить номера строк в блоке. Измените строку:

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

так что вместо этого читается:

@@ -2,7 +2,8 @@
Уильям Перселл
источник
16
Покопавшись, я обнаружил, что эти строки показывают «диапазон от файла» и «диапазон до файла». Я действительно не понимаю логики изменения 1 на 2. Я попробовал, и он работает, но я не понимаю, почему изменяется "диапазон от файла". Исходный файл остается неизменным, применяю ли я весь патч или только отредактированный кусок. Не могли бы вы уточнить или указать мне ссылку на унифицированный формат diff. Мне не удалось его найти.
Джош
9
@Josh: stackoverflow.com/questions/2529441/… может помочь, даже если я не получаю полностью блоки единого формата. @William +1
VonC
5
@Josh: Если посмотреть на это, похоже, что это ошибка. После редактирования фрагмента git пытается проверить патч, проверяя, что все фрагменты будут применяться (это может быть чрезмерным). К сожалению, в этом случае это означает, что предыдущий кусок (который вы не применяете) проверяется, и есть некоторое перекрытие, которое приводит к сбою git apply --check. Я не знаю элегантного решения; Возможно, git поступает правильно, будучи здесь излишне осторожным.
Уильям Перселл,
22
Подробнее об изменении номеров строк, пожалуйста? Почему мы должны это делать? И как? Что означает каждое число?
Bill
4
@WilliamPursell какие версии git? Я переключился на новый компьютер и запустил git v2.17.0, и внезапно мои исправления в патчах больше не действуют.
Деннис
105

Это как в этом сообщении git-add ?

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

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

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

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

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

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

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

См. Также этот коммит в git add -p .

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

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

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

VonC
источник
5
Спасибо за ссылку, но я это уже видел. Я не добавлял / не оставлял дополнительную строку. Проблема была в номерах строк, но я все еще не понимаю, как исправить.
Джош
9
Я не заменял удаленное '-' пробелом - таким образом, испортил отступ. Спасибо!!
pedorro
Просто убедитесь, что вы правильно поняли пустое пространство. Я думал, что все неизмененные строки должны быть просто черными строками, а не просто символом отступа ... Был час «отредактированный кусок не применяется», пока я не понял почему: - /
oligofren
@oligofren Я не уверен, что понимаю вас: что вы должны были сделать, чтобы ваш отредактированный кусок стал применим?
VonC
1
@VonC: Сначала я подумал, что нужно заменить - foo на «(просто пустое место, а не« пустое место и вся строка »). Мне потребовалось время, чтобы понять, что это должен был быть `foo`.
oligofren
48

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

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

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

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

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

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

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

Нильс Гансер
источник
6
Спасибо, это действительно намного проще, чем возиться с номерами строк.
michiakig
3
Это была моя проблема. Мне нужно, чтобы мой кусок был меньше. Сделал сплит в интерактиве. Разделение было не тем, что я хотел, поэтому я решил попробовать отредактировать вручную. Продолжал получать ошибку. Начал сначала, сработал с первого раза.
Kyle s
Это лучший ответ в этой теме. Не разделяйте и не редактируйте. Просто отредактируйте.
Dr_Zaszuś
В моем случае дополнительная проблема возникла из-за окончаний строк Windows, показанных как ^Mв файле diff. Как только я сохранил файл с окончаниями CR, патч интерактивного редактирования прошел!
Dr_Zaszuś
Спасибо, это помогло мне. Мне пришлось поработать над огромным куском, поэтому я разделил его, и все сломалось. Если он не разделен, все работает нормально.
Маттиас Фишер
16

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

 first line
-second line
 third line

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

Роза Перроне
источник
1
Мне это было непонятно, я думал, что Git велел мне сделать строку одним пробелом.
JackHasaKeyboard
15

Также важно правильно изменить заголовок ханка (например @@ -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.

Секретный соус ... счетные строки:

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

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

Ортомала Локни
источник
1
Есть ли способ автоматизировать редактирование заголовка лома или настроить git для определения соответствующего количества строк?
Деннис
Вы, вероятно, можете написать сценарий своего любимого редактора, чтобы автоматизировать это. Возможно, для этого уже есть плагины, но это зависит от редактора.
Ортомала Локни
14

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

Уловка, которую я использовал, заключалась в том, что если у меня есть разница вроде:

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

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

+ Line to add
+ Line to add

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

Седрик
источник
2
Я не могу тебя отблагодарить! Я пытался поменять +на ' 'как минимум час.
soumer
Знаете, безумие - это то же самое и ожидание другого результата. Я говорил себе это 20 минут, прежде чем понял, что мне просто нужно удалить :)
solidak 03
Это должен быть ответ. Красиво и просто, спасибо!
xPeaWhyTee
7

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

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

Майкл Хайнс
источник
6

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

Джайеш
источник
Это действительно должно быть ответом. git-colaпохоже, работает в Linux, Windows и MacOS.
leeand00
5

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

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

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

git config --global core.editor "notepad++"
KLee1
источник
1
Это сработало для меня. Но мне нужен был полный путь к notepad ++, и на это потребовалось время: git config --global core.editor '"C:/Program\ Files\ \(x86\)/Notepad++/notepad++.exe"' (адаптируйте его в соответствии с тем, где на вашем компьютере установлен notepad ++)
Annabel
1
Точно такая же проблема для меня. Это был Блокнот, который вызывал проблемы. Как только я переключил свой редактор по умолчанию на Notepad ++, все снова заработало.
Johnny Oshika 01
4

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

Тимо
источник
0

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

Mantisimo
источник