== Tutorial - Слияние изменений == ''(Это 7-я из 9-ти частей[[RussianTutorial|Tutorial]]. Предыдущая - [[RussianTutorialExport]], следующая - [[RussianTutorialConflict]])'' В главе [[RussianTutorialExport]] мы разобрались, как передать изменения кому-нибудь. В этой части мы собираемся рассмотреть [[Merge|слияние]] различных [[Pull|подтянутых]] изменений из другого [[Repository|репозитория]]. Во-первых, мы должны создать то, что собираемся объединять. Снова [[Clone|клонируем]] репозиторий `my-hello`: {{{ $ cd .. $ hg clone my-hello my-hello-desc updating working directory 2 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} Мы собираемся добавить описание в раздел коментариев файла `hello.c`. {{{ $ cd my-hello-desc $ vi hello.c }}} Отредактируем вторую строчку, чтобы из этого: {{{ * hello.c }}} получилось следующее: {{{ * hello.c - hello, world }}} Сохранив, выходим из редактора и [[Commit|фиксируем]] наши изменения. На этот раз мы экономим время, используя опцию `-m` команды `commit`, избавляющую нас запуска редактора: {{{ $ hg commit -m "Add description of hello.c" }}} На этой стадии мы внесли одно изменение в `hello.c` репозитория `my-hello-new-output`, и другое изменение в `hello.c` репозитория `my-hello-desc`. Как мы можем объединить эти два различных направления разработки? Возникнут ли проблемы, если мы захотим перенести одну в другую? Это получится отлично. Находясь в `my-hello-desc,` давайте подтянем изменения из `my-hello-new-output` и посмотрим, что произойдёт: {{{ $ hg pull ../my-hello-new-output pulling from ../my-hello-new-output searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) }}} Mercurial говорит, что он добавил дополнительный [[Head|head]] в наш репозиторий. Посмотреть head'ы мы можем командой `heads`: {{{ $ hg heads changeset: 3:86794f718fb1 tag: tip parent: 1:82e55d328c8c user: mpm@selenic.com date: Mon May 05 01:20:46 2008 +0200 summary: Express great joy at existence of Mercurial changeset: 2:c3844fde99f0 user: mpm@selenic.com date: Tue May 06 20:10:35 2008 +0200 summary: Add description of hello.c }}} Mercurial поставляется с замечательным [[UsingExtensions|расширением]], отображающим историю репозитория в виде ASCII графа: GraphlogExtension. Все, что вам нужно сделать, чтобы оно заработало - это разрешить его в вашем файле `~/.hgrc` (или `Mercurial.ini` в Windows), добавив строчку {{{hgext.graphlog = }}} в секцию `[extensions]` как здесь: {{{ [extensions] hgext.graphlog = }}} Когда вы это сделаете, станет доступна дополнительная команда `glog` (см. также `hg help glog`): {{{ $ hg glog o changeset: 3:86794f718fb1 | tag: tip | parent: 1:82e55d328c8c | user: mpm@selenic.com | date: Mon May 05 01:20:46 2008 +0200 | summary: Express great joy at existence of Mercurial | | @ changeset: 2:c3844fde99f0 |/ user: mpm@selenic.com | date: Tue May 06 20:10:35 2008 +0200 | summary: Add description of hello.c | o changeset: 1:82e55d328c8c | user: mpm@selenic.com | date: Fri Aug 26 01:21:28 2005 -0700 | summary: Create a makefile | o changeset: 0:0a04b987be5a user: mpm@selenic.com date: Fri Aug 26 01:20:50 2005 -0700 summary: Create a standard "hello, world" program }}} В этом графе вы можете увидеть, что мы просто подтянули changeset `86794f718fb1` (который теперь является [[Tip|tip'ом]]) в наш репозиторий . Так как оба changeset'а: и подтянутый `86794f718fb1`, и наш `c3844fde99f0`, имеют одного [[Parent|родителя]] `(82e55d328c8c)`, то можно сказать, что были созданы две различные линии разработки, называемые ветками ([[Branch|branch]]). Заметим, что в данном случае ветка недолговечна и это раздвоение легко разрешается Mercurial'ом. Глядя на вывод `pull`, можно подумать, что он похож на пример из RussianTutorialShareChange. Вы можете спросить: почему бы просто не делать [[Update|обновление]] так же, как мы это сделали в RussianTutorialShareChange? Давайте попробуем и посмотрим, что произойдёт: {{{ $ hg update abort: crosses branches (use 'hg merge' or 'hg update -C') }}} Здесь явно что-то не так. Как вы можете заметить, Mercurial предостерегает нас от откровенных глупостей, и если мы упустим упоминание "(+1 heads)" в сообщении после команды `pull`, то можем быть уверены - Mercurial напомнит нам, что мы, вероятно, хотели сделать что-то другое: объединение (merge). Но перед тем, как мы приступим к нашему первому объединению, давайте проверим, с каким changeset-ом мы сейчас синхронизированы. Для этого мы можем воспользоваться командой `parents` (см. [[Parents]]): {{{ $ hg parents changeset: 2:c3844fde99f0 user: mpm@selenic.com date: Tue May 06 20:10:35 2008 +0200 summary: Add description of hello.c }}} Это говорит о том, что содержимое нашего [[WorkingDirectory|рабочего каталога]] пока синхронизировано с changeset'ом `c3844fde99f0` – это то, что мы недавно комитили. Важно понимать, что ''pull'' подтянул другие изменения из ''хранилища'' нашего репозитория. Подтягивание не меняет ничего в нашем рабочем каталоге. И взгляните ещё раз на вывод команды `glog`: один changeset помечен символом "`@`". Это родительский changeset рабочего каталога: "`@`" возле `c3844fde99f0`. Давайте, наконец, обьединять. Вас это пугает? Это действительно очень просто. Давайте последуем предложению из последней строки вывода нашей предыдущей команды `pull:` {{{ $ hg merge merging hello.c 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) }}} Вот и всё! Mercurial выполнил объединение автоматически, потому что изменения не конфликтовали (объединение конфликтующих изменений рассматриваются в RussianTutorialConflict). Если сейчас посмотреть `содержимое hello.c` в рабочем каталоге, мы найдём оба изменения: и из `my-hello-new-output`, и из `my-hello-desc`. Когда работаешь с изменениями, сделанными другими людьми, в подавляющем большинстве случаев используется именно этот вид объединения. Очень часто всё даже проще, потому что файлы, меняющиеся в различных направлениях разработки, обычно различны. Поэтому, в большинстве случаев объединения, вообще не будет каких либо ''файлов'' для объединения. Мы ещё не закомитили результаты объединения. Прежде чем сделать это, давайте посмотрим, что нам скажет команда `parents` (сокращённая до `par`): {{{ $ hg par changeset: 2:c3844fde99f0 user: mpm@selenic.com date: Tue May 06 20:10:35 2008 +0200 summary: Add description of hello.c changeset: 3:86794f718fb1 tag: tip parent: 1:82e55d328c8c user: mpm@selenic.com date: Mon May 05 01:20:46 2008 +0200 summary: Express great joy at existence of Mercurial }}} Это значит, что рабочий каталог базируется на ''двух'' changeset'ах: у него два родителя. Заметьте, что порядок родителей имеет значение: первый родитель (parent 1) это изначальный changeset `3844fde99f0`, в который мы добавили описание в коментарий `hello.c`. Он был текущим родителем, когда мы ввели команду `merge`. Второй родитель (parent 2) - это changeset `86794f718fb1`, который мы подтянули из другого репозитория и с которым мы и объединяли. Сейчас `glog` покажет знак `@` у двух родителей: {{{ $ hg glog @ changeset: 3:86794f718fb1 | tag: tip | parent: 1:82e55d328c8c | user: mpm@selenic.com | date: Mon May 05 01:20:46 2008 +0200 | summary: Express great joy at existence of Mercurial | | @ changeset: 2:c3844fde99f0 |/ user: mpm@selenic.com | date: Tue May 06 20:10:35 2008 +0200 | summary: Add description of hello.c | o changeset: 1:82e55d328c8c | user: mpm@selenic.com | date: Fri Aug 26 01:21:28 2005 -0700 | summary: Create a makefile | o changeset: 0:0a04b987be5a user: mpm@selenic.com date: Fri Aug 26 01:20:50 2005 -0700 summary: Create a standard "hello, world" program }}} /!\ Заметьте, что если вы передумали и хотите отменить это объединение перед тем, как что-то закомитить, просто выполните `hg revert -r2 --all. Это` вернёт файлы в рабочем каталоге в состояние ревизии 2, но __не изменит количество родителей обратно с двух на одного__ (см. [[Revert]]). Либо вам придётся выполнить "`hg update -C -r.`", чтобы отменить объединение и вернуть рабочий каталог к состоянию с одним родителем. Для завершения процедуры слияния мы должны не забыть закомитить [[LocalModifications|локальные изменения]], о чём нам и напоминают в последней строке вывода предыдущей команды `merge`: {{{ $ hg commit -m "Merged changes from my-hello-new-output" }}} Эта команда не должна ничего выводить. Теперь объединение зарегистрировано в репозитории как новый [[MergeChangeset|merge changeset]] и `glog` нам это покажет: {{{ $ hg glog @ changeset: 4:d2ecac0134d8 |\ tag: tip | | parent: 2:c3844fde99f0 | | parent: 3:86794f718fb1 | | user: mpm@selenic.com | | date: Tue May 06 23:44:19 2008 +0200 | | summary: Merged changes from my-hello-new-output | | | o changeset: 3:86794f718fb1 | | parent: 1:82e55d328c8c | | user: mpm@selenic.com | | date: Mon May 05 01:20:46 2008 +0200 | | summary: Express great joy at existence of Mercurial | | o | changeset: 2:c3844fde99f0 |/ user: mpm@selenic.com | date: Tue May 06 20:10:35 2008 +0200 | summary: Add description of hello.c | o changeset: 1:82e55d328c8c | user: mpm@selenic.com | date: Fri Aug 26 01:21:28 2005 -0700 | summary: Create a makefile | o changeset: 0:0a04b987be5a user: mpm@selenic.com date: Fri Aug 26 01:20:50 2005 -0700 summary: Create a standard "hello, world" program }}} Чтобы наглядно показать результаты изменений, выполненных при объединении, мы можем воспользоваться командой `annotate`, которая покажет changeset для каждой строки (в примере указаны локальные changesets -- ревизии). Обратите внимание, что 2-ая ревизия -- это наша модификация репозитория `my-hello-desc`, а 3-я ревизия -- это изменения, вытянутые из репозитория `my-hello-new-output` в репозиторий `my-hello-desc`. {{{ $ hg annotate hello.c 0: /* 2: * hello.c - hello, world 0: * 0: * Placed in the public domain by Bryan O'Sullivan 0: * 0: * This program is not covered by patents in the United States or other 0: * countries. 0: */ 0: 0: #include 0: 0: int main(int argc, char **argv) 0: { 0: printf("hello, world!\n"); 3: printf("sure am glad I'm using Mercurial!\n"); 0: return 0; 0: } }}} Как разобраться с ситуациями, когда случаются [[Conflict|конфликтующие]] изменения, мы узнаем в [[TutorialConflict]]. ---- CategoryTutorial CategoryRussian