# git diff _Ежедневная работа · GitLab Knowledge Base_ **TL;DR:** Показывает различия между двумя версиями. Четыре основных режима: без флагов (working tree vs index), `--staged` (index vs HEAD), `HEAD` (working tree vs HEAD), ` ` (commit vs commit). Плюс опции для фильтрации, форматов и сравнения веток. `git diff` - самая часто используемая команда расследования. Знаешь четыре её режима - и понимаешь, в какой зоне Git что. ## Четыре основных режима ```bash git diff # working tree vs index (что не застейджил) git diff --staged # index vs HEAD (что войдёт в следующий коммит) git diff HEAD # working tree vs HEAD (сумма обоих) git diff # коммит A vs коммит B ``` Это четыре зоны Git и пары между ними (см. главу 5 книги). ## Частые сценарии ```bash # Что я ещё не застейджил git diff # Что войдёт в следующий коммит git diff --staged # синоним: git diff --cached # Всё, что отличается от последнего коммита git diff HEAD # Что изменилось между релизами git diff v1.0 v1.1 git diff v1.0..v1.1 # эквивалентно # Только в каталоге git diff -- src/auth/ git diff HEAD -- "**/*.py" # Между двумя ветками git diff main feature # all differences between tips git diff main...feature # only what feature added relative to merge-base ``` Разница между `git diff A B` и `git diff A...B` тонкая: - **`A B`** - diff между *вершинами*. «Если приложить B к A - какие изменения». - **`A...B`** - diff от *общего предка* до B. «Что добавил B, игнорируя параллельные изменения в A». Для code review удобнее `A...B`: чистая картина «что сделала feature», без шума из main. ## Полезные опции ```bash git diff --stat # сводка: файлы и числа строк git diff --shortstat # одна итоговая строка git diff --name-only # только список изменённых файлов git diff --name-status # список + статус (A/M/D/R) git diff -w # игнорировать whitespace git diff --word-diff # диф по словам, не по строкам git diff --word-diff=color # с цветным выделением git diff -M # детект переименований (rename) git diff -C # детект копирований (copy) git diff -B # break-rewrite: расщепить # сильно изменённый файл на delete+add git diff --find-renames=50% # порог похожести для переименования git diff -p # full patch (по умолчанию) git diff -U10 # 10 строк контекста (по умолчанию 3) git diff -U0 # без контекста, только сами правки ``` ## Pickaxe и поиск по содержимому Не совсем `git diff`, но рядом - `git log -S` и `-G`: ```bash git log -S "magicConstant" --oneline # коммиты, изменившие # количество вхождений строки git log -G "TODO\(.*\)" --oneline # коммиты с diff'ом, матчащим regex ``` См. [log](/courses/git/kb/log.md). ## Сравнение между файлами без репозитория ```bash git diff --no-index a.txt b.txt ``` Полезно как универсальный diff с цветами и фильтрами, даже когда файлы не в Git. ## Подводные камни - **`git diff` без аргументов не показывает застейдженное.** Если кажется, что нет изменений, а ты что-то стейджил - `git diff --staged`. - **Бинарные файлы** показываются как `Binary files differ`. Чтобы увидеть имена - `--stat` или `--name-only`. Чтобы заставить показать как текст - `--text`. - **Файлы с другой кодировкой** (windows-1251, и т.п.) могут отображаться кракозябрами. Решение - `.gitattributes` с `diff=cp1251` (для русских файлов) или конвертация при diff'е. - **Длинные строки** в JSON / minified JS показываются одной строкой - нечитаемо. `--word-diff` иногда помогает. - **Diff большого файла** медленный. `--stat` быстрее всех. ## Команды ```bash git diff ``` Различия working tree и индекса (что не застейджено) ```bash git diff --staged ``` Различия индекса и HEAD (что войдёт в следующий коммит) ```bash git diff HEAD ``` Все правки от HEAD, и застейдженные и нет ```bash git diff main...feature ``` Что добавила feature относительно общего предка с main ## См. также - [git log](/courses/git/kb/log.md) - [git status](/courses/git/kb/status.md) - [git commit](/courses/git/kb/commit-cmd.md)