- PVSM.RU - https://www.pvsm.ru -
>
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 — это не только линейное добавление коммитов. А с помощью каких конкретно команд достигается это гибкость в управлении во время кризисных ситуациях? Познакомимся с сегодняшними героями:
Проблема: Вы закоммитили и запушили ошибочный код. Просто удалить коммит из истории (reset) на удаленном сервере — плохая практика (ломает историю для коллег). Нужно отменить изменения, но сохранить факт ошибки и исправления.
Решение: git revert [1] создает новый коммит, который является инверсией (противоположностью) изменений указанного коммита. Он не стирает старый плохой коммит, а аккуратно «откатывает» его эффект.
Допустим, наш злосчастный коммит имеет хеш zxc123
git revert zxc123
# Git откроет редактор для сообщения нового коммита-отмены
# (можно оставить по умолчанию).
# Пушим исправление-отмену
git push origin main
Польза: История остается целостной. Коллеги видят и ошибку, и ваше исправление. Идеально для исправления уже опубликованных ошибок в main/master.
Проблема: Вы активно работаете над фичей в ветке feature/login, но срочно нужно починить баг в main. Делать коммит с полуготовым кодом (WIP: Something...) — некрасиво и может сломать сборку. Нужно временно убрать текущие изменения.
Решение: git stash [2] берет все изменения в рабочей директории и индексе (те, что были бы добавлены 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 — и вы точно там, где остановились.
Проблема: Вы починили критический баг в ветке hotfix/v1.1 (коммит dev456). Этот фикс срочно нужен и в ветке develop, но переносить всю ветку hotfix (merge) пока нельзя или не нужно. Нужно взять только этот один коммит с исправлением.
Решение: git cherry-pick [3] «переносит» изменения из указанного коммита (созданного где-то в другом месте истории) и применяет их как новый коммит в текущей ветке.
git checkout develop # Переходим в ветку, куда нужен фикс
git cherry-pick dev456 # Git попытается применить изменения из коммита dev456
#Возможны конфликты! Их нужно разрешить, как при мерже.
git add . # После разрешения конфликтов добавляем файлы
git cherry-pick --continue # Завершаем применение (создается новый коммит в develop)
git push origin develop
Польза: Позволяет делиться конкретными исправлениями между ветками без полного слияния, поддерживая изоляцию функциональности. Осторожно: злоупотребление может запутать историю.
Проблема: Вы сделали коммит (commit A), но сразу поняли, что:
Забыли добавить файл.
Сообщение коммита написано криво.
Небольшая ошибка в коде, которую стыдно коммитить отдельно.
Хотите разбить один большой коммит на несколько логичных.
ВАЖНО – коммит еще не запушен!
Решение: git reset [4] --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 "Новое сообщение коммита" # Создаем новый правильный коммит
Польза: Позволяет аккуратно переписать последний, еще не опубликованный коммит, не оставляя следов «стыдных» промежуточных коммитов. Важно: работает только для НЕзапушенных коммитов!
Проблема: В проекте обнаружился баг. Вы уверены, что неделю назад его не было. За это время было сделано 50 коммитов. Ручной поиск коммита, где баг появился — ад. Нужен автоматизированный поиск виноватого.
Решение: git bisect [5] использует алгоритм бинарного поиска. Вы указываете:
«Хороший» коммит (где бага точно нет, 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
➤ [6]Семантическое моделирование. Проектирование БД с помощью ER-модели [7]
➤ Огромный гайд по настройке рабочего окружения: Linux, VScode, Python [8]
➤ DevOps Tutorials — Ansible: разворачиваем веб-приложение на виртуальном сервере [9]
➤ [11]35-летний юбилей! Советский «Поиск-1» выходит в Cеть [12]
Автор: WolfffR
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/git/426210
Ссылки в тексте:
[1] git revert: https://git-scm.com/docs/git-revert
[2] git stash: https://git-scm.com/docs/git-stash
[3] git cherry-pick: https://git-scm.com/docs/git-cherry-pick
[4] git reset: https://git-scm.com/docs/git-reset
[5] git bisect: https://git-scm.com/docs/git-bisect
[6] : https://habr.com/ru/companies/timeweb/articles/845410/
[7] Семантическое моделирование. Проектирование БД с помощью ER-модели: https://habr.com/ru/companies/timeweb/articles/916824/
[8] Огромный гайд по настройке рабочего окружения: Linux, VScode, Python: https://habr.com/ru/companies/timeweb/articles/916040/
[9] DevOps Tutorials — Ansible: разворачиваем веб-приложение на виртуальном сервере: https://habr.com/ru/companies/timeweb/articles/913426/
[10] Будущее JavaScript: что нас ждет: https://habr.com/ru/companies/timeweb/articles/927768/
[11] : https://habr.com/ru/companies/timeweb/articles/884082/
[12] 35-летний юбилей! Советский «Поиск-1» выходит в Cеть: https://habr.com/ru/companies/timeweb/articles/929590/
Нажмите здесь для печати.