>
git commit -m "WIP"
— три слова, после которых начинается настоящий ад.
Приветствую. Такая технология как Git в представлении не нуждается. Все знают add, commit, push — это как азбука. Но что делать, когда что-то пошло не так? Ошибочный коммит прокатился по ветке? Надо срочно переключиться, но незавершенные правки мешают? Нужно перенести только одно исправление из другой ветки?
Знакомая ситауция? Тогда давайте разберем 5 команд, которые выходят за рамки базового workflow и реально спасают репутацию (и ваши нервные клетки): revert, stash, cherry-pick, reset --soft и bisect. Перейдем от теории к практике.
❯ Теория (минимум, чтобы понимать «почему»)
Git хранит историю как цепочку коммитов(своеобразных контрольных точек). Каждый коммит — это снимок(snapshots) состояния ваших файлов на момент создания + ссылка на родителя(ей). Ветки — это просто подвижные указатели на конкретные коммиты в этой цепочке.

В Git есть три основных состояния, в которых могут находиться ваши файлы: modified
, staged
и committed
modified
означает, что вы изменили файл, но ещё не закоммичен в базе данных.
staged
означает, что вы отметили изменённый файл в его текущей версии для добавления в снимок следующего коммита.
committed
означает, что данные надёжно хранятся в вашей локальной базе данных.

Staging area часто именуется как Git Index или просто индекс.
Основная ответственность за чистоту истории и корректность кода лежит на разработчике. Однако Git предоставляет достаточно способов для управления историей и рабочим состоянием, когда что-то идет не по плану. Эти инструменты позволяют:
Отменять изменения, уже попавшие в историю.
Временно убирать незавершенную работу.
Точечно переносить изменения между ветками.
Аккуратно переписывать последние коммиты.
Автоматически искать источник проблемы.
Хорошо, мы поняли, что Git — это не только линейное добавление коммитов. А с помощью каких конкретно команд достигается это гибкость в управлении во время кризисных ситуациях? Познакомимся с сегодняшними героями:
5 Спасательных Команд
❯ git revert : Мягкая отмена
Проблема: Вы закоммитили и запушили ошибочный код. Просто удалить коммит из истории (
reset
) на удаленном сервере — плохая практика (ломает историю для коллег). Нужно отменить изменения, но сохранить факт ошибки и исправления.-
Решение: git revert создает новый коммит, который является инверсией (противоположностью) изменений указанного коммита. Он не стирает старый плохой коммит, а аккуратно «откатывает» его эффект.
Допустим, наш злосчастный коммит имеет хеш zxc123 git revert zxc123 # Git откроет редактор для сообщения нового коммита-отмены # (можно оставить по умолчанию). # Пушим исправление-отмену git push origin main
Польза: История остается целостной. Коллеги видят и ошибку, и ваше исправление. Идеально для исправления уже опубликованных ошибок в main/master.
❯ git stash: Мастер переключения контекста
Проблема: Вы активно работаете над фичей в ветке feature/login, но срочно нужно починить баг в main. Делать коммит с полуготовым кодом (WIP: Something...) — некрасиво и может сломать сборку. Нужно временно убрать текущие изменения.
Решение: git stash берет все изменения в рабочей директории и индексе (те, что были бы добавлены git add), упаковывает их в специальное хранилище («stash») и возвращает рабочую директорию к состоянию последнего коммита. Чисто!
#В ветке feature/login с незавершенными изменениями:
git stash # Сохраняем изменения в stash. Рабочая директория чиста!
git checkout main # Переключаемся на main для срочного багфикса
#Чиним баг в main, коммитим, пушим...
git checkout feature/login # Возвращаемся к своей фиче
git stash pop # Возвращаются последние застэшенные изменения обратно в рабочую директорию (и удаляются из stash)
#Или:
git stash apply # Применить изменения, но оставить копию в stash
Польза: Мгновенно освобождает рабочее состояние для срочных задач без создания мусорных коммитов. pop/apply — и вы точно там, где остановились.
❯ git cherry-pick : Точечный перенос
Проблема: Вы починили критический баг в ветке hotfix/v1.1 (коммит dev456). Этот фикс срочно нужен и в ветке develop, но переносить всю ветку hotfix (merge) пока нельзя или не нужно. Нужно взять только этот один коммит с исправлением.
-
Решение: git cherry-pick «переносит» изменения из указанного коммита (созданного где-то в другом месте истории) и применяет их как новый коммит в текущей ветке.
git checkout develop # Переходим в ветку, куда нужен фикс git cherry-pick dev456 # Git попытается применить изменения из коммита dev456 #Возможны конфликты! Их нужно разрешить, как при мерже. git add . # После разрешения конфликтов добавляем файлы git cherry-pick --continue # Завершаем применение (создается новый коммит в develop) git push origin develop
Польза: Позволяет делиться конкретными исправлениями между ветками без полного слияния, поддерживая изоляцию функциональности. Осторожно: злоупотребление может запутать историю.
❯ git reset --soft HEAD~1: Вежливый ребейз последнего коммита
Проблема: Вы сделали коммит (commit A), но сразу поняли, что:
Забыли добавить файл.
Сообщение коммита написано криво.
Небольшая ошибка в коде, которую стыдно коммитить отдельно.
Хотите разбить один большой коммит на несколько логичных.
ВАЖНО – коммит еще не запушен!
Решение: git reset --soft HEAD~1 «отматывает» указатель текущей ветки на 1 коммит назад (на родителя HEAD), но сохраняет все изменения из отмененного коммита A в индексе (staging area) и рабочей директории. Фактически, коммит A исчезает из истории текущей ветки, а его изменения готовы к новому коммиту.
#Сделали коммит с ошибкой/недоделкой (commit A), НЕ ПУШИЛИ.
git reset --soft HEAD~1 # История "откатилась" на шаг назад.
# Все изменения из commit A теперь в индексе (как будто вы сделали git add . после правок).
# Исправляем файлы, которые забыли/исправляем ошибки...
git add zabyl.js # Добавляем то, что забыли
й
git commit -m "Новое сообщение коммита" # Создаем новый правильный коммит
Польза: Позволяет аккуратно переписать последний, еще не опубликованный коммит, не оставляя следов «стыдных» промежуточных коммитов. Важно: работает только для НЕзапушенных коммитов!
❯ git bisect: Детектив по поиску бага
Проблема: В проекте обнаружился баг. Вы уверены, что неделю назад его не было. За это время было сделано 50 коммитов. Ручной поиск коммита, где баг появился — ад. Нужен автоматизированный поиск виноватого.
-
Решение: git bisect использует алгоритм бинарного поиска. Вы указываете:
«Хороший» коммит (где бага точно нет,
git bisect good
).«Плохой» коммит (где баг точно есть, обычно текущий HEAD,
git bisect bad
).
Git автоматически переключит вас на коммит посередине между "хорошим" и "плохим". Вы проверяете наличие бага и говоритеgit bisect good
(бага нет) илиgit bisect bad
(баг есть). Git сужает диапазон и переключает вас снова. Повторяете, пока Git не укажет точный коммит, где появился баг.
# Начинаем сессию
git bisect start
#Текущее состояние (HEAD) - плохое (баг есть)
git bisect bad HEAD
# Тег v1.2 (или хеш коммита) - хорошее (бага нет)
git bisect good v1.2
# Git автоматически переключит на коммит посередине.
# Запускаем тесты/проверяем вручную наличие бага...
# Если баг ЕСТЬ в этом состоянии:
git bisect bad
# Если бага НЕТ в этом состоянии:
git bisect good
# Если не удаётся проверить (например, код не компилируется)
git bisect skip
# Git переключит на новый коммит (середину нового диапазона). Повторяем проверку...
# В итоге Git сообщит: "abc123 is the first bad commit"
git bisect reset # Завершаем сессию, возвращаемся в исходную ветку
Польза: Резко сокращает время поиска коммита, в котором была внесена ошибка, с O(n) до O(log n). Незаменим для анализа регрессий.
Фактически, git bisect можно использовать для поиска коммита, который изменил любое свойство вашего проекта; например, коммит, который исправил ошибку, или коммит, который привел к улучшению производительности бенчмарка.
❯ Заключение
Используйте Git не только для линейного добавление кода. Это отличный инструмент для управления историей и рабочим процессом, особенно когда что-то идет не так(а оно всегда идет). Освоение revert
, stash
, cherry-pick
, reset --soft
и bisect
выводит ваше владение Git на новый уровень. Эти команды:
Сохраняют историю чистой (
revert
вместо опасногоreset
).Повышают вашу гибкость (
stash
для мгновенного переключения контекста).Позволяют точечно делиться исправлениями (
cherry-pick
).Дают шанс на исправление локальных ляпов (
reset --soft
для последнего коммита).Экономят часы отладки (
bisect
для поиска источника зла).
Не бойтесь их использовать (с пониманием последствий, конечно). Они действительно сэкономят вам кучу нервов и помогут поддерживать репутацию надежного разработчика.
Когда следующий баг заставит вас плакать в git log, незовите маму — зовите bisect
. А если коллега случайно сломает main — дайте ему ссылку на эту статью. Или просто revertните его последний коммит.
Happy Gitting
Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале ↩
? Читайте также:
Комментарии (29)
inkvizitor68sl
24.07.2025 08:39Очередная статья про гит без упоминания worktree.
Worktree нужно пихать в каждую статью про гит двадцать пятым кадром. Как гипнотизеры, в рандомные места в статье вставлять слово worktree. Начинать статью с этого слова, и прощаться с читателями, используя это слово. Можно даже не писать, что это - просто возьмите 10 слов worktree и рассыпьте по статье - но без этого минимума статьи про гит писать нельзя.
eeman22
24.07.2025 08:39git reflog бы еще упомянул.
Ты случайно долбанул, например,
git reset --hard
удалил ветку или потерял коммит - git log их не показывает.
делаемgit reflog
+git checkout
и в след раз не втыкаем:)
vDyDHp8
24.07.2025 08:39Интеллидж развратила нас своим шелвом и я хз когда я позапрошлый раз в гит что то руками делал).
Viacheslav01
24.07.2025 08:39А я наоборот все руками делаю, ну кроме просмотра изменений больших в файлах.
Все остальное руками, не доверяю я этим GUI )))
RulenBagdasis
24.07.2025 08:39Ага, а потом: "я не знаю, что случилось, я что-то нажал и оно само" ))) Предпочитаю работать с гитом из консоли, так ты точно уверен, что ты делаешь и какой будет результат. Да и универсальнее так, ты не привязан к редактору/ide, у тебя всегда один и тот же интерфейс.
guryanov
24.07.2025 08:39А в чем проблема мусорных коммитов? Их же никто не заставляет пушить. Наоборот, закоммитил в ветке задачи коммит tmp и потом можно хоть через год к этой задаче вернуться и доделать. Конечно надо будет этот коммит отредактировать, способов много разных. К примеру тот же git reset HEAD~1 доделать код и закоммить потом как следует.
abby
24.07.2025 08:39Если кто-нибудь использует git stash, можете объяснить в чём преимущество по сравнению с неиспользованием. Ещё и в Visual Studio и в Code пиарят, как и тут; запарился уже объяснять альтернативы и помогать коллегам с этим git stash.
xDamneDx
24.07.2025 08:39Очень удобно использовать если ты изменения внес, которые еще рано коммитить, застешил, сходил в другую ветку (например пр чей-то в ide посмотреть), вернулся в свою ветку и сделал git stash pop, но это если аккуратно относиться к коммитам, так-то можно и git commit -am “WIP” и погнал.
Еще удобно если в текущую ветку нужно подлить изменения: стеш, пулл, поп, вместо ребейса или простигосподи мержа
gluck59
24.07.2025 08:39Git stash полезен например при совпадении следующих двух условий:
Между вашей локальной машиной и сервером существуют некие различия. То ли на сервере линух (а у вас локально вындоуз), то ли на сервере фря (а у вас локально убунта), то ли еще что-то подобное, что нельзя привести в полное соответствие.
У вас локально все ок, а на сервере глюк. Код одинаковый, база одинаковая, а вот глюк.
Это как раз тот случай, когда вам приходится заходить на сервер, расставлять в ключевых местах вывод дебага и чинить глюк точечно.
Даже если вы впоследствии убьете весь этот дебаг, контрольные суммы правленых на сервере файлов изменятся и следующий git pull сругается на "чего-то тут незакоммиченое есть".
И вот тогда вы пушите фикс найденного глюка в проекте, делаете stash на сервере и затем спокойно повторяете pull там же.
И всё становится хорошо.
Pavel1114
24.07.2025 08:39не лучшие практики. Отсутствие CI и замена его git pull. Отстуствие логирования, настраиваемого без правки кода. Ну и непонятно зачем тут stash, если логичнее было бы просто git reset --hard - вы же просто хотите потереть вывод дебаг перед pull.
Eltaron
24.07.2025 08:39Git в прод-директории на сервере? Ммм, так вот чей проект ищут боты, брутфорсящие GET /.git/HEAD
gluck59
24.07.2025 08:39Да? Ну хорошо, предположим что уже нашли: https://atmclub.ru/
Расскажите плиз что у вас получилось.
xDamneDx
24.07.2025 08:39Я бы посоветовал git rebase -i —exec вместо bisect, так можно автоматически прогнать любую команду на интервале коммитов
Pavel1114
24.07.2025 08:39git bisect конечно же поддерживает выполение команды на каждом шаге, что позволяет автоматизировать процесс. Странно, что об этом не упомянуто в статье https://git-scm.com/docs/git-bisect#_bisect_run
abby
24.07.2025 08:39Всё таки, субъективно, со своими коммитами удобнее, потому что сам контролируешь и устоявшийся годами work flow, хотя и stash тоже коммититы создаёт.
А вообще у меня всегда минимум три worktree или вообще независимых клона. Надо переключиться по какой-либо прочине (срочно, или приоритеты поменялись или что-то перепроверить и т.п.), просто в соседней копии делаешь и всё.
Тут ещё срочное может быть в ветке другой версии (например, какой-нибудь релиз, или вторая версия, типа legacy, и т.п.) Там свои зависимости как минимум, проект другой, надо всё перезапускать. Всё это дёргать и пересобирать - только время тратить. Со второй копией хоть дебаг оставь в середине, потом вернёшься и всё хорошо.
При этом почему-то новички в git всегда теряются с этими stash, то у них одно, то другое, то конфликты, то что-то как-то исчезло. Обьясняешь, что делает stash, говоришь, делай так сам, а потом как хочешь применяй свои изменения, и эти проблемы как правило уходят.
Ответ на https://habr.com/ru/companies/timeweb/articles/927102/comments/#comment_28617254
ZoRDoK
24.07.2025 08:39git commit --amend
Рекомендую, если хотите красивые коммиты, а не "закоммитил в пятницу вечером, в пн разберусь" - команда добавляет в предыдущий коммит
garm
Вместо
git reset --soft HEAD~1
я обычно использую
git commit --amend
Помогает во всех случаях, кроме разбиения большого коммита на несколько маленьких.
Akhmed_theDark
А чем эта запись отличается от git reset —hard. Помоему тоже самое нет?
garm
Нет, reset —hard убирает не только последний коммит, но и все его изменения. Если изменения нужно только немного подправить, это не очень удобно.
Fedorkov
Вы двое, видимо, говорите про
git reset --hard HEAD~
. Без последнего аргумента команда просто отменяет незакоммиченные изменения (кроме untracked файлов), не трогая последний коммит.Necessitudo
А если коммит уже запушен? Работает?
amphasis
в любом случае после такого придется делать push -f
mvv-rus
А, может, попробуем обойтись push --force-with-lease ?
amphasis
Руками я бы это поленился писать, а учитывая то, что веду работу в своей персональной ветке, как будто разницы нет.
PS. Да и что греха таить, большинство git команд выполняю через интерфейс IDE, а в консоль лишь изредка приходится залезть за каким-нибудь
git branch -u
mvv-rus
Visual Studio 2022 позволяет настроить использование из IDE именно --force-with-lease. А я в ней работаю.
Fedorkov
Я обычно ещё добавляю
--no-edit
, чтобы гит не предлагал редактировать название коммита.