Hg: Редактируем историю

Mercurial - распределенная система управления версиями, поэтому commit делается сначала локально, а затем только отсылается на централизованный (или не очень) сервер. Со времен использования SVN, описание каждого commit'а должно соответствовать неким требованиям ( например содержать номер задачи или bug в системе bug-tracking ). При использовании SVN все просто - "commit rejected", но как быть с Mercurial когда посылается пачка уже готовых изменений. В такое ситуации к нам на помощь приходит расширение histedit.

Histedit идет вместе с Mercurial начиная с версии 2.3, поэтому просто подключаем его в своем ~/.hgrc (или в hgrc локального репозитория <repo_root>/.hg/hgrc):

[extensions]
histedit=

Итак, есть у нас некий абстрактный репозитория с историей:

$ hg log
changeset:   2:d364cae76afb
tag:         tip
user:        ab
date:        Mon Jul 14 13:20:11 2014 +0400
summary:     3

changeset:   1:1ce63774ddf9
user:        ab
date:        Mon Jul 14 13:20:05 2014 +0400
summary:     2

changeset:   0:1f8f1cd01b1f
user:        ab
date:        Mon Jul 14 13:19:48 2014 +0400
summary:     1

Нужно отредактировать сообщения к commit'ам 1 и 2. Выполняем команду:

$ hg histedit -r 1

Должен открыться редактор ( если открылся не в том редакторе, исправить это можно так export EDITOR=<editor_exe>) с содержимым начинающимся с:

pick 1ce63774ddf9 1 2
pick d364cae76afb 2 3

Иправляем pick на mess:

mess 1ce63774ddf9 1 2
mess d364cae76afb 2 3

Сохраняем и после этого последовательно будут открываться редакторы с сообщениями "2" и "3", которые заменяем на "Change message 2" и "Change Message 3", получаем:

$ hg log
changeset:   2:c857ece3f07a
tag:         tip
user:        ab
date:        Mon Jul 14 13:25:25 2014 +0400
summary:     Change Message 3

changeset:   1:428df879bb9d
user:        ab
date:        Mon Jul 14 13:24:57 2014 +0400
summary:     Change message 2

changeset:   0:1f8f1cd01b1f
user:        ab
date:        Mon Jul 14 13:19:48 2014 +0400
summary:     1

Если есть необходимость, не только подправить сообщение но и сами изменения, тогда выполняем всю туже команду:

$ hg histedit -r 1

Заменяем pick на edit, и сохраняем. Histedit вернет состояние локального репозитория до коммита. После внесения изменений, нужно снова делать:

$ hg commit -m "<Your new message>"
$ hg histedit --continue

"hg histedit --continue" выполняем для того чтобы histedit внес изменения в иторию репозитория. В зависимости от количества редактируемых commit'ов histedit или закончит работу или перейдет к редактированию следующего commit'а.

Попадет ли отредактированная история на сервер? Хороший вопрос, не проверял, скорее всего нет.