Вот код, который вы можете использовать :), попробуйте и скажите мне:
^([0-2][0-9]|(3)[0-1])(\/)(((0)[0-9])|((1)[0-2]))(\/)\d{4}$
Я сам не использую Subversion, но из release notes для Subversion 1.5: Merge tracking (foundational) следует, что есть следующие отличия от того, как работает отслеживание слияний в полных DAG системах управления версиями, таких как Git или Mercurial.
Слияние ствола с веткой отличается от слияния ветки со стволом: по какой-то причине слияние ствола с веткой требует --reintegrate
опции к svn merge
.
В распределенных системах контроля версий, таких как Git или Mercurial, нет технической разницы между стволом и веткой: все ветки созданы одинаковыми (хотя может быть социальная разница). Слияние в любом направлении выполняется одинаково.
Вам нужно предоставить новую опцию -g
(--use-merge-history
) в svn log
и svn blame
для учёта отслеживания слияний.
В Git и Mercurial отслеживание слияний автоматически учитывается при отображении истории (журнала) и вины. В Git вы можете запросить следовать только за первым родителем с помощью --first-parent
(я полагаю, подобная опция существует и для Mercurial), чтобы "отбросить" информацию об отслеживании слияний в git log
.
Насколько я понимаю, свойство svn:mergeinfo
хранит информацию о конфликтах для каждого пути (Subversion основана на changeset), в то время как в Git и Mercurial это просто объекты коммитов, которые могут иметь более одного родителя.
"Known Issues" подраздел для отслеживания слияний в Subversion предполагает, что повторяющиеся / циклические / отражающие слияния могут работать неправильно. Это означает, что при следующих историях второе слияние может не сработать правильно ('A' может быть стволом или ответвлением, а 'B' может быть ответвлением или стволом, соответственно):
*---*---x---*---y---*---*---*---M2 <-- A \ \ / --*----M1---*---*---/ <-- B
В этом случае вышеприведенный ASCII-арт нарушается: Ветвь 'B' создаётся (форкируется) из ветви 'A' в ревизии 'x', затем позже ветвь 'A' сливается в ревизии 'y' в ветвь 'B' как слияние 'M1', и, наконец, ветвь 'B' сливается в ветвь 'A' как слияние 'M2'.
*---*---x---*-----M1--*---*---M2 <-- A \ / / \-*---y---*---*---/ <-- B
В этом случае вышеприведенный ASCII-арт нарушается: Ветвь 'B' создана (форк) из ветви 'A' в ревизии 'x', она слита в ветвь 'A' в ревизии 'y' как 'M1', а затем снова слита в ветвь 'A' как 'M2'.
Subversion может не поддерживать расширенный случай criss-cross merge.
*---b-----B1--M1--*---M3 \ \ / / \ X / \ / \ / \--B2--M2--*
Git прекрасно справляется с этой ситуацией на практике, используя "рекурсивную" стратегию слияния. Я не уверен насчет Mercurial.
В "Known Issues" есть предупреждение, что отслеживание слияния может не работать при переименовании файлов, например, когда одна сторона переименовывает файл (и, возможно, изменяет его), а вторая сторона изменяет файл без переименования (под старым именем).
На практике и Git, и Mercurial прекрасно справляются с такими случаями: Git использует обнаружение переименования, Mercurial - отслеживание переименования.
HTH
До Subversion 1.5 (если я не ошибаюсь), у Subversion был существенный недостаток в том, что он не запоминал историю слияния.
Давайте рассмотрим случай, описанный VonC:
- x - x - x (v2) - x - x - x (v2.1)
|\
| x - A - x (v2-only)
\
x - B - x (wss)
Обратите внимание на версии A и B. Скажем, вы объединили изменения из версии A в ветке «wss» в ветку «только для v2» в версии B (по любой причине) , но продолжал использовать обе ветви. Если вы попытаетесь снова объединить две ветки с помощью mercurial, он объединит изменения только после ревизий A и B.В Subversion вам придется все объединять, как если бы вы не делали слияние раньше.
Это пример из моего собственного опыта, когда слияние от B до A заняло несколько часов из-за объема кода: это было бы настоящей болью, чтобы снова пройти , что было бы случай с subversion pre-1.5.
Еще одно, вероятно, более важное отличие в поведении слияния от Hginit: Subversion Re-education :
Представьте, что мы с вами работаем над некоторым кодом, и мы разветвляем этот код , и каждый из нас уходит в свои отдельные рабочие области и вносит много-много изменений в этот код по отдельности, поэтому они довольно сильно расходятся.
Когда нам нужно выполнить слияние, Subversion пытается просмотреть обе версии - мой измененный код и ваш измененный код - и пытается угадать, как {{ 1}} разбейте их вместе в один большой нечестивый беспорядок. Обычно это не удается, создавая страницы и страницы «конфликтов слияния» , которые на самом деле не конфликтуют, а просто места, где Subversion не удалось выяснить, что мы делал.
Напротив, пока мы работали в Mercurial отдельно, Mercurial был занят поддержанием серии наборов изменений. Итак, когда мы хотим объединить наш код {{ 1}} вместе у Mercurial есть гораздо больше информации: он знает , что каждый из нас изменил, и может повторно применить эти изменения, а не просто глядя на конечный продукт и пытаясь угадать, как его собрать .
Короче говоря, метод Mercurial в анализе различий превосходит (был?) Метод подрывной деятельности.
Не говоря об обычных преимуществах (автономные коммиты, процесс публикации, ...) вот пример "слияния", который мне нравится:
Основной сценарий, который я постоянно вижу, это ветка, на которой ... разрабатываются две несвязанные задачи
(она началась с одной функции, но привела к разработке другой функции.
Или это началось с патча, но привело к разработке другой функции).
Как объединить только одну из двух фич в основной ветке?
Или как изолировать эти две функции в их собственных ветках?
Вы можете попытаться сгенерировать некоторые виды патчей, проблема в том, что вы больше не уверены в функциональных зависимостях , которые могли существовать между:
Git (и Mercurial тоже, я полагаю) предлагает опцию rebase --onto для перебазирования (сброса корня ветки) части ветки:
Из сообщения Jefromi
- x - x - x (v2) - x - x - x (v2.1)
\
x - x - x (v2-only) - x - x - x (wss)
вы можете распутать эту ситуацию, когда у вас есть патчи для v2, а также новая функция wss в:
- x - x - x (v2) - x - x - x (v2.1)
|\
| x - x - x (v2-only)
\
x - x - x (wss)
, позволяя вам:
Другая особенность, которая мне нравится (влияющая на слияние) - это возможность сминать коммиты (в ветке, ещё не перенесённой в другое репо), чтобы представить:
Это обеспечивает слияние намного проще, с меньшим количеством конфликтов.
Я тоже искал случай, когда, скажем, Subversion не может объединить ветку, а Mercurial (и Git, Bazaar, ...) выполняет правильная вещь.
Книга SVN описывает, как переименованные файлы объединяются неправильно . Это относится к Subversion 1.5 , 1.6 , 1.7 и 1.8 ! Я попытался воссоздать ситуацию ниже:
cd /tmp rm -rf svn-repo svn-checkout svnadmin create svn-repo svn checkout file:///tmp/svn-repo svn-checkout cd svn-checkout mkdir trunk branches echo 'Goodbye, World!' > trunk/hello.txt svn add trunk branches svn commit -m 'Initial import.' svn copy '^/trunk' '^/branches/rename' -m 'Create branch.' svn switch '^/trunk' . echo 'Hello, World!' > hello.txt svn commit -m 'Update on trunk.' svn switch '^/branches/rename' . svn rename hello.txt hello.en.txt svn commit -m 'Rename on branch.' svn switch '^/trunk' . svn merge --reintegrate '^/branches/rename'
Согласно книге, слияние должно завершиться чисто, но с неверными данными в переименованном файле, так как обновление на стволе
забыто. Вместо этого я получаю конфликт дерева (это с Subversion 1.6.17, последней версии в Debian на момент написания):
--- Merging differences between repository URLs into '.': A hello.en.txt C hello.txt Summary of conflicts: Tree conflicts: 1
Не должно быть никакого конфликта вообще - обновление должно быть объединено с новым именем файл.В то время как Subversion терпит неудачу, Mercurial обрабатывает это правильно:
rm -rf /tmp/hg-repo
hg init /tmp/hg-repo
cd /tmp/hg-repo
echo 'Goodbye, World!' > hello.txt
hg add hello.txt
hg commit -m 'Initial import.'
echo 'Hello, World!' > hello.txt
hg commit -m 'Update.'
hg update 0
hg rename hello.txt hello.en.txt
hg commit -m 'Rename.'
hg merge
Перед слиянием репозиторий выглядит следующим образом (из hg glog
):
@ changeset: 2:6502899164cc | tag: tip | parent: 0:d08bcebadd9e | user: Martin Geisler | date: Thu Apr 01 12:29:19 2010 +0200 | summary: Rename. | | o changeset: 1:9d06fa155634 |/ user: Martin Geisler | date: Thu Apr 01 12:29:18 2010 +0200 | summary: Update. | o changeset: 0:d08bcebadd9e user: Martin Geisler date: Thu Apr 01 12:29:18 2010 +0200 summary: Initial import.
Результат слияния:
merging hello.en.txt and hello.txt to hello.en.txt 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)
Другими словами: Mercurial взял изменение из ревизии 1 и объединил его с новым именем файла из ревизии 2 ( hello.en.txt
). Обработка этого случая, конечно, необходима для поддержки рефакторинга, и рефакторинг - это именно то, что вы захотите сделать в ветке.