Подтвердить что ты не робот

Проблемы с git reset - после добавления .gitattribute - локальные изменения, которых не должно быть

Я наблюдал проблемы CRLF после слияния пакетов от моего коллеги. Иногда линии с LF смешивались с источниками, вероятно, с теми, которые были объединены. Поэтому мы решили добавить файл .gitattributes со следующим содержимым (комментарии удалены):

*.cpp text
*.h text
*.inc text
*.cfg text
*.dic text

*.sln text eol=crlf
*.vcxproj text eol=crlf
*.filters text eol=crlf
*.user text eol=crlf
*.rc text eol=crlf
*.rc2 text eol=crlf

Теперь я наблюдаю странное поведение. Я вижу много файлов modified: ... (т.е. Нестационарных), которых не должно быть. Я пробовал git reset --hard, но файлы все еще имеют одинаковый статус. Я попытался снова клонировать репозиторий - тот же результат.

У меня есть git version 1.7.11.msysgit.0, установленный из Git-1.7.11-preview20120620.exe, загружаемый в качестве текущей версии для Windows.

Что еще я должен попробовать?

Спасибо, Petr

4b9b3361

Ответ 1

Причина

Это значение * text=auto в .gitattributes вызывает эту проблему. Вы можете удалить его и жить долго и счастливо, но у вас могут быть файлы с кодировками строк без репо, или даже файлы с несколькими различными окончаниями окончания строки (например, LF и CRLF, и даже CR!) В вашем репо.

Почему это происходит (подробнее)

Когда git проверяет файл как есть, на котором он будет изменять окончания строки при добавлении/фиксации. Файл на самом деле еще не изменен, но git уже считает его измененным, потому что он будет из-за настроек репо.

Как-то это работает немного странно с git. Например, git reset --hard иногда работает, а иногда и нет, возможно, в зависимости от ваших настроек. Или, если вы заходите в свой .gitattributes и отмечаете расширение как двоичное, измененный файл волшебным образом исчезает:

*.ext binary

Эффект сохраняется даже после удаления двоичной маркировки даже после повторного git reset --hard, поэтому это может быть проблема с кэшированием git или git. Выполнение git -rm в файле, а затем выполнение git reset --hard восстанавливает измененную маркировку.

Как исправить его

Предположим, что вы хотите сохранить свой параметр * text=auto, чтобы git предупреждал вас о непоследовательных концах строк в различных текстовых файлах сейчас и в будущем. Если да, выберите свой метод:

Вариант 0: временно отключить git от маркировки файлов как измененных

  • Изменить .gitattributes, закомментировать * text=auto, сохранить
  • git status (этот шаг необходим для изменения записи git в .gitattributes)
  • git reset --hard (это восстановит * text=auto, а также nuke любые изменения в вашем рабочем каталоге, если вы сделали какой-либо).

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

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

Вариант 1: простой "конечный пользователь" исправляет

Если у вас всего несколько файлов, убедитесь, что ваши .gitattributes и core.autocrlf настроены по своему вкусу, а затем просто сделайте git add/commit, и вы не должны снова видеть эту проблему. Файлы будут преобразованы в ваши окончательные строки и сохранены в вашем репо, как указано в вашей конфигурации. Эта фиксация будет сохранена в вашем репо, поскольку "весь файл был изменен", потому что каждая строка будет иметь свои окончания строк. Для нескольких файлов в более крупном репозитории с открытым исходным кодом это нормально. Не забудьте объединить или забрать вишню, которые фиксируются во всех ваших ветких, поскольку проблема будет существовать во всех ветвях, где были эти файлы, до тех пор, пока вы ее не исправите. Кстати, здесь вы можете использовать опцию 0. Т.е. если вы переключитесь на незафиксированную ветку, и она жалуется, запустите Option 0, затем выполните исправление (слияние или вишня).

ВАЖНО: если вы идете по этому маршруту Варианта 1, убедитесь, что вы правильно конвертировали измененные файлы. git, возможно, не сделает это для вас так, как вы ожидаете, сделайте это сами до совершения, т.е. используйте это: Преобразование форматирования новой строки с Mac на Windows. Причина git может быть запутана, так как я видел файлы, в которых есть все три CR, LF и CRLF. Перед тем, как совершить сделку, сделайте Nuke в своем предпочтительном формате.

Вариант 2: расширенная механика "git перезаписи истории" fix:

Если у вас есть более частное репо и вы не боитесь переписать историю, см. это: git видит весь файл как одну строку из-за окончания строки в Mac Это перепишет весь репо и избавится от любых проблем, связанных с окончанием строки в любом месте на всех деревьях, ветвях, навсегда! Обязательно включите все потенциальные неприятные расширения текстовых файлов, которые вы, возможно, захотите нормализовать, или они могут появиться позже.

В моем случае я сделал Вариант 2, поскольку я имел дело с множеством проблем с окончанием файла во многих ветких. Но потом у меня появилось несколько неожиданных расширений, которые я не нормализовал, и просто сделал вариант 1, так как я пропустил только 5-6 файлов.