Полезные команды Git: безопасная отмена коммитов, добавление файла из другой ветки и другие

Рассказывает автор блога AlgoTech


Git — это мощный, хотя и незамысловато выглядящий, инструмент, который при неосторожном использовании может устроить большой беспорядок. Поэтому, прежде чем пробовать выполнять различные фокусы с Git, я рекомендую ознакомиться с его основными командами (init, clone, push, pull, status, log и т.д.) и концептами (репозиторий, ветвь, коммит, и т.д.).

Итак, если вы уверенно чувствуете себя при работе с Git, вот несколько полезных трюков, о которых я знаю.

Reflog. Отмена операций

Я помню, что в начале знакомства с Git я боялся запускать команды. Я думал, что всё испорчу. Например, первое использование git rebase вызвало у меня несколько восклицаний наподобие «Вот *****! Что я только что сделал?!» из-за дублировавшихся или вообще исчезнувших коммитов. Вскоре после этого я понял, что нужно идти дальше.

Лично я не люблю использовать инструмент, не зная, что именно он делает для достижения результата. Это как вождение машины без руля: всё прекрасно до тех пор, пока не доедешь до поворота. А что потом? Ну, вы меня поняли.

Итак, в нашем деле очень важно понимать концепты. Я много читал про Git, прошёл несколько обучающих курсов, и моё видение мира Git кардинально изменилось. Используя его, я стал чувствовать себя гораздо спокойнее, а что более важно, я познал его истинную мощь. И одной из самых мощных команд является git reflog.

Используя reflog, вы можете вернуться в прошлое, отменяя почти любые действия, сделанные в Git. Даже если это были rebase или reset. Кроме того, её легко использовать. Чтобы доказать это, приведу маленький пример.

Чтобы изменить нужное состояние, нужно запустить checkout, используя абсолютную ссылку:

или относительную ссылку:

и вы окажетесь в независимом (detached) состоянии HEAD, из которого можно создать новую ветвь.

Вот и всё. Все операции после вышеуказанного состояния отменены.

Revert. Отмена изменений коммита

Вы, должно быть, сталкивались с ситуацией, когда вам нужно было отменить некоторые изменения. На помощь придёт команда revert:

Что она делает? Она просто отменяет действия прошлых коммитов, создавая новый, содержащий все отменённые изменения. Зачем использовать её вместо других решений? Это — единственный безопасный способ, так как он не изменяет историю коммитов. Он обычно используется в публичных ветвях, где изменение истории нежелательно.

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

Rebase

Вы можете выполнить эту команду и просто убрать строки, относящиеся к ненужным коммитам. Это самое очевидное и простое решение, но у него есть недостаток, из-за которого его нельзя использовать в публичных ветвях: он изменяет историю коммитов. Поэтому после rebase’а у вас может возникнуть проблема с push’ем.

Reset

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

Checkout

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

Вывод таков, что git revert — самая безопасная операция для отмены действий. Кроме того, нужно заметить, что эти команды не взаимозаменяемы в 100% случаев.

Log. Более приятное форматирование

С git log всё просто. Вы вводите команду и видите историю коммитов в хронологическом порядке, и каждый пункт включает в себя хэш коммита, автора, дату и прикреплённое сообщение.

Давайте взглянем на вид лога по умолчанию:

Я думаю, что могло бы быть и лучше.

Я предпочитаю простые вещи. Поэтому я использую две опции:

  • –oneline – показывает каждый коммит в одной строке. Кроме того, она показывает лишь префикс ID коммита.
  • –decorate – печатает все относительные имена показанных коммитов.

Вот как это выглядит:

Опция –oneline сокращает количество занятых строк, а опция –decorate добавляет относительные имена (локальные/удалённые ветви + HEAD). Используя эти две опции, мы получаем более компактный и осмысленный git log. Да, мы теряем некоторые вещи, но они не особо важны. Так гораздо лучше, да?

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

Ничего себе! Давайте посмотрим, как это выглядит:

Весьма неплохо.

И всё-таки вводить эти команды каждый раз достаточно неудобно, так? Давайте создадим алиасы. Я считаю, что использование алиасов очень сильно повышает продуктивность. Чтобы зарегистрировать их, добавим следующие строки в «~/.bash_profile» (конечно, если вы используете *nix OS):

Таким образом, мы получили не только хорошо выглядящую историю коммитов, но и упрощённый способ доступа к ней, используя команды gl и gh.

Еще один вариант украшения вывода лога приведен в этой статье.

Diff. Разница между коммитами

Простая команда, показывающая изменения между объектами в проекте — git diff. Один из основных сценариев её использования — сравнение двух коммитов:

Другой — вывод всех изменений, не внесённых в индекс. Для этого нужно выполнить следующее:

Branch. Проверка ветвей на слияние

Я думаю, вы уже знаете, что делает базовая команда git branch (без опций выводит список локальных веток — прим. перев.), поэтому перейдём к делу. Время от времени вам понадобится удалять старые или ненужные ветви из вашего «дерева» git.

Используя следующее:

вы получите список всех веток, соединённых с текущей.

Можно и наоборот:

Так вы получите список всех не соединённых с текущей веток.

Таким образом, вы всегда узнаете, безопасно ли удаление той или иной ветви.

Checkout. Получение файла из другой ветви

Вам наверняка приходилось искать конкретную версию файла, которая была в другой, ещё не присоединённой ветви. Помните команду checkout, приведённую выше? Она выглядит так:

Указанный файл будет приведен к версии, указанной в заданном коммите. Раньше мы использовали это для отмены изменений файла. Удобно то, что этот коммит необязательно должен находиться в той же ветви, что и наш файл. Поэтому мы можем задать любому файлу любую версию из любого коммита или ветви.


Надеюсь, вы нашли здесь для себя что-то полезное. Прошу заметить, что все вышеуказанные моменты субъективны, поскольку я подгонял их под свои нужды.

Перевод статьи «Git Tips and Tricks»