Во многих случаях, когда у двух файлов «одинаковое содержимое», а diff выдаёт кучу различий, виноваты пробелы: редактор удалил пробелы в конце строк, заменил табуляции пробелами или изменил ширину отступа. У инструментов diff есть опции, чтобы игнорировать такие различия, но каждая игнорирует разное, и пользоваться ими нужно осознанно.
Опции GNU diff, связанные с пробелами
| Опция | Длинное имя | Что игнорируется |
|---|---|---|
-Z | --ignore-trailing-space | Пробелы в конце строки |
-E | --ignore-tab-expansion | Различия из-за замены табуляции пробелами |
-b | --ignore-space-change | Изменение количества пробелов, пробелы в конце строки |
-w | --ignore-all-space | Все пробелы |
-B | --ignore-blank-lines | Изменения, где добавлены или удалены только пустые строки |
-i | --ignore-case | Регистр букв |
--strip-trailing-cr | Символ CR в конце входных строк |
Соответствующие опции git diff
Документация git описывает их так.
--ignore-cr-at-eol: при сравнении игнорирует возврат каретки (CR) в конце строки.--ignore-space-at-eol: игнорирует изменения пробелов в конце строки.-b,--ignore-space-change: игнорирует изменения количества пробелов. Пробелы в конце строки игнорируются, а все прочие последовательности из одного и более пробелов считаются одинаковыми.-w,--ignore-all-space: игнорирует пробелы при сравнении строк. Игнорируются даже различия, когда в одной строке пробел есть, а в другой его нет.--ignore-blank-lines: игнорирует изменения, все строки которых пустые.
Решающее различие между -b и -w
Эти две опции часто путают. Суть в том, различается ли, есть пробел или нет.
| Слева | Справа | -b (количество пробелов) | -w (все пробелы) |
|---|---|---|---|
a b | a b | Одинаково | Одинаково |
a b | ab | Различно | Одинаково |
x = 1 | x=1 | Различно | Одинаково |
if (a) + пробел в конце | if (a) | Одинаково | Одинаково |
| Отступ из 1 табуляции | Отступ из 4 пробелов | Одинаково | Одинаково |
-b сжимает каждую группу пробелов до одного, а -w удаляет пробелы полностью. Поэтому -w считает одинаковыми x = 1 и x=1 и даже int a и inta.
Опасность для файлов со значимыми отступами
В файлах, где отступы — часть синтаксиса (Python, YAML, Makefile), опции игнорирования пробелов могут скрыть реальное изменение.
if ready:
start()
notify()
if ready:
start()
notify()
Во втором варианте notify() вышел за пределы блока if и поведение изменилось, но при сравнении с -w пробелы удаляются целиком, и различие пропадает. -b это различие заметит, потому что пробелы в начале строки из «есть» превратились в «нет». Однако если отступ вырос с 4 до 8 пробелов и код ушёл во вложенный блок, изменилось лишь количество пробелов, и -b тоже ничего не покажет.
Надёжный способ — сравнивать файлы со значимыми отступами без опций пробелов. Используйте опции пробелов, чтобы проверить, что изменение было только «косметическим», а окончательную проверку делайте без них — это безопасная привычка.
Что охватывает игнорирование пустых строк (-B)
-B и --ignore-blank-lines в git скрывают изменения, состоящие только из пустых строк. Если добавленная пустая строка оказалась в одном блоке с реальным изменением, она может всё равно отображаться. Опция полезна, когда в документе изменили число пустых строк между абзацами или форматировщик кода поправил пустые строки между функциями.
Опции этого сайта и их соответствие
| Этот сайт | Ближайшее в GNU diff | Ближайшее в git diff |
|---|---|---|
| Пробелы: сравнивать как есть | (без опций) | (без опций) |
| Пробелы: игнорировать пробелы в конце строк | -Z | --ignore-space-at-eol |
| Пробелы: игнорировать количество пробелов | -b | -b |
| Пробелы: игнорировать все пробелы | -w | -w |
| Без учёта регистра | -i | (нет аналога) |
| Игнорировать пустые строки | Похоже на -B (пустые строки исключаются из сравнения) | Похоже на --ignore-blank-lines |
| Нормализовать концы строк | --strip-trailing-cr + игнорирование последнего перевода строки | Похоже на --ignore-cr-at-eol |
«Игнорировать пустые строки» на этом сайте полностью исключает пустые строки из сравнения и лишь показывает их бледным цветом. Кроме того, опции игнорирования действуют и на подсветку внутри строк: при игнорировании количества пробелов места, где отличается только число пробелов, не выделяются.
Попробуйте в этом инструменте
Вставьте примеры из таблицы в сравнение текстов и по очереди меняйте опции пробелов — разница будет видна сразу. О «невидимых различиях» вроде CR в конце строки и перевода строки в конце файла рассказано в статье Концы строк и невидимые различия, а о чтении результата в виде patch — в статье Как читать unified diff.