Git: исправление ошибок и наведение порядка в коммитах

Ошибка в коммите… Как её исправить? Беспорядок в истории коммитов… Как привести всё в пристойный вид? Автор статьи, перевод которой мы публикуем сегодня, говорит, что она написана специально для тех, кто задавался такими вопросами. По его словам, изучив методики работы с Git, представленные здесь, можно значительно продвинуться по пути освоения Git.


Предполагается, что читатель этой статьи уже знаком с основами Git. Если это не так — сначала рекомендуется освоить базу, например, воспользовавшись этим материалом.

Исправление ошибок в коммитах

Здесь мы рассмотрим несколько сценариев появления ошибок в коммитах и их исправления.

▍Сценарий №1

Предположим, вы закоммитили много файлов и поняли, что сообщение коммита получилось не особенно понятным. После этого вы решили данное сообщение изменить. Для того чтобы это сделать, воспользуйтесь командой git commit --amend. Вот пример её применения:

git commit --amend -m "New commit message"

 

▍Сценарий №2

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

Такой подход вполне имеет право на жизнь. Но для того, чтобы поддерживать историю коммитов в хорошем состоянии, вероятно, было бы куда лучше иметь возможность добавить случайно пропущенный файл в тот же коммит. Сделать это можно, опять же, командой git commit --amend. Выглядит её использование так:

git add file6
git commit --amend --no-edit

Флаг --no-edit означает, что сообщение коммита не меняется.

▍Сценарий №3

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

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

git config user.email "your email id"

Предположим, вы забыли выполнить такую настройку и уже сделали первый коммит. Исправить положение может уже знакомая нам команда amend. С её помощью можно изменить сведения об авторе предыдущего коммита:

git commit --amend --author "Author Name <Author Email>"

 

▍Примечание

Используйте команду amend только в своём локальном репозитории. Её применение в удалённых репозиториях может привести к огромной путанице.

Наведение порядка в истории коммитов

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

Рекомендуется поддерживать синхронизацию между локальным и удалённым репозиториями. Это позволяет избежать множества конфликтов, связанных со слиянием, возникающих при слишком редкой синхронизации репозиториев. Следуя этой практике, вы решаете загружать изменения из удалённого репозитория каждые два дня.

Каждый раз, когда вы загружаете код из удалённого в локальный репозиторий, в локальном репозитории создаётся новый коммит-слияние (Merge Commit). Это означает, что в вашей локальной истории коммитов будет много таких коммитов, которые могут запутать того, кто будет просматривать ваш код.


История коммитов в локальном репозитории

Как привести в порядок историю коммитов? Для решения этой задачи можно воспользоваться командой git rebase.

▍Команда git rebase

Рассмотрим команду git rebase на примере.


Коммиты в ветке Release и в ветке Feature

В ветке Release есть три коммита: Rcommit1Rcommit2, и Rcommit3. Вы создали свою ветку Feature из ветки Release, когда в ней был всего один коммит — Rcommit1. После этого вы добавили два коммита в ветку Feature. Это — Fcommit1 и Fcommit2. Ваша цель заключается в том, чтобы загрузить коммиты из ветки Release в свою ветку Feature. Для того чтобы это сделать, вы собираетесь воспользоваться командой rebase.

Будем использовать для двух рассматриваемых веток имена release и feature.

В результате применение команды rebase будет выглядеть так:

git checkout feature
git rebase release

 

▍Особенности команды rebase

Команда rebase используется для того, чтобы обеспечить наличие в ветке Feature свежего кода из ветки Release.

При применении этой команды система пытается добавить в ветку Feature каждый коммит, по одному, и осуществить проверку на наличие конфликтов. Если звучит это сложно — давайте рассмотрим следующий рисунок. Тут показаны внутренние механизмы команды rebase.


Ветка Feature и три шага работы команды rebase

Шаг 1

В момент вызова команды ветка Feature указывает на голову ветки Release. После этого в ветке Feature оказывается три коммита: Rcommit1Rcommit2, и Rcommit3. Возможно, тут у вас появится вопрос о том, что случилось с коммитами Fcommit1 и Fcommit2. Эти коммиты никуда не делись, они будут использованы на следующих шагах.

Шаг 2

Теперь Git пытается добавить коммит Fcommit1 в ветку Feature. При отсутствии конфликта Fcommit1добавляется после Rcommit3. При обнаружении конфликта Git сообщит об этом и вам придётся разрешить этот конфликт вручную.

Шаг 3

После того, как в ветку Feature добавлен коммит Fcommit1, Git пытается добавить туда же Fcommit2. Тут, опять же, если конфликтов нет, то Fcommit2 добавляется после Fcommit1 и операция оказывается успешно завершённой. Если обнаружен конфликт, то Git, как и прежде, сообщит об этом и предложит с ним разобраться.

После завершения работы команды rebase можно будет увидеть, что в ветке Feature имеются коммиты Rcommit1Rcommit2Rcommit3Fcommit1, и Fcommit2.

▍Примечание

При работе с Git находят применение и команда merge, и команда rebase. Нельзя сказать, что одна из них предпочтительнее другой.

В случае использования команды merge вы получите коммит-слияние. В случае использования rebaseникаких дополнительных коммитов у вас не будет.

Рекомендуется использовать эти команды в различных ситуациях. Так, rebase подходит для обновления кода локального репозитория на основе свежего кода из удалённого репозитория. Используйте команду merge, выполняя пулл-запросы, направленные на слияние ветки Feature с веткой Release или Master.

Итоги

Изучив представленные в этом материале концепции, вы улучшили свои навыки владения Git и приблизились к уровню Git-эксперта. Надеемся, то, что вы тут узнали, вам пригодится. Но мир Git огромен, поэтому, освоив что-то новое, не останавливайтесь на достигнутом и двигайтесь дальше.