Перезапись истории

Не перезаписывайте историю, если вы уже отправили ветку в удаленный репозиторий или, рассматривая ситуацию с другой стороны, не отправляйте свою ветку в удаленный репозиторий, пока вы не будете ею довольны!

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

Это будет выражаться в том, что вместо прежних коммитов 1C:EDT будет создавать новые коммиты, содержащие те же самые изменения. В результате вы будете иметь у себя те же самые изменения, которые вам нужны, но с более понятной и красивой историей.

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

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

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

Конечно, есть ситуации, когда перезапись истории коммитов в опубликованной ветке не вредна, а даже полезна. Например, если это чисто экспериментальная ветка или это ветка, предназначенная для проверки написанного (review branches).

Исправить последний коммит (amend)

Например, вы зафиксировали изменения и после этого поняли, что забыли исправить что-то, относящееся к этой задаче. Или забыли написать что-то важное в сообщении коммита.

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

  1. Выполните забытые изменения (если нужно просто исправить сообщение, перейдите к п.4);
  2. Откройте панель Индексирование Git;
  3. Нажмите (Добавить все файлы в индекс) в контекстном меню поля Неиндексированные изменения;
  4. Нажмите (Дополнить (редактировать сообщение предыдущего коммита)) в контекстном меню поля Сообщение коммита;
    В поле появится сообщение предыдущего коммита;
  5. Отредактируйте сообщение коммита;
  6. Нажмите Фиксировать;

    Вместо последнего коммита будет создан новый коммит (с новым Id), который содержит прежние и новые изменения и новое сообщение коммита.

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

Как отменить исправление последнего коммита

Например, у вас есть последний коммит, «третий коммит», к которому вы хотите добавить некоторые доработки, о которых вы забыли.

Вы выполняете эти доработки, исправляете последний коммит, меняете сообщение коммита на «третий коммит + забытые доработки» и фиксируете изменения.

Прежний коммит заменяется новым коммитом, с новым Id, новым содержимым и новым сообщением коммита.

Однако теперь, запустив приложение и посмотрев на полученный результат, вы поняли, что поспешили исправлять последний коммит. Лучше вернуть все в исходное состояние, которое было до того, как вы стали добавлять забытые доработки. Но как это сделать, если старый коммит уже исчез?

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

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

В этой панели убедитесь, что выбрана ветка HEAD (или текущая ветка), а среди ссылок вы увидите тот коммит, на котором был указатель ветки до его исправления. Он будет предпоследним.

Чтобы отменить исправление последнего коммита нужно выполнить жесткий сброс на этот предпоследний коммит (СбросЖестко (HEAD, индекс и рабочий каталог) в контекстном меню). Ваша ветка вернется к исходному состоянию.

Изменить сообщение коммита (reword)

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

В том числе вы можете исправить сообщение не только последнего коммита, но и предыдущих.

Это можно выполнить в панели История:
  1. Найдите в списке нужный коммит;
  2. Нажмите ИсправитьРедактировать сообщение в его контекстном меню;
  3. Исправьте сообщение коммита;
  4. Нажмите Редактировать сообщение.

Вместо этого коммита будет создан новый. Если это не последний коммит, то вместо коммитов, следующих за этим, также будут созданы новые коммиты;

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

Исправить предыдущий коммит (edit)

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

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

Исправить предыдущий коммит можно в панели История:
  1. Найдите в списке нужный коммит;
  2. Нажмите ИсправитьРедактировать в его контекстном меню;
  3. 1C:EDT откроет панель Interactive Rebase. В ней будут содержаться выбранный коммит с действием Редактировать и следующие за ним коммиты с действием Выбрать;
  4. Выполните в проекте те изменения, которые вы хотите добавить к этому коммиту;
  5. В панели Индексирование Git нажмите (Добавить все файлы в индекс) в контекстном меню поляНеиндексированные изменения;
  6. Отредактируйте сообщение коммита;
  7. Нажмите Фиксировать;
  8. Нажмите Продолжить в панели Interactive Rebase или в панели Индексирование Git.
Предупреждение: Обратите внимание, что вместо прежнего коммита и следующих за ним создаются новые коммиты с новыми идентификаторами. В результате все выглядит так, как будто первоначальные коммиты никогда не существовали. Поэтому не исправляйте предыдущий коммит, если вы уже отправили его в удаленный репозиторий. Это вызовет проблемы у тех разработчиков, которые уже успели получить ваши изменения из удаленного репозитория.
Ловкий прием: Если результат исправления предыдущего коммита вас не устраивает, вы можете вернуть все к исходному состоянию так же, как и в случае с обычным перебазированием. Как это сделать, рассказано в разделе Как отменить перебазирование.

Объединить коммиты

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

Используйте для этого интерактивное перебазирование:

  1. Извлеките ветку, которую вы хотите преобразовать. Например, feature;
  2. В панели История выберите родителя этой ветки;
  3. Нажмите Interactive Rebase в контекстном меню этого коммита. Для того, чтобы вы могли задать операции, применяемые к коммитам, 1C:EDT откроет панель Interactive Rebase;
  4. Для всех коммитов, кроме первого, выберите действие Squash;
  5. Нажмите Старт, чтобы выполнить интерактивное перебазирование;
  6. 1C:EDT создаст новый коммит вместо прежних и откроет диалог, в котором будут собраны сообщения всех обработанных коммитов;
  7. Отредактируйте сообщение нового коммита;
  8. Нажмите Редактировать сообщение.

В результате вместо прежних трех коммитов будет создан один новый коммит, содержащий все их изменения.

Предупреждение: Интерактивное перебазирование перезаписывает историю коммитов. Поэтому не выполняйте интерактивное перебазирование, если вы уже опубликовали свою ветку в удаленном репозитории. Ваши коллеги, возможно, уже использовали опубликованные вами изменения в своей работе. Ваше интерактивное перебазирование заставит их также перезаписывать и изменять свою работу. Исключение могут составлять только те ветки, которые предназначены исключительно для экспериментов или для проверки написанного (review branches).
Ловкий прием: Если результат объединения коммитов вас не устраивает, вы можете вернуть все к исходному состоянию так же, как и в случае с обычным перебазированием. Как это сделать, рассказано в разделе Как отменить перебазирование.