git diff --check показывает изменения не связанных веток / файлов

Фон

Я пытаюсь увидеть пробельные ошибки текущей ветви (игнорируя CR на eol). Большинство файлов используют CRLF, и у меня нет установленного конфигурации core.whitespace.

Это оригинальная команда:

git -c core.whitespace=trailing-space,cr-at-eol diff --check master..HEAD

HEAD относится к ветви, созданной поверх старой версии master (" oldmaster ").

Проблема в том, что git diff --check ведет себя неожиданным образом: он показывает не только ошибки в master..HEAD, но и ошибки в oldmaster..master.

Вопросы

  • Это происходит потому, что git diff --check сравнивает целые снимки в заданном диапазоне ревизий?

  • Почему git log а также git diff вести себя по-другому в этом случае?

  • не должны git diff --check сравнить только измененные строки в измененных файлах?

Информация

мастер против старого мастера (числа совпадают):

$ git log --oneline oldmaster..master | wc -l
115

$ git diff --name-only oldmaster..master | wc -l
115

Это показывает соответствующие коммиты правильно:

$ git log --oneline master..HEAD | wc -l
4

Это показывает правильные файлы:

$ git log --oneline --name-only master..HEAD -- | grep -E '^[a-zA-Z]+/' \
  | sort -u | wc -l
4

К ним, по некоторым причинам, также относятся файлы, измененные в oldmaster..master:

$ git diff --name-only master..HEAD -- | wc -l
119

$ git -c core.whitespace=trailing-space,cr-at-eol diff --name-only \
  master..HEAD -- | wc -l
119

Оба из них также показывают несвязанные файлы:

$ git diff --check master..HEAD -- | grep -E '^[a-zA-Z]+/' | cut -d : -f 1 \
  | sort -u | wc -l
30

$ git -c core.whitespace=trailing-space,cr-at-eol diff --check master..HEAD \
  -- | grep -E '^[a-zA-Z]+/' | cut -d : -f 1 | sort -u | wc -l
9

1 ответ

Решение

За исключением комбинированных различий (которые вы здесь не используете), git diff строго сравнивает два снимка.1 Используемый синтаксисgit diff A B против git diff A..B- здесь неактуально. Git извлекает снимок A, извлекает снимок B и сравнивает эти два снимка. Любые параметры флага, которые вы используете, такие как --check, применяются к этому конкретному сравнению. совершить A не должен быть предком Bни наоборот; Git не смотрит ни на один из коммитов "между" этими двумя коммитами; это просто извлекает Aзатем извлекает Bи отличает тех.2

git log Команда делает что-то совсем другое: она просматривает граф ревизий. Дано git log A..BGit находит все коммиты, доступные из B которые недоступны из A, Для ясного определения достижимости см. Think Like (a) Git.

Обратите внимание, что при использовании -p с git log просматривать коммиты как патчи, git log сравнивает каждый коммит с его (единственным) родителем. Если в A..B диапазон, например, git log -p A..B первые шоу B и работает git diff B^ Bзатем показывает B^ и работает git diff B^^ B^и последние шоу B^^ и работает git diff B^^^ B^^, (Предполагается, что в диапазоне нет коммитов слияния, но git log в любом случае по умолчанию пропускает патчи для фиксации слияния.)


1 Чтобы увидеть комбинированный дифференциал, используйте git show на коммит слияния. git diff Команда также будет создавать комбинированные различия с некоторыми конкретными аргументами, иногда неправильно: в частности, синтаксис с тремя точками, git diff A...B, предназначен для сравнения базы слияния A а также B совершать B, но иногда делает что-то другое. Кроме того, когда вы используете индекс и индекс содержит конфликтующее слияние, обычный git diff будет производить комбинированные различия.

2 Технически ему даже не нужно извлекать два снимка - он просто работает непосредственно с их древовидных объектов. Он должен извлечь различные капли, чтобы вычислить разницу. Для идентичных сгустков, git diff знает, что они идентичны, потому что их хэш-идентификаторы совпадают. Но об этом проще рассуждать как "извлекать и сравнивать".

Другие вопросы по тегам