2013-04-18 2 views
16

Я читал многочисленные вопросы и блоги SO на git-svn и слияния. Некоторые из них (в частности, git-svn man page) предупреждают против, используя слияние где-нибудь рядом с филиалом. Я планирую dcommit от.Git-svn объединяет две ветви SVN

Другие, как этот SO answer, утверждают, что слияние хорошо до тех пор, пока я использую разовый полнометражных ветви, которые я удаляю перед тем dcommitting.

У меня есть установка с двумя долгоживущей SVN (и мерзавца) ветви:

  • ствол (ГИТ-SVN: svn/trunk, мерзавец: master) - стабильную ветвь
  • филиалы/devel (git-svn: svn/devel, git: devel) - основная ветка развития, из которой я вилка от ветвей функции (и я могу жить с их перезагрузкой обратно в devel вместо слияния).

Snapshot of current state in Source Tree

В приведенном выше рисунке, (1) показывает прошлые истории SVN, где branches/devel была слита в trunk.

(2) показывает, что у меня есть dcommitted мое текущее развитие в SVN.

Вопрос: можно использовать git-svn слить две ветви SVN так, что история показывает, точка слияния (как и сама SVN можно сделать)? Другими словами: что произойдет, если я буду dcommit от master, как показано на странице (3)?

Будет ли это испортить мою историю SVN (или git)? Или это просто забыть, что devel был объединен в master?

EDIT: Если git просто забывает, что devel был слит в master, есть разница между dcommiting с точки (3) и применяя все коммиты как единый патч?

ответ

14

Рытье еще немного в этот вопрос, я обнаружил, что мерзавец поддерживает настройку svn:mergeinfo свойства на ветке SVN, когда dcommit «ING:

git svn dcommit --mergeinfo "/branches/somebranch:1-3" 

NB!svn:mergeinfo is перезаписан с тем, что указано в командной строке, поэтому будьте осторожны, чтобы перечислять предыдущие слияния тоже.

Хотя более поздние версии мерзавец добавлен параметр конфигурации автоматически установить это свойство:

config key: svn.pushmergeinfo 

я некоторые проблемы с автоматической mergeinfo - по одной причине или другой GIT рассчитывается неправильно, и я не мог заставить его работать.

РЕШЕНИЕ: git-merge-svn

Чтобы автоматизировать этот процесс, я написал сценарий git-merge-svn оболочки, которая может быть использована для объединения двух ветвей SVN с правильной svn:mergeinfo набора на dcommit.

Скрипт обрабатывает обе ситуации:

  • ветвь не сливались в мерзавца - будут делать git merge заранее
  • ветви были уже объединены в мерзавец (но не в SVN) - не будет проходить до тех пор, предыдущая предок для объединенных изменений фиксации.

С помощью этого скрипта я был в состоянии производить эти слияния только на мерзавца стороне и сохранить данные слияния, так что GIT график показывает журнал красиво:

git-merge-svn result

Пример использования:

  1. Сделайте несколько фиксаций на devel6
  2. dcommitdevel6 в SVN (требуется, чтобы получить номера версий SVN для фиксаций)
  3. выписка testtunk6 - да, я знаю, что я сделал опечатку в имени ;-)
  4. git merge-svn devel6

последние commant выходы:

% git merge-svn devel6 
About to do an SVN merge: devel6 -> testtunk6 

* NEW MERGE COMMIT 
|\ 
| * devel6 [7b71187] (r102) 
* | testtunk6 [0682a45] (r101) 
\| 
    * [273d6d6] (r100) 


STEP 1: GIT merge 
Executing: 
    git merge devel6 

Continue? (y/n) [n]: y 
Merge made by the 'recursive' strategy. 
testfile | 1 + 
1 file changed, 1 insertion(+) 

STEP 2: SVN dcommit 

executing: 
git svn dcommit --mergeinfo 
/idp/branches/devel:9-32,35-41 /idp/branches/devel6:89 /idp/branches/devel6:94 /idp/branches/devel6:93 /idp/branches/devel6:96 /idp/branches/devel6:97 /idp/branches/devel6:99 /idp/branches/devel6:100 /idp/branches/devel6:102 

Continue? (y/n) [n]: y 
Committing to https://my.svn.host/svn/auth/idp/branches/testtunk6 ... 
    M testfile 
Committed r103 
    M testfile 
Found merge parent (svn:mergeinfo prop): 7b71187fc371d3f86658c5850009e63be88157ac 
r103 = 87759323cbadd38bac78087d57b6870a926287e7 (refs/remotes/svn/testtunk6) 
No changes between 3fb2168cfbbe605fbd810d76513443203a85a549 and refs/remotes/svn/testtunk6 
Resetting to the latest refs/remotes/svn/testtunk6 
+0

Очень круто! Благодаря! – msrxthr

+0

Есть ли способ заставить это работать: 'git-merge-svn master mybranch', за которым следует сразу' git-merge-svn mybranch master'? Второе слияние пытается dcommit к mybranch, и если вы попробуете еще раз, то он говорит, что он уже слит (ложь, вероятно, из-за того, что git-хозяин сливается с ша-хэшем, который соответствует шагу mybranch, несмотря на то, что он не был привязан к svn - хотя строка git-svn-id существует, поскольку она была объединена с фиксацией, которая была передана с mybranch на svn). –

+0

@ShadowCreeper - на самом деле сообщение, вероятно, верно - SVN сообщает, что коммиты уже присутствуют в 'mybranch', какие они есть. Ваш ожидаемый результат будет заключаться в том, что 'mybranch' и' master' указывают на тот же SHA1, но это невозможно с SVN - это ветки, по существу, папки, а две ветви должны указывать на разные папки. Итак, в SVN все в лучшем случае, а в Git вы не можете использовать полную функциональность - так оно и есть. – Laas

4

Git и Svn имеют разную структуру данных, чтобы сохранить историю.

Svn использует простое дерево. То есть каждая фиксация имеет только одного родителя, но у одного фиксатора может быть несколько дочерних элементов (ветвей). Таким образом, Svn не поддерживает слияния. Вещь, которую они называют «слиянием», на самом деле изменяет портирование, ближайшая аналогия в git - rebase или, может быть, cherry-pick. Из версии 1.5 Svn поддерживает свойство metainfo svn:mergeinfo, которое помогает как-то отслеживать, что было «объединено», однако оно выглядит главным образом как обходное решение, объясняющее, почему ветви в Svn настолько трудны в использовании. Точка слияния - это фиксация, которая скручивает все объединенные изменения и разрешение конфликтов в один набор изменений, возможно, аннотированный свойством svn:mergeinfo.

Git использует Directed acyclic graph, что является очень естественным способом описания слияния и разветвления истории. Точка слияния - это еще одна фиксация с двумя (или более!) Родителями. Таким образом, ваш (3) на картинке является фиксацией слияния. Итак, вся история выглядит естественной, она имеет все возможности достижимости на графике истории из текущей точки.

Git-Svn bridge пытается сделать все, чтобы справиться с недостатком дизайна Svn, прежде чем делать dcommit, он обычно переустанавливает все объединенные коммиты в верхней части текущей ветви Svn. Asof ~ 2 года назад git-svn не смог поставить svn:mergeinfo, поэтому вещь, о которой вы просите, невозможна. Более того, когда вы находитесь dcommit ing, git создает «близнецовую» фиксацию «с трудом», связанную с фиксацией svn, поэтому она перезаписывает оригинальную фиксацию.

+0

спасибо за объяснение. Я закончил с рабочим процессом, что я «rebase -i» все одноразовые ветви на 'devel' и в точке выпуска, я просто создаю патч и применяю это как отдельную фиксацию к' master'. Таким образом, 'master' состоит только из коммитов-релизов, а dev-history - только в ветке' devel'. Хорошее решение. – Laas

+0

@Laas Вы имеете в виду, что вы сквош все коммиты в один, используя 'rebase -i'? Да ... может работать, и довольно легко сделать, однако он закручивает историю, но похоже, что это лучшее, что вы могли бы достичь, используя svn. – kan

+2

@Laas Или альтернативное решение - это набор червяков для коммиттов с флагом '-x', по крайней мере, он будет продолжать коммитировать отдельно, неявно связав их с комментарием« cherry selected from commit ». Этот комментарий обрабатывается 'git log' и некоторыми другими командами, что упростит некоторые вещи. – kan

Смежные вопросы