Перейти к содержимому

git diff

Описание

Команда git diff используется для сравнения изменений между коммитами, рабочей директорией и областью индексации (staging area). Она принимает два набора входных данных и выводит различия между ними. Обычно она используется в сочетании с командами git status и git log для анализа состояния git-репозитория.

gitdiff

Вывод diff

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

Формат сырого вывода

Посмотрите на команды ниже для создания простого репозитория:

git diff

bash
mkdir test_repo
cd test_repo
touch test.txt
echo "this is a git diff test example" > test.txt
git init .
#Initialized empty Git repository in /Users/kev/code/test/.git/
git add test.txt
git commit -am "add diff test file"
#[master (root-commit) 9e2dcac] add diff test file
#1 file changed, 1 insertion(+)
#create mode 100644 test.txt

Чтобы git diff вывел результат, необходимо изменить содержимое файла test.txt после добавления его в созданный репозиторий. Это можно сделать, выполнив следующую команду:

git diff

bash
echo "this is a diff example" > test.txt

Только теперь мы можем просмотреть diff и обсудить вывод. Выполнение git diff даст следующий результат:

git diff

bash
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Источники ввода для diff

Ниже показано входное сравнение для diff. В результате a/test.txt и b/test.txt будут переданы в diff.

git diff

bash
diff --git a/test.txt b/test.txt

Метаданные

Эта строка показывает некоторые внутренние метаданные Git. Числа в этом выводе соответствуют идентификаторам хешей версий объектов Git.

git diff

bash
index 6b0c6cf..b37e70a 100644

Символы изменений

Эти строки показывают символы, назначенные каждому источнику ввода diff. Изменения из a/test.txt отмечены знаком ---, а изменения из b/test.txt отмечены знаком +++.

git diff

bash
--- a/test.txt
+++ b/test.txt

Чанки diff

Diff не показывает весь файл целиком. Он отображает только изменённые строки. Эта изменённая часть называется «чанком» (chunk). Преимущество чанков в том, что они показывают строки до и после изменений, что позволяет лучше понять контекст модификаций.

git diff

bash
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Первая строка — это заголовок чанка. Каждый чанк начинается с заголовка, заключённого в символы @@. Изменения, внесённые в файл, суммируются в этом заголовке.

Распространённые флаги

Git предоставляет несколько полезных флагов для различных рабочих процессов:

  • --staged (или --cached): Сравнивает изменения в индексе с коммитом HEAD.
  • --stat: Показывает сжатое сводное представление изменённых файлов вместо полного diff.
  • --name-only: Выводит только имена изменённых файлов.

Подсветка изменений

Для подсветки изменений, чтобы они были более заметными, можно использовать следующие 2 инструмента.

git diff --color-words

Первый способ подсветки изменений — это специальный режим, предлагаемый git diff: --color-words. Он разбивает добавленные и удалённые строки на токены по пробельным символам, а затем сравнивает их.

git diff

bash
git diff --color-words
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

(Примечание: --color-words подсвечивает встроенные изменения с помощью цветов терминала. В обычном текстовом формате вывод соответствует стандартному diff.)

git diff-highlight

При клонировании исходного кода Git будет найдена поддиректория с именем contrib. Эта поддиректория содержит инструменты, связанные с Git. Один из этих инструментов называется diff-highlight. Он подсвечивает изменённые части слов. Обратите внимание, что этот инструмент фильтрует стандартный ввод и требует включения цветов в терминале для отображения.

git diff

bash
git diff | git diff-highlight
diff --git a/test.txt b/test.txt
index 6b0c6cf..b37e70a 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Сравнение бинарных файлов

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

git diff

bash
git diff
Binary files a/script.pdf and b/script.pdf differ

В Git есть функция, позволяющая указать команду оболочки для преобразования содержимого бинарных файлов в текст перед выполнением diff. Однако может потребоваться небольшая настройка. Прежде всего, вам следует определить фильтр textconv с описанием способа преобразования определённого типа бинарных файлов в текст. Например, вы можете использовать простую утилиту pdftohtml (доступную через Homebrew) для преобразования PDF в HTML. Есть два способа настройки: путём редактирования файла .git/config или глобально, путём редактирования .gitconfig.

git diff

bash
[diff "pdfconv"]
textconv=pdftohtml -stdout

Затем вам нужно связать один или несколько шаблонов файлов с фильтром pdfconv, что можно сделать, создав файл .gitattributes в корне репозитория.

git diff

bash
*.pdf diff=pdfconv

После настройки git diff сначала запустит бинарный файл через настроенный скрипт конвертера и выполнит diff вывода конвертера. Используя тот же подход, вы также можете получать полезные diff для всех типов бинарных файлов (zip, jar и других архивов).

Сравнение файлов: git diff file

Команда git diff также имеет явную опцию указания пути к файлу. Операция git diff обработает конкретный файл, как только ему будет передан путь к файлу. В примере ниже аргумент ./path/to/file сравнит изменения в рабочей директории с коммитом HEAD.

git diff

bash
git diff HEAD ./path/to/file

Сравнение всех изменений

Чтобы сравнить изменения во всём репозитории, следует запустить git diff без указания пути к файлу. Таким образом, вы можете вызвать примеры выше без аргумента ./path/to/file и получить одинаковые результаты для всех файлов в локальном репозитории.

Изменения с последнего коммита

По умолчанию git diff сравнивает рабочую директорию с областью индексации (индексом). Чтобы увидеть все неизменённые изменения с момента последнего коммита:

git diff

bash
git diff

Сравнение файлов между двумя коммитами

Команде git diff можно передать ссылки Git (refs), такие как имена хвостов (heads), тегов и веток. Каждый коммит в Git имеет уникальный идентификатор, который можно найти, выполнив git log. Вы также можете передать два идентификатора коммитов для их прямого сравнения:

git diff

bash
git diff <commit-hash-1> <commit-hash-2>

Сравнение веток

Сравнение веток выполняется аналогично другим ссылкам (refs), передаваемым в git diff. Давайте рассмотрим примеры с оператором точек:

git diff

bash
git diff branch1..branch2

Две точки в примере выше показывают, что входными данными для diff являются концы (tips) обеих веток. Вы получите тот же результат, если опустить точки и использовать пробел между ветками. Кроме того, существует оператор с тремя точками:

git diff

bash
git diff branch1...branch2

Оператор с тремя точками изменяет первый входной параметр branch1, инициирующий diff. Он преобразует branch1 в ссылку на общий коммит-предок для двух входных данных diff. Последний входной параметр остаётся таким же, как конец ветки branch2.

Сравнение файлов из двух веток

Чтобы сравнить конкретный файл в ветках, следует передать путь к файлу в качестве третьего аргумента для git diff:

git diff

bash
git diff master new_branch ./test.txt

Практика

Какие функциональные возможности и опции есть у команды 'git diff'?

Считаете ли это полезным?

Предпросмотр dual-run — сравните с маршрутами Symfony на продакшене.