Size: 12919
Comment:
|
Size: 15187
Comment: корректорские правки
|
Deletions are marked like this. | Additions are marked like this. |
Line 2: | Line 2: |
''(Это 7-я из 9-ти частей[:RussianTutorial:Tutorial]. Предыдущая - [:RussianTutorialExport], следующая - [:RussianTutorialConflict])'' В [:RussianTutorialExport] мы разобрались как передать изменения кому-нибудь. В этой части мы собираемся рассмотреть [:Merge:слияние] различных [:Pull:подтянутых] изменений из другого [:Repository:репозитория]. Во-первых, мы должны создать то что собираемся объединять. Снова [:Clone:клонируем] репозиторий `my-hello`: |
''(Это 7-я из 9-ти частей[[RussianTutorial|Tutorial]]. Предыдущая - RussianTutorialExport, следующая - RussianTutorialConflict)'' В главе RussianTutorialExport мы разобрались, как передать изменения кому-нибудь. В этой части мы собираемся рассмотреть [[Merge|слияние]] различных [[Pull|подтянутых]] изменений из другого [[Repository|репозитория]]. Во-первых, мы должны создать то, что собираемся объединять. Снова [[Clone|клонируем]] репозиторий `my-hello`: |
Line 15: | Line 14: |
Line 22: | Line 20: |
Отредактируем вторую строчку, что бы из этого: |
Отредактируем вторую строчку, чтобы из этого: |
Line 28: | Line 25: |
Line 34: | Line 30: |
Сохранив, выходим из редактора и [:Commit:фиксируем] наши изменения. На этот раз, мы экономим время, используя опцию `-m` команды `commit`, избавляющую нас запуска редактора: |
Сохранив, выходим из редактора и [[Commit|фиксируем]] наши изменения. На этот раз мы экономим время, используя опцию `-m` команды `commit`, избавляющую нас запуска редактора: |
Line 41: | Line 35: |
На этой стадии, мы внесли изменения в `hello.c` репозитория `my-hello-new-output`, и другие изменения в `hello.c` репозитория `my-hello-desc`. Как мы можем объединить эти два различных направления разработки? Возникнут ли проблемы, если мы захотим перенести одну в другую? Это получится отлично. Находясь в `my-hello-desc` давайте подтянем изменения из `my-hello-new-output` и посмотрим что произойдёт: |
На этой стадии мы внесли одно изменение в `hello.c` репозитория `my-hello-new-output`, и другое изменение в `hello.c` репозитория `my-hello-desc`. Как мы можем объединить эти два различных направления разработки? Возникнут ли проблемы, если мы захотим перенести одну в другую? Это получится отлично. Находясь в `my-hello-desc,` давайте подтянем изменения из `my-hello-new-output` и посмотрим, что произойдёт: |
Line 56: | Line 49: |
Mercurial говорит что он добавил дополнительный [:Head:head] в наш репозиторий. Посмотреть head'ы мы можем командой `heads`: |
Mercurial говорит, что он добавил дополнительный [[Head|head]] в наш репозиторий. Посмотреть head'ы мы можем командой `heads`: |
Line 74: | Line 65: |
Mercurial поставляется с замечательным [:UsingExtensions:расширением] отображающим историю репозитория в виде ASCII графа: [:GraphlogExtension]. Все, что вам нужно сделать, чтобы оно заработало это разрешить его в вашем файле `~/.hgrc` (или `Mercurial.ini` в Windows), добавив строчку {{{hgext.graphlog = }}} в секцию `[extensions]` как здесь: |
Mercurial поставляется с замечательным [[UsingExtensions|расширением]], отображающим историю репозитория в виде ASCII графа: GraphlogExtension. Все, что вам нужно сделать, чтобы оно заработало - это разрешить его в вашем файле `~/.hgrc` (или `Mercurial.ini` в Windows), добавив строчку {{{hgext.graphlog = }}} в секцию `[extensions]` как здесь: |
Line 80: | Line 69: |
hgext.graphlog = }}} Когда вы это сделаете станет доступна дополнительная команда `glog` (см. также `hg help glog`): |
hgext.graphlog = }}} Когда вы это сделаете, станет доступна дополнительная команда `glog` (см. также `hg help glog`): |
Line 109: | Line 97: |
В этом графе вы можете увидеть что мы просто подтянули changeset `86794f718fb1` (который теперь является [:Tip:tip'ом]) в наш репозиторий . Так-как оба changeset'а, и подтянутый `86794f718fb1` и наш `c3844fde99f0` были зафиксированы основываясь на одном [:Parent:родителе] `82e55d328c8c`, можно сказать, что были созданы две различные линии разработки, называемые ветками ([:Branch:branch]). Заметим, что в данном случае ветка не недолговечна и это раздвоение легко разрешается Mercurial'ом. Хотя глядя на вывод `pull`, можно подумать что он похож на пример из [:RussianTutorialShareChange]. Вы можете спросить: Почему бы просто не делать простое [:Update:обновление] также как мы это сделали в RussianTutorialShareChange? Давайте попробуем и посмотрим что произойдёт: |
В этом графе вы можете увидеть, что мы просто подтянули changeset `86794f718fb1` (который теперь является [[Tip|tip'ом]]) в наш репозиторий . Так как оба changeset'а: и подтянутый `86794f718fb1`, и наш `c3844fde99f0`, имеют одного [[Parent|родите]][[Parent|ля]] `(82e55d328c8c)`, то можно сказать, что были созданы две различные линии разработки, называемые ветками ([[Branch|branch]]). Заметим, что в данном случае ветка недолговечна и это раздвоение легко разрешается Mercurial'ом. Глядя на вывод `pull`, можно подумать, что он похож на пример из RussianTutorialShareChange. Вы можете спросить: почему бы просто не делать [[Update|обновление]] так же, как мы это сделали в RussianTutorialShareChange? Давайте попробуем и посмотрим, что произойдёт: |
Line 120: | Line 105: |
Здесь явно что-то не так. Как вы можете заметить, Mercurial предостерегает нас от откровенных глупостей, если мы упустим упоминание "(+1 heads)" в сообщении после команды `pull`, мы можем быть уверены что Mercurial напомнит нам, что мы, вероятно, хотели сделать что-то другое: нам надо обьеденять (merge). But before we do our very first merge let's check to which changeset we are synced to. We can use the `parents` command for this (see [:Parent]): |
Здесь явно что-то не так. Как вы можете заметить, Mercurial предостерегает нас от откровенных глупостей, и если мы упустим упоминание "(+1 heads)" в сообщении после команды `pull`, то можем быть уверены - Mercurial напомнит нам, что мы, вероятно, хотели сделать что-то другое: объединение (merge). Но перед тем, как мы приступим к нашему первому объединению, давайте проверим, с каким changeset-ом мы сейчас синхронизированы. Для этого мы можем воспользоваться командой `parents` (см. [[Parents]]): |
Line 132: | Line 116: |
This tells us that our [:WorkingDirectory:working directory] content is still synced to changeset `c3844fde99f0` – after all, that is what we just committed. What's important to understand here is, that the pull we did just pulled that other change into the ''store'' of our repository. The pull didn't change anything in our working directory. And take a second look at the output of `glog`: one changeset is marked with an "`@`". That's the current parent of the working dir: We are "at" `c3844fde99f0`. So, let's finally move on to the merge now. Merging sounds painful, right? It's actually very easy. Let's follow the instructions of the last line of the output of our earlier `pull:` |
Это говорит о том, что содержимое нашего [[WorkingDirectory|рабочего каталога]] пока синхронизировано с changeset'ом `c3844fde99f0` – это то, что мы недавно комитили. Важно понимать, что ''pull'' подтянул другие изменения из ''хранилища'' нашего репозитория. Подтягивание не меняет ничего в нашем рабочем каталоге. И взгляните ещё раз на вывод команды `glog`: один changeset помечен символом "`@`". Это родительский changeset рабочего каталога: "`@`" возле `c3844fde99f0`. Давайте, наконец, обьединять. Вас это пугает? Это действительно очень просто. Давайте последуем предложению из последней строки вывода нашей предыдущей команды `pull:` |
Line 146: | Line 126: |
That's all there is to it! Mercurial was able to handle the merge automatically for you, because the change chunks were non-conflicting (a merge with conflicts will be treated in [:TutorialConflict]). If we look at `hello.c` in the working dir now, we find that it contains ''both'' the change from `my-hello-new-output` and the change from `my-hello-desc`. When working with changes made by other people, this is the kind of merge you will end up performing 2nd most of the time. Most often, it's even simpler than that and the files that are changed in the diverged lines of development are disjunct. So, in most merges, there won't even be any ''files'' to merge. We haven't yet committed that merge now. Before we do that, let's see what the `parents` command is telling us now (we use abbrevation `par`): |
Вот и всё! Mercurial выполнил объединение автоматически, потому что изменения не конфликтовали (объединение конфликтующих изменений рассматриваются в RussianTutorialConflict). Если сейчас посмотреть `содержимое hello.c` в рабочем каталоге, мы найдём оба изменения: и из `my-hello-new-output`, и из `my-hello-desc`. Когда работаешь с изменениями, сделанными другими людьми, в подавляющем большинстве случаев используется именно этот вид объединения. Очень часто всё даже проще, потому что файлы, меняющиеся в различных направлениях разработки, обычно различны. Поэтому, в большинстве случаев объединения, вообще не будет каких либо ''файлов'' для объединения. Мы ещё не закомитили результаты объединения. Прежде чем сделать это, давайте посмотрим, что нам скажет команда `parents` (сокращённая до `par`): |
Line 170: | Line 146: |
This now tells us, that the working directory is based on ''two'' changesets: it has two parents. Note that these two parents are ordered: the first parent (parent 1) is our earlier changeset `c3844fde99f0` in which we added that description to `hello.c`. That was the then current parent when we issued the `merge` command. The second parent (parent 2) is changeset `86794f718fb1` which we pulled from the other repository and which actually is the changeset we have merged-in now. Another `glog` now shows the `@` sign on the two parents: |
Это значит, что рабочий каталог базируется на ''двух'' changeset'ах: у него два родителя. Заметьте, что порядок родителей имеет значение: первый родитель (parent 1) это изначальный changeset `3844fde99f0`, в который мы добавили описание в коментарий `hello.c`. Он был текущим родителем, когда мы ввели команду `merge`. Второй родитель (parent 2) - это changeset `86794f718fb1`, который мы подтянули из другого репозитория и с которым мы и объединяли. Сейчас `glog` покажет знак `@` у двух родителей: |
Line 203: | Line 174: |
/!\ Note that if you change your mind and you want to undo this merge before comitting anything, just doing a `hg revert -r2 --all` will only revert the state of the files in the working dir to revision 2 and __not change the parents of the working dir back to a single parent__ (see [:Revert]). You should do a "`hg update -C -r.`" instead to undo the merge in this case. To complete the whole merging procedure, we should not forget to commit these [:LocalModifications:local modifications], as suggested on the last line of the output from the earlier `merge` command: |
/!\ Заметьте, что если вы передумали и хотите отменить это объединение перед тем, как что-то закомитить, просто выполните `hg revert -r2 --all. Это` вернёт файлы в рабочем каталоге в состояние ревизии 2, но __не изменит количество родителей обратно с двух на одного__ (см. [[Revert]]). Либо вам придётся выполнить "`hg update -C -r.`", чтобы отменить объединение и вернуть рабочий каталог к состоянию с одним родителем. Для завершения процедуры слияния мы должны не забыть закомитить [[LocalModifications|локальные изменения]], о чём нам и напоминают в последней строке вывода предыдущей команды `merge`: |
Line 211: | Line 181: |
There shouldn't be any output from this command. Now, the merge is recorded in the store of the repository as a new [:MergeChangeset:merge changeset] and we can explore it with `glog`: |
Эта команда не должна ничего выводить. Теперь объединение зарегистрировано в репозитории как новый [[MergeChangeset|merge changeset]] и `glog` нам это покажет: |
Line 246: | Line 214: |
To show the changes of our merging, we can furthermore use the `annotate` command to show changeset information per file line. Note that revision 2 is our modification to `my-hello-desc` repository and revision 3 is the changes pulled and merged from `my-hello-new-output` repository to `my-hello-desc` repository. |
Чтобы наглядно показать результаты изменений, выполненных при объединении, мы можем воспользоваться командой `annotate`, которая покажет changeset для каждой строки (в примере указаны локальные changesets -- ревизии). Обратите внимание, что 2-ая ревизия -- это наша модификация репозитория `my-hello-desc`, а 3-я ревизия -- это изменения, вытянутые из репозитория `my-hello-new-output` в репозиторий `my-hello-desc`. |
Line 270: | Line 236: |
Let us continue on and learn how to deal with situations where [:Conflict:conflicting] changes have been made in [:TutorialConflict]. |
Как разобраться с ситуациями, когда случаются [[Conflict|конфликтующие]] изменения, мы узнаем в TutorialConflict. |
Line 274: | Line 239: |
CategoryTutorial CategoryRussian |
CategoryTutorial CategoryRussian |
Tutorial - Слияние изменений
(Это 7-я из 9-ти частейTutorial. Предыдущая - RussianTutorialExport, следующая - RussianTutorialConflict)
В главе RussianTutorialExport мы разобрались, как передать изменения кому-нибудь. В этой части мы собираемся рассмотреть слияние различных подтянутых изменений из другого репозитория.
Во-первых, мы должны создать то, что собираемся объединять. Снова клонируем репозиторий 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
Сохранив, выходим из редактора и фиксируем наши изменения. На этот раз мы экономим время, используя опцию -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'ы мы можем командой 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 поставляется с замечательным расширением, отображающим историю репозитория в виде 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'ом) в наш репозиторий . Так как оба changeset'а: и подтянутый 86794f718fb1, и наш c3844fde99f0, имеют одного родителя (82e55d328c8c), то можно сказать, что были созданы две различные линии разработки, называемые ветками (branch). Заметим, что в данном случае ветка недолговечна и это раздвоение легко разрешается Mercurial'ом.
Глядя на вывод pull, можно подумать, что он похож на пример из RussianTutorialShareChange. Вы можете спросить: почему бы просто не делать обновление так же, как мы это сделали в 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
Это говорит о том, что содержимое нашего рабочего каталога пока синхронизировано с 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.", чтобы отменить объединение и вернуть рабочий каталог к состоянию с одним родителем.
Для завершения процедуры слияния мы должны не забыть закомитить локальные изменения, о чём нам и напоминают в последней строке вывода предыдущей команды merge:
$ hg commit -m "Merged changes from my-hello-new-output"
Эта команда не должна ничего выводить. Теперь объединение зарегистрировано в репозитории как новый 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 <stdio.h> 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: }
Как разобраться с ситуациями, когда случаются конфликтующие изменения, мы узнаем в TutorialConflict.