ДокументацияGitПродвинутые команды Git
Продвинутый 11 мин чтения

Продвинутые команды Git

git bisect для поиска сломанного коммита, git blame для определения автора строки, git cherry-pick для переноса отдельных коммитов, git stash, git reflog и другие полезные команды.

gitbisectblamecherry-pickstashreflogadvanced

git bisect — поиск сломанного коммита

Баг появился, но непонятно когда и из-за какого коммита. git bisect находит его бинарным поиском: вы отмечаете «хороший» и «плохой» коммит, а Git делит историю пополам, пока не найдёт виновника.

Интерактивный bisect

# Начать поиск
git bisect start

# Указать текущий (плохой) коммит
git bisect bad

# Указать коммит, где всё работало
git bisect good v2.3.0
# или по хешу
git bisect good abc1234

Git переключится на середину между хорошим и плохим коммитом:

Bisecting: 50 revisions left to test after this (roughly 6 steps)
[def5678] some commit message

Вы проверяете — баг есть или нет:

# Баг всё ещё есть — помечаем как плохой
git bisect bad

# Бага нет — помечаем как хороший
git bisect good

Git сужает диапазон и переключается на следующий коммит. Через несколько шагов:

def5678 is the first bad commit

Автоматический bisect

Можно автоматизировать проверку — Git сам запустит скрипт и найдёт виновника:

# Скрипт возвращает 0 — хорошо, 1-124 — плохо, 125 — пропустить
git bisect start HEAD v2.3.0
git bisect run npm test
# Скрипт проверки: запускает тест и проверяет результат
git bisect run sh -c 'npm run test:specific || exit 1'
# Скрипт: проверяет, что сборка успешна
git bisect run sh -c 'npm run build && exit 0 || exit 1'

Завершение bisect

# После завершения — вернуться к исходному состоянию
git bisect reset

Важно: bisect.detached HEAD — вы находитесь не на ветке. После reset вернётесь обратно.

git blame — кто написал эту строку

git blame показывает, кто и когда изменил каждую строку файла:

# Полная информация по файлу
git blame src/app/auth.service.ts

Вывод:

a1b2c3d4 (Иван Иванов  2024-03-15 10:30:22  1) import { Injectable } from '@angular/core'
e5f6g7h8 (Анна Петрова  2024-03-16 14:20:05  2) import { HttpClient } from '@angular/common/http'
a1b2c3d4 (Иван Иванов  2024-03-15 10:30:22  3)
a1b2c3d4 (Иван Иванов  2024-03-15 10:30:22  4) @Injectable({ providedIn: 'root' })

Полезные флаги

# Только определённые строки
git blame -L 10,30 src/app/auth.service.ts

# Диапазон от строки 10 до конца
git blame -L 10, src/app/auth.service.ts

# По регулярному выражению (от функции до конца)
git blame -L :login src/app/auth.service.ts

# Показать email вместо имени
git blame -e src/app/auth.service.ts

# Игнорировать переносы строк (показать последний значимый коммит)
git blame -w src/app/auth.service.ts

blame конкретного коммита

# Как выглядел blame в конкретном коммите
git blame abc1234 -- src/app/auth.service.ts

В IDE

VS Code: выделите строки → правый клик → «Open Blame» или установите расширение GitLens — оно показывает автора каждой строки прямо в редакторе.

git cherry-pick — перенос отдельных коммитов

cherry-pick переносит конкретный коммит из одной ветки в другую, не сливая всю ветку:

main:     A---B---C---D
                   \
feature:            E---F---G

Нужен только коммит F в main:

git checkout main
git cherry-pick f1a2b3c   # Хеш коммита F
main:     A---B---C---D---F'

F' — копия коммита F с новым хешем.

Типичные сценарии

# Перенести hotfix из feature-ветки в main
git checkout main
git cherry-pick abc1234

# Перенести несколько коммитов
git cherry-pick abc1234 def5678 ghi9012

# Диапазон коммитов (включительно)
git cherry-pick abc1234^..def5678

Разрешение конфликтов при cherry-pick

git cherry-pick abc1234
# CONFLICT в src/app/auth.service.ts

# Разрешить конфликт вручную
# Затем:
git add src/app/auth.service.ts
git cherry-pick --continue

# Или отменить cherry-pick
git cherry-pick --abort

git stash — временное хранение изменений

Вы работаете над фичей, но срочно нужно переключиться на другую ветку. Коммитить незаконченную работу не хочется. stash сохраняет текущие изменения и прячет их:

# Сохранить все изменения (staged + unstaged)
git stash

# С сообщением
git stash push -m "WIP: авторизация через Google"

# Сохранить только определенные файлы
git stash push -m "частично" src/app/auth.service.ts

# Сохранить включая untracked файлы
git stash -u

# Сохранить всё, включая игнорируемые файлы
git stash -a

После stash рабочая директория чистая — можно переключаться на другую ветку.

Восстановление

# Посмотреть список stash
git stash list
# stash@{0}: On feature/auth: WIP: авторизация через Google
# stash@{1}: On main: экспериментальный фикс

# Восстановить последний stash (и удалить из списка)
git stash pop

# Восстановить конкретный stash
git stash pop stash@{1}

# Восстановить, но оставить в списке
git stash apply stash@{0}

Управление stash

# Посмотреть содержимое stash
git stash show -p stash@{0}

# Создать ветку из stash
git stash branch fix-from-stash stash@{0}

# Удалить конкретный stash
git stash drop stash@{1}

# Удалить все stash
git stash clear

git reflog — история всех действий

reflog — лог всех перемещений HEAD. Даже если вы потеряли коммит после reset или rebase, reflog поможет его найти:

git reflog
a1b2c3d HEAD@{0}: checkout: moving from feature to main
e5f6g7h HEAD@{1}: commit: feat: add search
i8j9k0l HEAD@{2}: commit: fix: resolve null pointer
m1n2o3p HEAD@{3}: rebase: checkout main
q4r5s6t HEAD@{4}: reset: moving to HEAD~2

Восстановление «потерянных» коммитов

# Вы случайно сделали git reset --hard HEAD~3
# Коммиты «пропали», но reflog помнит:

git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# x7y8z9w HEAD@{1}: commit: important feature  ← это нужно!

# Вернуться к потерянному коммиту
git checkout x7y8z9w
# или создать ветку
git branch recovered x7y8z9w
# Удалить reflog (старые записи удаляются через 90 дней автоматически)
git reflog expire --expire=30.days.ago --all

git clean — удаление неотслеживаемых файлов

# Посмотреть, какие файлы будут удалены (dry run)
git clean -n

# Удалить untracked файлы
git clean -f

# Удалить untracked файлы и папки
git clean -fd

# Удалить включая ignored файлы (node_modules, dist и т.д.)
git clean -fdx

# Ядерная очистка — полный возврат к чистому состоянию
git reset --hard
git clean -fdx

Полезные комбинации

Отменить последний коммит (сохранив изменения)

git reset --soft HEAD~1

Изменения вернутся в staging area. Коммит исчезнет из истории.

Изменить последний коммит

# Добавить забытый файл
git add forgotten-file.ts
git commit --amend --no-edit

# Изменить сообщение
git commit --amend -m "fix: correct login redirect"

Перенести коммит в другую ветку

# Коммит abc1234 был сделан не в той ветке
git checkout feature/correct-branch
git cherry-pick abc1234
git checkout main
git reset --hard HEAD~1  # Удалить из main

Найти коммит, удаливший строку

# Найти коммит, где была удалена строка
git log -S "removeUserFromStore" --oneline

# Найти коммит, где была добавлена строка
git log -S "removeUserFromStore" --diff-filter=A --oneline

Сравнить две ветки

# Список файлов, различающихся между ветками
git diff main..feature/auth --name-only

# Статистика изменений
git diff main..feature/auth --stat

# Конкретный файл
git diff main..feature/auth -- src/app/auth.service.ts

Скопировать файл из другой ветки

# Получить файл из другой ветки без слияния
git checkout feature/auth -- src/app/auth.service.ts

Итог

КомандаДля чего
git bisectБинарный поиск сломанного коммита
git blameКто изменил строку
git cherry-pickПеренести коммит в другую ветку
git stashВременно сохранить незакоммиченные изменения
git reflogИстория всех действий — восстановление «потерянных» коммитов
git cleanУдалить untracked/ignored файлы
git reset --softОтменить коммит, сохранив изменения
git commit --amendПоправить последний коммит
git log -S "text"Найти коммит по содержимому

Эти команды не нужны каждый день, но когда ситуация требует — они экономят часы работы. bisect и reflog — настоящие спасители: первый находит баг в истории из сотен коммитов, второй восстанавливает то, что казалось потерянным навсегда.