Слияние изменений в промежуточных ветках с DVCS - PullRequest
3 голосов
/ 17 августа 2011

Я некоторое время работал с Plastic SCM, но только недавно обнаружил изъян в моей ментальной модели работы наборов изменений в ветвях.

Рассмотрим этот простой сценарий:

  • Предположим, у меня есть ветвь A с файлом foo.txt
  • Я разветвляю набор последних изменений A на дочернюю ветку B.
  • Я переключаю рабочее пространство на B и извлекаю foo.txt и делаю некоторые изменения, которые я проверяю.
  • Я изменяю последний набор изменений B на C.
  • Я пытаюсь объединить C с A

Вкратце: ветвь к B, изменение foo.txt в B, ветвь к C, слияние C к A.

К моему удивлению, изменения, внесенные в foo.txt в промежуточной ветви B, были проигнорированы, потому что я не внес изменения в foo.txt в C. Таким образом, после слияния из C в A, A содержит исходный foo. TXT перед разветвлением B.

Я ожидал, что мои промежуточные изменения в B будут объединены при выполнении полного слияния из C в A, но, очевидно, мое понимание наборов изменений в ветвях было неверным. Это время от времени приводило к некоторой очистке, когда изменения таинственным образом терялись.

Аналогично ли ведут себя Git и Mercurial или другие DVCS?

Edit:

Пластиковая версия <= 3 объединяет только изменения в исходной ветви, а не промежуточные ветви. </p>

Пластик> = 4 объединяет весь путь ветвления.

Ответы [ 2 ]

4 голосов
/ 18 августа 2011

Mercurial работает с ветками иначе, чем git.В Mercurial имя ветви набора изменений фактически является частью набора изменений.Закладки ведут себя примерно так же, как ветви git.Различия все еще существуют, и эта статья отлично справляется с закладками hg и ветками git.

Используете ли вы закладки Mercurial или именованные ветви (или даже просто анонимные ветви), вы все равно получаете это:

@__    merged C into A (branch A again)
|  \
|   o  add c.txt (branch C; a commit is necessary to start named branch)
|  / 
| o    appended to a.txt (branch B)
|/
o      added a.txt (branch A)

А после слияния A содержит: a.txt, в котором добавлен текст, добавленный во втором наборе изменений (а также c.txt, добавленный в третьем).

4 голосов
/ 18 августа 2011

Git не работает таким образом. В Git ветка - это просто указатель, указывающий на последний коммит в серии. Когда вы находитесь в этой ветке и делаете новый коммит, указатель перемещается к новому коммиту.

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

Сценарий, о котором вы говорите, будет выглядеть в Git следующим образом:

           A
           ↓
a1 ← a2 ← a3    B
             ↖  ↓
               a4   C
                 ↖  ↓
                   a5

В Git у вас просто есть серия коммитов, но некоторые из них имеют метки веток, указывающие на них. A указывает на a3 (который знает, что a2 является его родителем); B указывает на a4, который имеет a3 в качестве родителя, и так далее. Таким образом, по умолчанию, если вы слили C в A, Git произвел бы «ускоренную пересылку» слияния (что означает, что у A нет изменений), и вы получите это:

                B    A, C
                ↓    ↓
a1 ← a2 ← a3 ← a4 ← a5

Теперь вы можете избавиться от изменений B, если хотите. Одним из способов является интерактивная перебазировка:

git rebase -i

Здесь показан список коммитов, и вы просто удаляете коммит B из этого списка. Git воспроизводит ваши коммиты без этого. Другой способ - начать с A, затем использовать

git cherry-pick a5

, чтобы поместить изменения a5 в качестве следующего набора изменений после a3. Но обе эти вещи должны быть особенными. По умолчанию B будет включен в слияние.

...