Я-то думал тут будет что-то интересненькое про то, как заставить шар летать. А оказывается автор лишь его обклеил своими текстурами — сомнительное достижение. Самое интересное — это сам глобус из которого был сделан такой шарик. Пойду лучше погуглю видео про этот глобус…
10 минут назад не готов был ответить, но сейчас уже знаю ответ: в git это называется cherry-pick, в Mercurial — Transplant — перенос частичных изменений и история их перемещений средствами системы контроля версий!
Предвижу следующий вопрос с Вашей стороны:
«А что если в проекте Y будут сделаны изменения (добавлена одна функция), которая может потом пригодится в проекте X — для этого ведь понадобится передать частичное изменение (без всех предков) из Y -> X».
Отвечаю: поскольку, частичная передача изменений без ревизий-предков противоречит всей коцепции веток и слияний, делать следует так:
Для всех общих функций в проектах X и Y заводится четвёртая ветка под названием «4(XY) — общее для проектов X и Y» и слияния просиходят по следующей схеме:
Ещё вопрос: «А что если полезная функция была УЖЕ внесена в 3(Y) и теперь мы хотим перенести её в ветку для проекта X?»
Да, можно отщепить эту функцию старым дедовским способом, взяв отдельный diff из ветки 3(Y) и наложив его на ветку 2(X). Но это плохое решение. А если эту функцию потом надо будет немного усовершенствовать причём для двух проектов сразу? Придётся возиться в обоих ветках, либо опять гонять diff вручную.
Именно для из этих соображений, я предлагаю Вам ветку 4(XY). Выносить всё общее для двух проектов нужно туда (по аналогии с глобально-общей-для всех проектов веткой 1).
Итак, я всё ещё не ответил на вопрос: как средствами Mercurial правильно перенести функцию УЖЕ написанную в ветке 3(Y) куда-то в более подходящее ей место (4XY или 1), если она потребовалась в нескольких проектах одновременно? И не отвечу, ибо не знаю прямо сейчас :) Обычно я заранее планирую что и где должно лежать и пользуюсь строгой последовательностью слияний от общего к частному.
У меня пока одна идея: использовать функциональность распределённых систем под названием Rebase. Подробности опускаю, т.к. не сам не пробовал, только читал в доках.
Пока писал длинные ответ, Вы в целом описали свою проблематику.
Могу дать такой совет, как это должно было бы быть сделано в распределённой системе (Mercurial в частности).
Первый класс изменений ведётся в ветке 1.
Второй класс изменений (под проект Х) ведётся в ветке 2.
Если появляется проект Y, то под него заводится ветка 3.
Все слияния (переносы изменений) делать в направлении 1 -> 2 и 1 -> 3.
Никаких потребностей в выборочных переносах при этом появиться не должно.
Ревизия при слиянии в другую ветку (merge) тянет за собой всех предков — и именно это предотвратит конфликт на шаге 9 в изначальном примере.
Внимательно прочитал Ваш пример и вы абсолютно правы: я переношу ВСЕ возможные изменения с одной ветки на другую, а Вы выборочно.
Ваш вопрос: можно ли в Mercurial переносить изменения по вашей схеме и не получить конфликт на шаге 9?
Я никогда не пробовал переносить изменения выборочно, как это описали Вы.
В частности, меня удивил пункт «7. Переносим изменения 2 и 6 на левую ветку», в результате которого на левой ветке в первой строке осталась одна буква «А». Чтобы добавить вторую букву A вы делаете дополнительный перенос изменения 3.
Вопрос концептуальный: зачем вам понадобился такой контроль версий? Возможно, это из-за специфики работы с SVN…
Если всё-таки необходимо переносить изменения вот так атомарно, то первое что приходит на ум: чтобы сделать выборочный перенос, нужно брать diff от версии N и N-1 (то самое выборочное изменение), сохранять его в файл и накладывать на другую ветку (patch) — но контроль версий тут уже не причём, с этим справится любая diff/patch программа и, естественно, в итоге на пункте 9 будет конфликт.
Второе что приходит на ум: в Mercurial есть расширение под названием MQ — реализует очередь патчей и позволяет проводить всякие хитрые манипуляции. Возможно, даже, удастся реализовать эту схему без конфликтов. Я не спец по mq, в бою не пробовал.
Но повторюсь ещё раз, скорее всего, Вам надо задуматься о самом подходе к веткам — почему Вы хотите копировать изменения выборочно?
Вернусь к Вашему примеру:
7. Переносим изменения 2 и 6 на левую ветку
А АА АА
ББ ББ ББ
В В В
Г Г
В левой ветке в первой строке одна буква A.
В левой ветке во второй строке две буквы ББ, которые (если проследить цепочку) пришли из изменения «5. Строка 2 на правой ветке изменена»:
А АА АА
Б Б ББ
Изменение 5 в свою очередь было сделано поверх изменения «3. На правой ветке строка 1 изменена»:
А А АА
Для меня, как для разработчика, возникает подозрение: если изменение 5 было сделано поверх 3 — скорее всего 5 зависит от 3? ББ во второй строке не скомпилируется без АА в первой?
А если так, то переносить ББ отдельно от АА — в чём смысл этих атомарных переносов?
Если же ББ никак не зависит от АА и в будущем есть потребность переносить ББ, не перенося AA — их следует сделать в двух разных ветках! Эту будут ревизии без связи предок-потомок и их можно будет атомарно как угодно переносить между ветками, не получив в итоге на шаге 9 никаких конфликтов (ибо память у Mercurial основана на ревизиях, которые однако переносятся между ветками вместе со всеми своими предками). Могу сделать пример и показать.
Таким образом, Ваша схема с атомарными переносами могла бы быть реализована бОльшим числом веток (каждое атомарное изменение производится в своей ветке, а потом комбинируй их как хочешь!) — но концептуально, это лишнее.
Боюсь я немного запутанно описал свои мысли.
Попробуйте прочитать вот эти две более стройные статьи с картинками про ветки и различные use case'ы:
Попытка слить 2 и 6 в 7 одновременно лишена смысла, т.к. изменение 2 уже содержится внутри 6.
Аналогично с 3 -> 8, и 5 -> 9: Mercurial не даст сделать такое слияние. Я сделал небольшой тестовый репозиторий для Вас и вот что получается:
Окунуться в историю было интересно, но не достаточно — хочется подробностей! Например, что это за Adaptive Hypervisor? На сколько процентов сейчас Parallels превосходит VMWare? И, как уже кто-то отмечал, хотя бы небольшое сравнение с VirtualBox…
Погуглил, в Mercruial есть аналогичное расширение под названием Transplant.
«А что если в проекте Y будут сделаны изменения (добавлена одна функция), которая может потом пригодится в проекте X — для этого ведь понадобится передать частичное изменение (без всех предков) из Y -> X».
Отвечаю: поскольку, частичная передача изменений без ревизий-предков противоречит всей коцепции веток и слияний, делать следует так:
Для всех общих функций в проектах X и Y заводится четвёртая ветка под названием «4(XY) — общее для проектов X и Y» и слияния просиходят по следующей схеме:
1(Платформа) -> 4(XY) -> 2(X)
и
1(Платформа) -> 4(XY) -> 3(Y).
Ещё вопрос: «А что если полезная функция была УЖЕ внесена в 3(Y) и теперь мы хотим перенести её в ветку для проекта X?»
Да, можно отщепить эту функцию старым дедовским способом, взяв отдельный diff из ветки 3(Y) и наложив его на ветку 2(X). Но это плохое решение. А если эту функцию потом надо будет немного усовершенствовать причём для двух проектов сразу? Придётся возиться в обоих ветках, либо опять гонять diff вручную.
Именно для из этих соображений, я предлагаю Вам ветку 4(XY). Выносить всё общее для двух проектов нужно туда (по аналогии с глобально-общей-для всех проектов веткой 1).
Итак, я всё ещё не ответил на вопрос: как средствами Mercurial правильно перенести функцию УЖЕ написанную в ветке 3(Y) куда-то в более подходящее ей место (4XY или 1), если она потребовалась в нескольких проектах одновременно? И не отвечу, ибо не знаю прямо сейчас :) Обычно я заранее планирую что и где должно лежать и пользуюсь строгой последовательностью слияний от общего к частному.
У меня пока одна идея: использовать функциональность распределённых систем под названием Rebase. Подробности опускаю, т.к. не сам не пробовал, только читал в доках.
Могу дать такой совет, как это должно было бы быть сделано в распределённой системе (Mercurial в частности).
Первый класс изменений ведётся в ветке 1.
Второй класс изменений (под проект Х) ведётся в ветке 2.
Если появляется проект Y, то под него заводится ветка 3.
Все слияния (переносы изменений) делать в направлении 1 -> 2 и 1 -> 3.
Никаких потребностей в выборочных переносах при этом появиться не должно.
Ревизия при слиянии в другую ветку (merge) тянет за собой всех предков — и именно это предотвратит конфликт на шаге 9 в изначальном примере.
Ваш вопрос: можно ли в Mercurial переносить изменения по вашей схеме и не получить конфликт на шаге 9?
Я никогда не пробовал переносить изменения выборочно, как это описали Вы.
В частности, меня удивил пункт «7. Переносим изменения 2 и 6 на левую ветку», в результате которого на левой ветке в первой строке осталась одна буква «А». Чтобы добавить вторую букву A вы делаете дополнительный перенос изменения 3.
Вопрос концептуальный: зачем вам понадобился такой контроль версий? Возможно, это из-за специфики работы с SVN…
Если всё-таки необходимо переносить изменения вот так атомарно, то первое что приходит на ум: чтобы сделать выборочный перенос, нужно брать diff от версии N и N-1 (то самое выборочное изменение), сохранять его в файл и накладывать на другую ветку (patch) — но контроль версий тут уже не причём, с этим справится любая diff/patch программа и, естественно, в итоге на пункте 9 будет конфликт.
Второе что приходит на ум: в Mercurial есть расширение под названием MQ — реализует очередь патчей и позволяет проводить всякие хитрые манипуляции. Возможно, даже, удастся реализовать эту схему без конфликтов. Я не спец по mq, в бою не пробовал.
Но повторюсь ещё раз, скорее всего, Вам надо задуматься о самом подходе к веткам — почему Вы хотите копировать изменения выборочно?
Вернусь к Вашему примеру:
7. Переносим изменения 2 и 6 на левую ветку
В левой ветке в первой строке одна буква A.
В левой ветке во второй строке две буквы ББ, которые (если проследить цепочку) пришли из изменения «5. Строка 2 на правой ветке изменена»:
Изменение 5 в свою очередь было сделано поверх изменения «3. На правой ветке строка 1 изменена»:
Для меня, как для разработчика, возникает подозрение: если изменение 5 было сделано поверх 3 — скорее всего 5 зависит от 3? ББ во второй строке не скомпилируется без АА в первой?
А если так, то переносить ББ отдельно от АА — в чём смысл этих атомарных переносов?
Если же ББ никак не зависит от АА и в будущем есть потребность переносить ББ, не перенося AA — их следует сделать в двух разных ветках! Эту будут ревизии без связи предок-потомок и их можно будет атомарно как угодно переносить между ветками, не получив в итоге на шаге 9 никаких конфликтов (ибо память у Mercurial основана на ревизиях, которые однако переносятся между ветками вместе со всеми своими предками). Могу сделать пример и показать.
Таким образом, Ваша схема с атомарными переносами могла бы быть реализована бОльшим числом веток (каждое атомарное изменение производится в своей ветке, а потом комбинируй их как хочешь!) — но концептуально, это лишнее.
Боюсь я немного запутанно описал свои мысли.
Попробуйте прочитать вот эти две более стройные статьи с картинками про ветки и различные use case'ы:
stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
nvie.com/posts/a-successful-git-branching-model/
abort: can't merge with ancestor
>hg merge -r5 -r9
abort: can't merge with ancestor
Попытка слить 2 и 6 в 7 одновременно лишена смысла, т.к. изменение 2 уже содержится внутри 6.
Аналогично с 3 -> 8, и 5 -> 9: Mercurial не даст сделать такое слияние. Я сделал небольшой тестовый репозиторий для Вас и вот что получается:
Попытка сделать 3 -> 8
Всё настроил, пока у меня эффект плацебо, но со временем посмотрим)
www.businessinsider.com/chart-of-the-day-tech-acquisitions-2010-9