Исследователь
0,1
рейтинг
31 июля 2013 в 19:20

Разработка → Полезности Mercurial

Думаю, почти все читающие знают, что такое Mercurial — это распределённая система контроля версий, для исходного кода и других (преимущественно текстовых) файлов. Многие ей пользуются, и знают основные команды, как то удаление/добавление файлов, создание коммита и отправка локальных изменений в другие репозитории. Однако, Mercurial имеет множество не столь известных функций и команд, которые часто достаточно полезны и удобны. Некоторые из них можно использовать сразу после установки по-умолчанию, некоторые нужно включить в настройках, а для других может потребоваться скачать дополнительное расширение.

Краткий список того, о чём пойдёт речь в статье:

  • hg serve (hgweb) — встроенный веб-сервер
  • расширения pager, progress и color
  • hg [c]record — выбор отдельных изменений для коммита
  • revsets и filesets — поиск коммитов и файлов с запросами любой сложности
  • hg evolve — Changeset Evolution или же «изменяемая история»


logo


hg serve (hgweb)



В стандартную поставку Mercurial входит веб-сервер, который позволяет быстро просмотреть репозиторий с удобным интерфейсом в любом браузере — для этого достаточно, находясь в папке с репозиторием, выполнить hg serve, и зайти на localhost:8000 (стандартный порт — 8000). Так можно просматривать почти всю информацию, которая доступна через обычный интерфейс командной строки. При этом с другого компьютера по сети можно использовать hg clone с адресом запущенного hgweb для клонирования.

Конечно, было бы странно, если бы веб-сервер можно было использовать только для этого — и это не так. Hgweb можно настроить так, чтобы он обрабатывал сразу несколько репозиториев, например из одной папки, а также поставить перед ним nginx или другой сервер (вариантов коммуникации хватает — обычный http через порт, или к примеру wcgi). Тонкости конфигурации рассмотрены в частности в официальной вики Mercurial. Важная функция, которой иногда не хватает в hgweb — авторизация пользователей и права на чтение/запись — также может быть реализована установкой и настройкой дополнительного frontend сервера. Например, я использую для этого обычную http-авторизацию в nginx, который запрещает любой неавторизованный доступ к приватным репозиториям, а также push в публичные.

Что касается внешнего вида, то в комплекте поставляется несколько тем на выбор, по-умолчанию используется «paper».

Примеры: selenic.com/hg — официальный репозиторий, hg.python.org — репозитории Python, hg.aplavin.ru — мои (в основном) репозитории.

Расширения pager, progress, color



Эти расширения входят в установку Mercurial, и для использования достаточно включить их в настройках. Для этого нужно добавить в файл ~/.hgrc секцию расширений:

[extensions]
pager = 
progress = 
color = 


(да, после знаков равенства ничего нет). Эти расширения делают работу с CLI-интерфейсом несколько более удобной: выводы многих команд становятся цветными, во время длительных операций выводится прогрессбар, а длинные простыни команд вроде hg log можно прокручивать — они открываются в стандартном pager'e (обычно это less). К сожалению, страницы помощи (hg help) открываются как и раньше, и для их удобного просмотра нужно вручную дописывать | less. Эти расширения не включены по-умолчанию, как говорит автор Mercurial, из-за иногда встречающихся неожиданных проблем с ними, в частности на Windows.

hg [c]record



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

Однако, это расширение не очень удобное и подходит только для эпизодических правок. Если вы пользуетесь такой функцией чаще, лучше скачать и подключить другое расширение, не из стандартного комплекта: crecord. Оно предоставляет достаточно удобный для использования псевдографический интерфейс (пример от его автора: image). Конечно, есть и полностью графические утилиты для этого (мне, например, понравилась qct, написанная на Qt), но для простых правок прямо «на месте» в консоли crecord вполне удобен.

revsets



Mercurial использует язык запросов, который можно использовать для сколь угодно сложных критериев поиска коммитов, причём он поддерживается во всех командах, которые работают с коммитами (а скоро будет и в hgweb). Например, почти «классический» пример — есть некоторый коммит, в котором исправлен баг, и нужно найти релизы в которые этот багфикс попал. Предполагая, что для задания релизов используются теги (все проекты, которые видел, так и делают), такой запрос можно сформулировать как 'tag() and descendants(x)' или 'tag() and x::' (где x — идентификатор коммита). То есть, если выполнить hg log 'tag() and x::', мы увидим все искомые релизы. Подробная информация о синтаксисе и всех имеющихся функциях — hg help revsets или на официальном сайте.

filesets



Filesets представляет собой также язык запросов, аналогичный revsets, но для задания файлов (для соответствующих команд, которые работают с файлами). Используется он почти аналогично, только в начале нужно добавлять set:, чтобы не было путаницы с обычными именами файлов. Что касается поддерживаемых функций, то они также есть в стадартной помощи: hg help filesets.

Changeset Evolution



Расширение evolve — экспериментальное, которое сейчас разрабатывает (в основном) один из членов команды Mercurial. Оно экспериментальное из-за пока ещё окончательно не решённых вопросов с UI и производительностью в некоторых случаях, а не из-за недостатка стабильности (вообще говоря, часть кода, связанного с его функциями, находится в самом Mercurial, но не работает по-умолчанию). В частности, это расширение используется в самом официальном репозитории Mercurial.

Changeset Evolution при подключение не только добавляет новые команды, но и изменяет поведение стандартных (и из других расширений) — тех, которые каким-либо образом редактируют историю: commit --amend, rebase, histedit и некоторые другие. При использовании evolve никакие коммиты полностью не удаляются из репозитория (за исключением команды strip, предназначенной как раз для полного удаления, которое всё же может пригодиться). Любое редактирование истории просто помечает более ненужные коммиты как удалённые (точнее, устаревшие — obsolete), а новые коммиты — как заменившие их. Таким образом, всегда можно найти любую версию изменения, которая когда-то раньше существовала.

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

Заключение



Вообще, в Mercurial есть и другие «продвинутые» возможности, но в этой статье я постарался описать те из них, которые могут пригодиться многим пользователям, и которыми люди не пользуются часто из-за незнания. Также хотелось бы добавить, что в Mercurial очень строгая политика обратной совместимости — все вносимые изменения не затрагивают имеющуюся функциональность, а добавляют новую. Очень старая версия на сервере может работать с новым клиентом, и наоборот (разумеется, неподдерживаемые в старой версии функции работать не будут). Такая серьёзная обратная совместимость касается всех команд и функций, видимых пользователю, то есть внутреннее API может меняться (но без весомых причин этого тоже не делают).

Сам я использую Mercurial на базовом уровне уже несколько лет, а в этом году участвую в Google Summer of Code с проектом улучшения hgweb. Попутно, общаясь с разработчиками, узнал и начал использовать в частности описанные в этой статье функции.
Александр Плавин @chersanya
карма
45,0
рейтинг 0,1
Исследователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (50)

  • 0
    Удивлен не найдя в списке mq. Вместе с patchbomb, одно из ежедневно используемых у меня и коллег.

    • 0
      MQ считается устаревающим, в том числе самими разработчиками. Книга эта, кстати, тоже достаточно давно не обновлялась. Я полный набор его функций не знаю — не использовал — но говорят что он полностью заменяется более новыми и удобными инструментами, такими как histedit, rebase, [c]record, evolve. Что касается patchbomb — оно всё-таки более узкоспециализировано и думаю те, кому нужно, сами могут найти по соотвестсвующему запросу (а так — оно тоже используется напрямую в разработке самого Mercurial).
      • 0
        >>MQ считается устаревающим, в том числе самими разработчиками
        Это почему же? К тому же прошу привести ссылку на слова разработчиков
        • 0
          Официальных заявлений нет, т.к. пока ещё (без законченного evolve) окончательной и полной альтернативы не существует. Однако, вот некоторые фрагменты (найдены простым поиском по логам, первые попавшиеся) переписки разработчиков на канале #mercurial в IRC. При желании можно ещё найти, конечно.

          А к вопросу «почему» — видимо, из-за неудобного/неинтуитивного интерфейса (опять же, по сравнению с другими командами). Я сам ни разу не пользовался MQ, сразу стал использовать более новые расширения для аналогичных целей. А вы сами какие конкретно операции выполняеете с помощью MQ?
          • +1
            Я без MQ как без рук! Допустим сейчас поздний вечер, вы код не дописали, но пора спать. Есть два выбора: оставить рабочую папку в том виде какой она есть и надеятся что в след. раз вы вспомните результат своей работы, а можно сделать hg qnew <patch-name> и тогда он хоть и будет выглядеть как комит, но комитом являться не будет и его можно будет до-рефрешить(hg qrefresh) после завершения работы.
            Другой сценарий: сделал опечатку в сообщении комита, но еще не сделал hg push, тогда превращаю n-комитов в патчи, далее откатываю патчи hg qpop, чтобы на верху остался нужный мне патч, затем правлю сообщение патча, hg qrefresh и превращаю патчи обратно в комиты.

            Ну и ряд других сценариев, MQ это очень очень удобно!
            • 0
              Хм… а чем не нравится histedit? Тоже входит в стандартную поставку. Для первого случая — вы коммитите вечером как обычно (чтобы не забыть, приписав к сообщению коммита что он временный), потом утром просто его редактируете как угодно. Второй случай ещё проще — тот же histedit, выбираете нужный коммит и (безо всяких других лишних действий) редактируете сообщение — там есть такая отдельная функция. А с настроенным evolve это можно и после push :) (вообще и без evolve можно с некоторыми ухищрениями, но тогда это изменение будет только локальным).

              Попробуйте, судя по вашему описанию мне кажется будет удобнее :) И нет дополнительной сущности в виде патчей — всё в рамках обычных коммитов.
              • 0
                Я могу объединить два комита в один? Нет! А патчи да! ;) У меня прямо сейчас, до hg push все отцепляется в ветку и делается в виде патчей! Это удобно тем что больше простору, быстрее откатить, получить новые из trunk и накатить снова и получается что мне меньше возиться при мерже с trunk и меньше линий в древе веток, глаза не мылятся! ;)
                • 0
                  Я могу объединить два комита в один? Нет!

                  Эм… Почему? Я же написал, используйте histedit — хоть объединить, хоть разделить. А что именно вы имете в виду под trunk? Насколько я помню, такой термин есть в svn.
                  • 0
                    В команде всегда есть некая главная ветка из которой можно взять и делать чуть ли не релиз прямо сейчас. В идеале она всегда находится в адекватном состоянии. Но на практике главная ветка ломается после мержей с другими ветками в которых велись работы по новой фиче, рефакторингу или баг-фиксу. Вот именно эту ветку и называю trunk. Другое удачное название release-brunch.

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

                    Я же дроблю еще дальше, если интересно опишу.
                    • 0
                      В команде всегда есть некая главная ветка из которой можно взять и делать чуть ли не релиз прямо сейчас. В идеале она всегда находится в адекватном состоянии. Но на практике главная ветка ломается после мержей с другими ветками в которых велись работы по новой фиче, рефакторингу или баг-фиксу. Вот именно эту ветку и называю trunk. Другое удачное название release-brunch.


                      «stable»? :) Коротко и ясно. А теги многие (если не все) используют для маркировки релизов, самое очевидное и удобное решение.
                      • 0
                        Ну по сути да, но не совсем! Есть множество разработчиков кто разделяет stable от current. Я же не делю! Говоря trunk я имею ввиду одну stable, но которая в результате мержей иногда превращается в current. Но этот подхдод не везде используется. К примеру, у нас в компании есть trunk, другое удачное название developer-branch, который очень часто ломается, что-то не до конца работает, вообщем я ее называю bugs-stream-branch. С течением времени от нее отцепляется очередная ветка и она называется release-_ и такое решение используется достаточно часто, а не только в нашей компании
          • 0
            Мы работаем с сериями патчей. Серия патчей — это основной этап разработки, это также конечный результат всей разработки — получить серию патчей для ревью.

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

            неудобного/неинтуитивного интерфейса (опять же, по сравнению с другими командами)
            Удивлен. Чтобы освоить mq мне хватило чтения короткого туториала и далее иногда hg help mq. И оно не требует каких-то дополнительных знаний о том, как устроен mercurial, работа идет с привычным, простым и понятным инструментом — набором патчей.
            • 0
              Мне, как человеку не использовавшему MQ, сложно понять, чем это лучше обычных ветвлений в дереве репозитория :) Все операции, которые вы производите с патчами и сериями, можно почти напрямую перенести на операции с коммитами и ветками (я имею в виду обычные ветки, не именованные). Попробуйте, может быть тоже окажется удобнее :)
              • +2
                Насколько я понимаю, единственное, чем MQ лучше технически — это возможностью переписывать историю на удалённом сервере. Evolve не зря назвали заменой MQ¹. К примеру, автор Vim никогда не принимает изменения из другого репозитория, всегда только патчи. MQ позволяет их удалить после принятия. Правда, я всё равно предпочитаю обычные ветки, несмотря на производимый в результате бардак.

                ¹ Evolve: A robust alternative to MQ
                • 0
                  Да, скорее всего именно так, поэтому сейчас evolve пилят несколько человек из команды, как я понимаю.
              • +1
                MQ полезен тем, что позволяет не афишировать без необходимости т.н. творческие метания (назвал переменную сначала как попало, потом придумал более подходящее имя), которые не совсем к месту в публичной истории. При этом позволяет легко переключаяться между несколькими задачами. Плюс метаниями таки можно поделиться при необходимости.
                • 0
                  Я же не спорю, что кому-то, особенно тем привык к MQ, кажется удобнее пользоваться им. Однако, повторюсь, все операции можно делать напрямую с коммитами, без патчей! Да, все, в том числе, то что вы написали: исправление названия переменной — редактирование коммита, переключение между задачами (тут я вообще не понял, зачем MQ, ведь даже редактирования истории нет) — несколько обычных веток в графе репозитория. Я не уговариваю никого использовать другие методы, но всё-таки, как по мне, они удобнее чем MQ.
                  • 0
                    тут я вообще не понял, зачем MQ, ведь даже редактирования истории нет
                    оно и не нужно — правите файло, потом hg qrefresh
                    • 0
                      Я немного о другом: для переключения между задачами достаточно просто иметь несколько веток и спокойно переключаться с помощью hg up.

                      В общем, я думаю все уже поняли, что есть два альтернативных метода и каждый использует то, что ему удобнее. Тем, кто начинал когда альтернатив не было и был только MQ (или же тем, кто начал с прочтения книги) могу только посоветовать попробовать более новый метод, возможно он покажется удобнее.
                      • 0
                        Evolve пока «нету»: сами авторы говорят, что оно недопилена, и bitbucket пока не поддерживает.

                        Кроме того, непонятно зачем, но evolve также не разрешает изменять коммиты, отмеченные как «публичные». Учитывая, что история реально никуда не девается и есть способ автоматического исправления проблем, это странно.
                        • 0
                          В сообщении, на которое вы отвечаете, про evolve ничего нет, и он не является необходимым для редактирования истории (а даёт дополнительные функции и удобства).

                          Вообще, хоть evolve пока и не окончателен, но ользоваться им можно спокойно (разработчики mercurial так и делают). А битбакет и другие хостинги действительно не поддерживают evolve, но не думаю что это такая уж проблема — на своём сервере можно включить что угодно :)

                          Публичные коммиты (с фазой public) «by design» нельзя редактировать, а evolve не может так просто добавить эту функцию из-за обратной совместимости с серверами где он выкючен. Если вы хотить менять отправленные на сервер, то поставьте в настройках на нём [phases] publish=False.
                • 0
                  Остается только вызов редактора текста приделать ;) И авто-рефакторинг во всех последующих комитах сверху, где то или иное слово упоминается )
      • +1
        Вообще-то, mpm им пользуется, так что не знаю, что и где устарело. Просто начинающим юзерам не стоит с ним играться, да.
  • 0
    Кстати, функция выборочного включения изменений в коммит в пределах файла поддерживается теперь и в TortoiseHg (начиная с версии 2.7)
  • 0
    Спасибо за статью. Скажите пожалуйста, в меркуриале есть аналог операции git rebase -i? Который позволял нормально бы причесать ветку перед отправкой.
    • 0
      В git я знаю только самые основные операции и не пользовался rebase -i, но предположу, что это некоторое редактирование истории. Тогда посмотрите на расширения (которые в комплекте, нужно просто включить): rebase для перемещения набора коммитов «поверх» другого, и histedit для всего остального (редактирование одиночных коммитов, свёртка нескольких в один, переупорядочивание, удаление). Ну и для удобства, но это опционально, можно включить упомянутый в статье evolve — он влияет на все команды, меняющие историю.
      • 0
        Ясно, спасибо. Судя по описанию, git rebase -i как раз соответствует hg histedit
        • +1
          У git всё же лучше интерфейс в этом плане: в mercurial нет fixup и exec, раньше не было reword; и histedit требует указания drop для удаляемых изменений, тогда как git обходится обычным удалением строки, что быстрее. Ещё histedit вызывает редактор для каждой строчки fold (squash из git), тогда как git обходится одним вызовом редактора на каждую серию squash/fixup (кажется, за исключением когда по пути встретились конфликты (если в дополнение к squash изменения были перемещены), но за это не поручусь). Ну и нельзя одной командой и переместить изменения, и изменить их порядок следования.

          Одну вещь всё же хорошо придумали: названия всех действий занимают ровно четыре (или один) символа, так что можно использовать режим замены в редакторе.
          • +2
            histedit требует указания drop для удаляемых изменений, тогда как git обходится обычным удалением строки, что быстрее

            Эта необходимость указывать символ «d» для удаления отлично помогает от случаев, когда переставлял несколько коммитов и какую-то строчку случайно удалил или забыл вставить. У меня несколько раз точно такое бывало. Да и удаление строки не сказал бы что быстрее :)

            в mercurial нет fixup и exec


            fixup это же просто fold, как написано в документации, только сообщение одного из коммитов игнорится? Кейсов для использования exec я что-то не смог представить, приведите пару примеров. Mercurial хорошо поддаётся различному расширению функциональности, поэтому если это реально полезная фича, думаю её добавят.

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

            Это я что-то вообще не понял. Изменение порядка коммитов это же по сути и есть перемещение части из них?

            Кстати, удобная возможность в Mercurial: в конфиге можно сделать алиасы типа hg edit <rev>, hg medit <rev> для редактирования коммита и изменения сообщения соответственно. Если нужно исправить один коммит, то это получается удобнее т.к. не нужно ещё в текстовом редакторе писать операцию, как при обычном histedit.
            • 0
              Эта необходимость указывать символ «d» для удаления отлично помогает от случаев, когда переставлял несколько коммитов и какую-то строчку случайно удалил или забыл вставить. У меня несколько раз точно такое бывало. Да и удаление строки не сказал бы что быстрее :)
              Я в этом отношении более аккуратен, потому и имею другое мнение.
              fixup это же просто fold, как написано в документации, только сообщение одного из коммитов игнорится?
              Да.
              Кейсов для использования exec я что-то не смог представить, приведите пару примеров. Mercurial хорошо поддаётся различному расширению функциональности, поэтому если это реально полезная фича, думаю её добавят.
              Use-case для exec я тоже не знаю, но зачем‐то же он есть в git. То, что я могу представить проще и безопаснее делать без exec.
              Это я что-то вообще не понял. Изменение порядка коммитов это же по сути и есть перемещение части из них?
              Я имею ввиду, что A-{B-C,D-E} можно превратить одной git rebase -i в A-B-C-E-D, тогда как с mercurial вам придётся сначала делать A-B-C-D-E (или A-{B-C,E-D}), а потом уже только A-B-C-E-D: histedit не делает rebase.
            • 0
              А удаление vs drop — это dd (в любой части строки) vs Rdrop^[ или cwd^[ (но только в начале строки, то есть прибавляется ещё и команда на переход в начало строки) (вместо ^[ подставить ESC). Согласитесь, первое гораздо быстрее остального.
              • 0
                Ничего не понял, но предполагаю что это клавиатурные сочетания в каком-то консольном редакторе типа vim :) В обычных GUI-редакторах что удалить строку, что заменить первое слово на «d» по сути одинаково.
                • 0
                  Это клавиатурные сочетания из Vim.

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

                  Относительно лёгкости:

                  В nano (ещё один относительно стандартный консольный редактор, но без поддержки режимов) с этим делом примерно так же (одно <C-k> для удаления против многоклавиш (вероятно, легче всего <C-d><C-d><C-d><C-d>d) для замены).

                  В mcedit удаление одной строки на <C-y>, замена потребует больше клавиш (вероятно, наиболее простыми является либо <INS>drop, либо то же, что и у nano).

                  В gedit (GUI!) есть сочетание <C-d> для удаления всей строки. Для замены на drop вероятно легче всего использовать <C-S-Right>d.

                  В sublime (GUI!) судя по этой статье есть <C-k><C-k> для удаления до конца строки (т.е. курсор должен быть в начале) и <C-DEL>d для замены первого слова на d (замечу, что клавиша DEL несколько дальше k и потому первое набирается значительно быстрее).

                  В kate (GUI!) можно «удалить» строчку <C-d> (на самом деле осуществляет комментирование, если судить по этой PDF’ке). Считается, что kate знает, что такое «комментарий» в файле от git rebase. Если нет то, см. следующий абзац.

                  В любом редакторе можно «удалить» строчку путём написания одного символа #: git воспринимает такие строчки как удалённые.

                  Во всех примерах предполагается нахождение курсора в начале строки. Во многих примерах расположение курсора абсолютно не важно для удаления строки (верно если не указано обратное). Во всех примерах расположение курсора важно для замены слова.

                  Так что либо я не понимаю как в GUI редакторах быстро заменить одно слово на другое, либо ни о каком «по сути одинаково» речи быть не может. Замечу, что перемещение кисти куда‐либо с основной позиции слепой печати — операция заведомо более дорогая, чем нажатие дополнительных одной‐двух‐трёх (зависит от вашей скорости печати) клавиш, особенно если они расположены под разными руками.
                  • 0
                    Использование GUI (в том числе GUI редакторов) подразумевает использование мыши (и одна рука обычно там уже находится). Таким образом, замена первого слова на «d»: двойной клик по этому слову и нажатие «d». Удаление строки: клик по строке и клавиатурное сочетание для удаления строки, которое точно не будет состоять из одной клавиши (кстати, ни разу не пользовался; в частности, узнал из вашего комментария что в Sublime, основном редакторе у меня, нет такого сочетания). Замечу, что постановка "#" в начале заведомо сложнее: нужно поместить курсор именно перед первым символом, и нажать Shift+3.

                    А вообще, зачем всё это обсуждение таких небольших различий в скорости выполнения действия, которое обычно делается достаточно редко (например, реже чем hg ci/git commit)? Ну вот выяснили вы, что в некоторых случаях удобнее удалить строку, а в некоторых — поставить «d» в начале, и что?
                    • 0
                      Если бы оно выполнялось часто, то я бы говорил про редакторы с расширениями и, соответственно, одну или две клавиши на действие. А так это просто мелкое неудобство, которого могло бы не быть.

                      Относительно мыши: если вы использовали git rebase -i из командной строки то рука вероятно не находилась на мыши. В этом случае, даже стрелочки + <Home>/<End> будут быстрее, чем заново искать основную позицию для правой руки (programming dvorak) после использования мыши: в отличие от позиций клавиш дополнительных блоков клавиатуры месторасположение мыши не фиксировано относительно основного блока. С us правда e[dit], f[old] и d[rop] на левой руке, только m[ess] (и p[ick]) нет, с git вообще все действия на ней (кроме p[ick], но последнее уже написано в обоих случаях), но перемещение руки на мышь всё равно остаётся более дорогим действием, чем перемещение на дополнительный блок, а <S-Home>/<S-End> — более быстрым, чем выделять мышью (если только не поддерживается тройное нажатие).

                      Постановка в начале не сложнее, потому что можно использовать клавишу <Home>.

                      И ещё, я категорически не понимаю, как использование редактора описанным вами способом сочетается с возможностью случайного удаления строки. Разве что разбирательства с перемещением курсора для последующей вставки отвлекают от самой задачи перемещения строки в нужное место настолько и занимают такое время, что за это время можно успеть получить сигнал (электронное письмо, кто‐то подошёл и т.д.), отвлечься на него и забыть про производимую операцию вообще. Я никогда не удалял случайно строчки именно по этой причине: dd или любое другое сочетание со схожим действием нажать ненамеренно проблематично, а за время перемещения строки в другое место я просто не успеваю отвлечься, чтобы потерять её.

                      Кстати, во многих программах выделение всей строки можно произвести тройным кликом.

                      А вообще, зачем всё это обсуждение таких небольших различий в скорости выполнения действия, которое обычно делается достаточно редко (например, реже чем hg ci/git commit)? Ну вот выяснили вы, что в некоторых случаях удобнее удалить строку, а в некоторых — поставить «d» в начале, и что?
                      Ничего. Ваш изначальный комментарий, ваш ответ и мой ответ на ваш ответ (считать те два мои комментария одним, я просто не успел отредактировать) были гораздо шире и касались более важных вещей. Но на следующем ответе вы уже коснулись только быстроты предпринимаемых действий и я просто продолжил доказательство тезиса, сомнение в котором было вами высказано. В данном случае — что удаление строки быстрее в любом редакторе.
                      • 0
                        Я ваше мнение понял, а вы никак не хотите признать что такое использование текстовых редакторов (перемещение клавишами) удобнее не для всех. Мне, например, намного удобнее и привычнее (соответственно, быстрее) указать позицию в редакторе мышью, чем идти к ней стрелками или смотреть точное число строк на сколько надо перейти. Поэтому, хотя при наборе команды в командной строке рука обычно не на мыши, потом для редактирования появившегося файла её в любом случай надо перенести на мышь. Странно, что дело вкуса и (даже больше) привычки вы пытаетесь рассматривать как «тезис», для которого возможно доказательство :)

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

                        Вырезал (в смысле Ctrl+X, а не удалил) строчку, стал смотреть по графу куда надо вставить, отвлёкся на перемещение другого коммита, про первый забыл (так у меня раз было).

                        Но на следующем ответе вы уже коснулись только быстроты предпринимаемых действий

                        Остальная часть вашего комментария — это факты, которые и так понятно что верны, и смысла их обсуждать нет:
                        — fixup — то же, что и fold, но учитывает только одно сообщение коммита
                        — use-case'ов для exec мы оба не знаем
                        — git rebase -i может одновременно делать rebase (кстати, по-хорошему это единственное, что должна делать команда называющаяся rebase — это уже от меня) и изменение порядка.
                        • 0
                          Я ваше мнение понял, а вы никак не хотите признать что такое использование текстовых редакторов (перемещение клавишами) удобнее не для всех. Мне, например, намного удобнее и привычнее (соответственно, быстрее) указать позицию в редакторе мышью, чем идти к ней стрелками или смотреть точное число строк на сколько надо перейти. Поэтому, хотя при наборе команды в командной строке рука обычно не на мыши, потом для редактирования появившегося файла её в любом случай надо перенести на мышь. Странно, что дело вкуса и (даже больше) привычки вы пытаетесь рассматривать как «тезис», для которого возможно доказательство :)
                          Тезис — не удобство. Тезис — скорость. Я очевидно не смогу доказать, что всем удобнее было бы не использовать мышь в таких случаях. Даже я сам бы с этим не согласился, вспомнив о том, что использовал до изучения Vim. Но можно показать, что неиспользование мыши будет быстрее.

                          Кроме того, сравнивать скорости до возникновения привычки бесполезно. Но после её возникновения скорость ограничивается в первую очередь физически. Мышь+клавиатура может быть быстрее стрелочек, если изменений очень много. Она не может быть быстрее Vim при знании способов перемещения в любом случае и не может быть быстрее стрелочек при достаточно малом числе изменений (если их где‐то десяток и меньше). Впрочем, я всё равно не считаю стрелочки удобнее мыши и не считаю мышь удобнее навигации в Vim. Мышь также будет быстрее, если рука уже лежит на ней.
                          Вырезал (в смысле Ctrl+X, а не удалил) строчку, стал смотреть по графу куда надо вставить, отвлёкся на перемещение другого коммита, про первый забыл (так у меня раз было).
                          Понятно. У меня просто другой порядок действий: сначала смотрю, куда перемещать, потом уже выполняю перемещение. Соответственно к моменту удаления решение уже принято. Как‐то не подумал, что может быть иначе: зачем удалять строчку, если неизвестно надо ли удалять её вообще (может, проще переместить другую)? Да и в части случаев (именно в это время мною обычно используется fixup) я знаю, что с чем буду объединять ещё до фиксации изменения (ещё плюс git: наличие autosquash).
                          Остальная часть вашего комментария — это факты, которые и так понятно что верны, и смысла их обсуждать нет:
                          Можно было их дополнить (тем же autosquash). Или обсудить необходимость возможности histedit также делать rebase (я считаю это удобным, так как не придётся решать конфликты по два раза (из‐за rebase и из‐за изменения порядка; конфликты разные) в худшем случае, но аргументы против я тоже могу представить).
                          • 0
                            Тезис — не удобство. Тезис — скорость. Я очевидно не смогу доказать, что всем удобнее было бы не использовать мышь в таких случаях. Даже я сам бы с этим не согласился, вспомнив о том, что использовал до изучения Vim. Но можно показать, что неиспользование мыши будет быстрее.

                            Нет, не будет. Быстрее то, к чему привык, а для привыкшего к использованию мыши совместно с клавиатурой будет быстрее именно использование мыши. Редактирование только с клавиатуры в этом случае медленнее, т.к. является менее привычным действием. Разумеется, для тех кто привык к клавиатурным сочетаниям и редакторам типа vim, будет быстрее обратное, и вполне возможно, что это будет даже быстрее чем у пользователей gui-редакторов.

                            Я сам думал о том, чтобы начать повсеместно использовать vim, видя как некоторые преподы у нас быстро и (на вид) удобно им редактируют файлы, но привычка перевесила это желание :) Тем более, что непосредственно набор кода/текста — занимает относительно небольшую часть времени.

                            Относительно rebase. Бегло просмотрев документацию, я не совсем понял как происходит собственно rebase. Вот например есть дерево A-{B-C,D-E} и мы хотим сделать A-B-D-E-C. Как достичь этого?
                            • 0
                              Нет, не будет. Быстрее то, к чему привык, а для привыкшего к использованию мыши совместно с клавиатурой будет быстрее именно использование мыши.
                              Будет. Я говорю о скорости способа, а не скорости вас настоящего, который может им воспользоваться. При длительном использовании нового способа возникнет новая привычка. Скорость исполнения имеет смысл сравнивать только с учётом её возникновения и по прошествии некоторого времени. А чтобы не делать такое сравнение чисто экспериментальным — надо исходить из расстояний, на которые перемещаются кисти и пальцы и времени на бессознательный поиск новой позиции.
                              Я сам думал о том, чтобы начать повсеместно использовать vim, видя как некоторые преподы у нас быстро и (на вид) удобно им редактируют файлы, но привычка перевесила это желание :) Тем более, что непосредственно набор кода/текста — занимает относительно небольшую часть времени.
                              У sublime есть Vim-mode, vintage mode или что‐то в этом роде. У самого Vim есть большое количество проблем, связанных с исторически допущенными архитектурными просчётами либо же являющихся данью обратной совместимости (а то и тем, и другим сразу). Насколько я знаю в sublime можно запихать фактически что угодно, что поддерживает Vim, причём написать всё на Python, в Vim добавление части возможностей того же sublime (к примеру, поддержка <C-S-Key> или <C-Key> для не‐ASCII и некоторых ASCII символов) требует неплохого знания C, а то и вдобавок желания провести refactoring.
                              Относительно rebase. Бегло просмотрев документацию, я не совсем понял как происходит собственно rebase. Вот например есть дерево A-{B-C,D-E} и мы хотим сделать A-B-D-E-C. Как достичь этого?
                              У вас другой пример, я ответа на него не знаю. Точнее знаю, но это те же две команды¹, что и с mercurial (вариантов несколько, но все требуют как минимум две команды). В моём (A-{B-C,D-E} → A-B-C-E-D) — это та же команда (git rebase master, предполагая, что E — текущая ветка, а C — master), к которой просто добавили --interactive. Останавливаться именно на таком варианте (не прося изменить ветку, на которую происходит перенос той же командой) обычно имеет смысл, так как у меня чаще всего A-B-C — публичная master и менять её категорически не рекомендуется, а D-E, которую хочется превратить в E-D — feature branch. Соответственно, превращать A-B-C в A-B-D-E-C не нужно или даже невозможно (не примет upstream).

                              ¹ Две команды:
                              • hg rebase --source D --dest B && hg rebase --source C --dest E (можно использовать намного меньше символов, но так понятнее)
                              • hg rebase --base E --dest C && hg histedit -r B
                              В данном контексте --source D и --base E (а также --rev D..E) эквивалентны. Git использует только --base (за исключением формы git rebase --onto master topicA topicB, эквивалентной hg rebase --rev 'topicA..topicB - topicA' --dest master).
  • 0
    Делить изменения на несколько коммитов можно в thg, причём уже очень давно.
    Для этого открываем «долгий ящик» — и вот там можно как раз выделять не только файлы целиком, но и отдельные лоскуты. И, соответственно, что-нибудь с ними делать. Например, тащим всё в ящик, кроме содержимого для первого коммита. Коммитаем. Тащим из ящика содержимое для второго коммита — и т.д.
    Единственный недостаток — лоскуты считаются в стандартном контексте (3 строки). Т.е. две подряд идущие строки стандартно считаются одним лоскутом, и стал быть неделимы.
  • +1
    Странно, что пропустили extension graphlog, а ведь без него графы коммитов не посмотреть.
    • +1
      Про графических лог в командной строке (и в hgweb кстати) действительно забыл упомянуть, но расширений никаких не надо, просто нужно выполнить hg log -G (начиная с версии 2.3, а сегодня кстати выходит 2.7 по плану). Цитата из вики Mercurial:
      As of Mercurial 2.3, log supports -G without any extensions. The included graphlog extension merely adds glog as an alias to log -G.
      • +1
        Да, но в Ubuntu 13.04, например, в репах ещё версия 2.2
  • 0
    Есть еще отличный (хоть и устаревший) экстеншн KeywordExtension, пользуюсь регулярно.
    • 0
      А для чего вы его используете? Я как-то для себя не понял, где можно применить.
    • 0
      Про него, кстати, написано, что оно «feature of last resort» (т.е. последнее, что стоит использовать, только если других вариантов нет). Туда же, правда, записаны и любимые в git подрепозитории (subrepositories) (в git называются submodules), и largefiles.
  • 0
    Кстати, вот гитоводы жалуются, что в Mercurial якобы нету приватных веток. Ну то есть накоммитили вы всего в «свою ветку», потом такой hg push, а оно возьми и вылейся на общее обозрение. А ведь всего делов-то почитать мануал по вгитененужным phases да выставить коммиту фазу secret либо во время коммита (hg --config='phases.new-commit=secret' commit ...), либо после коммита (hg phase --secret --force --revision=<revset>).
    • +2
      Начиная с версии 2.7, которая вышла 1 августа, можно делать просто hg commit --secret :)
      • 0
        вообще замечательно

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