Макар че съм работил доста с Subversion днес ми се наложи да направя merge и доста се поизпотих. Инсталацията и простичкия commit, update не са всичко. Сценария е trunk, branch-1.2.0 и много учудващо branch-1.2, които е бранч на branch-1.2.0 (не знам кои го е измислил така). Картинката е следната:
+-----------------> branch-1.2
| Merge ^
| |
+--------------------------> branch-1.2.0
|
|
trunk --------------------------------------------->
Задачата? Промените от branch-1.2.0 да идат в branch-1.2, но от всичко а от определен момент (commit). Един ден четох как да го направя от команден ред и днес се престраших да експериментирам.
Подготвям си нещата като вземам последните версии на "моя" и "чуждия" branch.
svn update --show-updates
Добре е да има застраховка и затова слагам един таг.
svn copy -m "Tag before merge with branch 1.2.0" https://svn.company.com/product/branches/1.2 https://svn.company.com/product/tags/release-1.2-M01
После отивам в директорията на "чуждия" branch и искам да видя всички промени от самото създаване на branch-a до сега:
svn log --stop-on-copy -v > changes.log
Същото правя и за "моя" branch, като тука по-специялно ме интересува кога точно в създаден. Най-отдолу пише:
------------------------------------------------------------------------
r3777 | someone | 2007-04-04 18:20:31 +0300 (Wed, 04 Apr 2007) | 1 line
Changed paths:
A /branches/1.2 (from /branches/1.2.0:3776)
Creating branch for development of 1.2.x versions
------------------------------------------------------------------------
Отварям си културно changes.log и почвам да разглеждам. Ахааа ето и версията, от която нататък трябва да взема промените - r3785
Изводите. До r3777 двата branch-a са си еднакви и игнорирам промените. Намирам си версията от която нататък ми трябват промените и се готвя за merge. Все забравям, че HEAD е последната версия а не trunk-a, който е с CVS минало ще ме разбере :)
За merge се задава диапазона и после откъде да се вземе този диапазон. Плахо проверявам с --dry-run от r3785 до сега т.е. HEAD.
cd
svn merge --dry-run -r3785:HEAD https://svn.company.com/product/branches/1.2.0
А това значи: Дай ми всички промени в branch-1.2.0 от версия 3785 до последната и ги приложи в текущия branch (1.2)
Виждам каво ме чака и се хвърлям в огъня.
svn merge -r3785:HEAD https://svn.company.com/product/branches/1.2.0
U administration/webroot/waf/layout/porduct/core/services/assets/model/Asset.jsp
U lib/plica-waf.jar
U lib/plica-waf-web.jar
U lib/plica-waf-src.jar
C core/webroot/skin/i18n/en.js
U core/webroot/skin/basic2/main.css
A core/webroot/skin/adb
A core/webroot/skin/adb/main.css
U core/webroot/skin/super/main.css
U core/src/java/product/extensions/reminders/model/display.properties
U core/src/java/product/core/services/subscriptions/model/display.properties
A core/src/js/box/adb.js
U core/src/js/PlaybackManager.js
U core/src/js/widgets/config.js
U core/src/js/widgets/epg.js
U core/src/js/widgets/reminders.js
U core/src/js/widgets/broadcast.js
? dir_conflicts.prej
Ух само един конфликт и нещо странно в директорията - dir_conflicts.prej. Лесно се справам с програмния конфликт.
svn resolved core/webroot/skin/i18n/en.js
Как обаче да подходя с dir_conflicts.prej? Първо какво значи това - станало е конфликт в svn properties. Ето и лекарството:
# see what we have
svn proplist .
# see the problem
less dir_conflicts.prej
# find the problem - it was in svn:ignore
svn propedit svn:ignore .
# change svn:ignore (add or remove something). In my case I have to add.
svn propset svn:ignore bin .
# do it
svn resolved .
Съвесно проверявам статуса и разликите:
svn status --show-updates
svn diff |colordiff
изтрелвам всичко
svn commit -m "Merged branch 1.2.0 to branch 1.2"
Все още не мога да свикна с Subversion, защото винаги правя аналогии с CVS-a. Много по-добър от CVS-а! Вижда ми се малко прекалено, ако разбира се ако забравим преименуването на файловете. Другото дразнещо нещо е merge-a. Ако ви се наложи да правите постоянен merge с trunk-a да речем, тогава вие и само вие трябва да държите списък за това от къде до къде сте направили merge. Какво имам в предвид. Ако в понеделник сте направили:
svn merge -r5238:HEAD http://svn.company.com/product/trunk
svm commit -m "merge commit"
Commit at 5302
Трябва да запомните това число 5302 и във вторник да почните точно от там.
svn merge -r5302:HEAD http://svn.company.com/product/trunk
Иначе ще получите много конфликти и пак ще се наложи да ги оправяте ръчно. Subversion просто не държи списък на направените merges и до къде са направени. Запазете вяра обаче в версия 1.5 това ще бъде коригирано. До тогава може да ползвате svnmerge и тези
напътствия.
И сега най-инересната част. След като синхронизирам branch-a 3 седмици с trunk и отделно активно се добавя код branch-a идва обратната задача - всичко от този branch да иде обратно в trunk. Много глупаво и напрактика двойна работа, ама нищо приемам го като предизвикателство.
cd trunk
svn merge http://svn.company.com/product/trunk http://svn.company.com/product/branches/1.2 .
с други думи всички разлики(HEAD:HEAD) в текущата директория, която е всъщност trunk-a.