среда, 18 августа 2010 г.

Назад, в будущее...

Закоммитил не функционирующие изменения. Причем привык сразу делать hg push, чтобы не забыть это сделать позже. И только потом выяснил что все сломалось, надо выкинуть эти изменения и начать сначала. Но меркуриал немного разочаровал.

hg rollback можно делать только один раз и только до того как ты сделал push, при этом ревизия совершенно исчезает.

hg backout позволяет сделать откат, при этом добавляя еще одну ревизию.

Записал в дневнике: Достаточно переместить хед на одну ревизию назад и дальше пойти уже от нее. Тот хед - пусть болтается как тупиковая ветвь. Вполне естественно. Хотя может быть я что-то не понимаю.

Чуть позже я понял, что я не понимаю. Если ревизия удалена от tip - то меркуриал формирует backout changeset на него. Но при этом получается, что Все ревизии, которые находятся между bad и tip - содерждат ошибку.

Я не возражаю против того, что репозиторий должен содержать всю историю. Пусть содержит. Только нет необходимости замусоривать основную ветку. Ломающие ревизии должны быть исключены из основной ветки, пусть догнивают в боковых ветвях.

С последней ревизией все просто, ее стоит просто вывести в отдельную ветвь и забыть.

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

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

PS: Не знаю точно, умеет ли так делать git, не дружу я с ним.

PPS: Когда нибудь, может быть, я напишу свою систему контроля версий. :)

9 коммент.:

Анонимный комментирует...

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

Если плохой коммит имеет хэш $BAD_COMMIT, то вот как можно очистить историю:

git branch old_bad_history

git rebase -i $BAD_COMMIT # тут появится редактор, в котором надо исключить bad_commit
# если возникнут конфликты при ребазировании, то их надо решить вручную

А затем можно сделать git push origin old_bad_history; git push --force, чтобы обновить центральный репозиторий.

В hg тоже есть rebase, но не уверен, что там будет так же легко с бранчами

Андрей Валяев комментирует...

Как сложно то... :)

Ну тут вся фигня в том, что действительно получается полностью новая ветка.

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

Надо чтобы одна команда - drop revision. :) сразу все делала.

Алексей Марков комментирует...

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

В локальном репозитории можно переставить head, что в git, что в hg.

И, как уже было указано выше, локальную историю в git-е можно изменить в широких пределах при помощи rebase. Вот чего в hg не хватает (мне).

Андрей Валяев комментирует...

Я и не предлагаю совсем удалять ревизию, я понимаю что на сервере этого делать нельзя.

Моя мысль сводится к следующему (попытаюсь изобразить)

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

Вот наш мейнлайн:

O-O-O-O-O-O-O-O-O-O-head

Одна из ревизий все ломает

O-O-O-bad-O-O-O-O-O-O-head

Но остальные изменения пока считаем корректными :)

O-O-O-bad-good1-good2-good3-head

Мы "удаляем" плохую ревизию из мейнлайна

O-O-O-bad-good1-good2-good3-head
\-good1'-good2'-good3'-head'

Ветка автоматически переходит на новую голову

O-O-O-good1'-good2'-good3'-head'
\-bad-good1-good2-good3-head

И основная история становится чистой. Но тупиковая ветвь никуда не исчезает.

Можно их сравнить (разница будет представлять из себя приблизительный чейнджсет, который все сломал.) И исправленную версию наложить уже с хвоста... :)

Хотя есть кто-то успел от нее отфоркаться - может быть немного более сложно при мердже.

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

Хотя может быть такие манипуляции еще усложнят пуш, получается что мы пушим новую ветку. Переключать бранчи на сервере наверное не очень правильно.

Сложно все это. :)

Андрей Валяев комментирует...

Форматирование съехало, но понятно что ответвление идет от предыдущей ревизии по отношению к ломающей.

Алексей Марков комментирует...

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

"Ветка автоматически переходит на новую голову"
"Переключать бранчи на сервере наверное не очень правильно."

Именно так! Переключать у других историю - опасно и неправильно. Это вопрос не техники, а договоренности.

В вашем случае мне кажется многое идет из-за раннего push, который был сделан до прогона тестов. :-)

Анонимный комментирует...

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

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

Андрей Валяев комментирует...

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

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

А тот факт, что ревизии с rx по ry по определению глючные (поскольку содержать bad changeset) сильно мешает в проведении двоичного поиска.

В принципе переключать бранч не страшно, при условии, что другие ревизии храняться в базе.

Другие пользователи после pull увидят что бранч ушел, и проребасятся или че там они сделают, чтобы вернуться в бранч.

Это просто вопрос подхода.

А вот в hg например получается что вроде бы бранч один, но при этом присутствуют ветвления.. странно это ИМХО.

Алексей Марков комментирует...

С последней фразой согласен на все 100%!
Эту вещь в hg я понять-принять не могу. Но некоторые коллеги именно от нее в восторге.