Ответ 1
Попытка ответить на мой вопрос: использование git для слияний svn кажется многообещающим.
Обновление: это не просто обещание, это большой успех. Короче говоря, Линус был прав.
Только что завершилось огромное слияние двух svn-ветвей, которые были разделены на 1,5 года; 3k файлы были изменены, получили тонны конфликтов в svn (~ 800, я думаю).
Я нашел git и git -svn спасатель жизни:
- автоконфликтное разрешение: для начала он дал намного меньше противоречивых файлов (~ половина, я думаю)
- невероятная производительность
- отлично модель репо/ветвление, гибкие рабочие процессы: простое экспериментирование с различными подходами, такими как слияние блоков по времени (по времени) всегда делать проверки здравомыслия (компиляция и т.д.); всякий раз, когда неприятности попадают: просто назад. Вы всегда можете сделать шаг назад, когда это необходимо.
- удобство использования, отличное оснащение:
-
git-log
(и базовые опцииgit-rev-parse
), ничто не может быть более мощным, чем это. Это также полезно:-p
дает вам разницу за один раз; в svn вы получите журнал, затем найдите diff для этой "ревизии-1: ревизия" или используйте неуклюжие пользовательские интерфейсы. Найти, когда строка была добавлена /удалена в репо, поиск нескольких ветвей одновременно -
gitk
: чрезвычайно полезно для визуализации истории веток в сочетании с отличными возможностями поиска. Не видели ничего подобного в других инструментах, особенно не так быстро, как это. Nevermind это в Tk, это просто блестяще -
git gui
: отлично работает, даже если не самый сексуальный - отличная помощь для новичков, чтобы обнаружить вещи. -
blame
: чудо. Да, он обнаруживает, откуда приходит исходный сегмент (копия, вставка и т.д.). -
mergetool
: гораздо приятнее, чем начинать большойsvn merge
, который затем останавливается каждый раз (т.е. каждые 5 минут), он сталкивается с конфликтом, нажимает '(p) ostpone', а не на ручную охоту за конфликтующими файлами позже. Предпочтительный аромат этого интегрированного вgit gui
(для этого нужен крошечный патч). Найдены интегрированные инструменты внешней диффе- ренции, которые лучше конфигурируются, чем вsvn
. - подключаемые драйверы слияния и мелкозернистый контроль над ними.
-
rebase
разрешено отфильтровывать более грязные части истории svn
-
- Распространение: нет необходимости приходить в офис при работе над этим, может приостанавливаться и прогрессировать шаг за шагом на поезде/самолете и т.д.
- USB-накопитель с Unison заставил синхронизировать работу ↔ домой кусок торта
- это было бы невозможно без git сумасшедшего сжатия (5-летний проект с фиксацией 26 тыс., тонны ветвей и двоичных файлов, trunk svn checkout: 1.9Gb = > все это в полном репозитории git: 1.4Gb!)
Итак, это действительно может изменить ситуацию от кошмара до радости - особенно, если вам нравится учиться (что в этом случае требует определенных усилий - я думаю, что изучать мотоцикл после велосипеда).
Даже если я не могу заставить всех в компании немедленно переключиться - я действительно не собирался на самом деле. Опять же, git-svn
сэкономит нас на "окунании носком". Но, увидев реакции коллег, коммутатор может произойти намного раньше, чем кто-либо ожидал:)
Я бы сказал - даже если мы забудем о слияниях и коммитах, этот материал уже отлично подходит для использования только для чтения для запросов, визуализации, резервного копирования и т.д.
Протест:
"Не выполнять dcommit git merge совершает репозиторий Subversion. диверсия не обрабатывает слияния таким же образом как Git, и это вызовет проблемы. Это означает, что вы должны сохранить свой Gitистория развития линейная (т.е. нет сливаясь с другими отраслями, просто перебазирования)". (последний абзац http://learn.github.com/p/git-svn.html)
Другим отличным источником является Pro git book, раздел "Переключение активных ветвей" в основном говорит о том, что слияние действительно работает, но dcommit
будет хранить содержимое слияния, но история будет скомпрометирована (что приведет к разрыву последующих слияний), поэтому вам следует отказаться от рабочей ветки после слияния.
В любом случае, это имеет смысл в конце концов, и на практике легко избежать ловушек здесь. В svn я обнаружил, что люди обычно не сливаются воедино, так что это можно было бы рассматривать только как шаг назад, если вы пришли из мира git первое место.
Во всяком случае, dcommit просто работал у меня. Я сделал это на своем собственном svn workbranch, который я сохранил только для этого, поэтому избегал любых дополнительных конфликтов в то время. Тем не менее, я решил сделать окончательное слияние с этой рабочей ветки на svn trunk в svn (после синхронизации всего в git); --ignore-ancestry
дал наилучшие результаты.
Обновление: как я узнал позже, последние несколько шагов выше (дополнительная ветвь svn и merge - ignore-ancestry) легко избежать, просто удерживая ветку, которую вы выполняете с линейной. Как говорит Гейб ниже, merge --squash
просто создает просто тупое svn-friendly commit. Когда вы будете готовы с огромным слиянием (-ами) на моей локальной ветке (которая может занять несколько дней/недель), я теперь просто:
git checkout -b dcommit_helper_for_svnbranch svnbranch
git merge --squash huge_merge_work_with_messy_nonlinear_history
git commit 'nice merge summary' # single parent, straight from the fresh svnbranch
git dcommit
Я знаю, что отслеживание слияния не будет отлично работать с svn-side, пока мы полностью не переключимся. Я не могу дождаться этого.
ОБНОВЛЕНИЕ: @Kevin запросил более подробную информацию о процессе слияния ветвей svn. Есть много статей, сообщений там, но в качестве новичков я нашел некоторые из запутывающих/вводящих в заблуждение/устаревший. Во всяком случае, как я это делаю в эти дни (конечно, застрял с git -svn после этого дела слияния, как и некоторые недавно инфицированные коллеги).
git svn clone -s http://svn/path/to/just-above-trunk # the slowest part, but needed only once ever..you can every single branch from the svn repo since revision #1. 2)
git svn fetch # later, anytime: keep it up to date, talking to svn server to grab new revisions. Again: all branches - and yet it usually a faster for me than a simple 'svn up' on the trunk:)
# Take a look, sniff around - some optional but handy commands:
git gui & # I usually keep this running, press F5 to refresh
gitk --all # graph showing all branches
gitk my-svn-target-branch svn-branch-to-merge # look at only the branches in question
git checkout -b my-merge-fun my-svn-target-branch # this creates a local branch based on the svn one and switches to it..before you notice :)
# Some handy config, giving more context for conflicts
git config merge.conflictstyle diff3
# The actual merge..
git merge svn-branch-to-merge # the normal case, with managable amount of conflicts
# For the monster merge, this was actually a loop for me: due to the sheer size, I split up the 2 year period into reasonable chunks, eg. ~1 months, tagged those versions ma1..ma25 and mb1..mb25 on each branch using gitk, and then repeated these for all of them
git merge ma1 # through ma25
git merge mb1 # through mb25
# When running into conflicts, just resolve them.. low tech way: keep the wanted parts, then "git add file" but you can
git mergetool # loops through each conflicted file, open your GUI mergetool of choice..when successful, add the file automatically.
git mergetool my-interesting-path # limit scope to that path
На самом деле я предпочел использовать 'git gui встроенную интеграцию mergetool (щелкните правой кнопкой мыши на конфликтующий файл). Это немного ограничено, так что см. Мой маленький патч выше, который позволяет вам подключать оболочку script, где вы можете ссылаться на любые слияния, которые вы предпочитаете (я пробовал различные из них иногда параллельно, поскольку они вызывали удивительное количество горя. но обычно я застрял с kdiff3..
Когда шаг слияния идет хорошо (без конфликтов), фиксация слияния выполняется автоматически; в противном случае вы разрешаете конфликты, а затем
git commit # am usually doing this in the git gui as well.. again, lightning fast.
Последняя фаза. Заметим, что до сих пор у нас были только локальные коммиты, а не разговоры с сервером svn. Если вы не использовали -squash или другие трюки, теперь у вас есть график, в котором у вашего слияния есть 2 родителя: советы ваших ветвей svn-mirror. Теперь это обычная gotcha: svn может брать только линейную историю.. поэтому 'git -svn' упрощает ее, просто отбрасывая второго родителя (svn-branch-to-merge в вышеприведенном случае).. так что реальное слияние отслеживание пропадает на стороне svn. но в противном случае это будет хорошо в этом случае.
Если вы хотите более безопасный/более чистый способ, то сюда приходит мой предыдущий фрагмент: просто выполните окончательное слияние с -squash. Адаптировался ранее к этому потоку:
git checkout -b dcommit_helper_for_svnbranch my-svn-target-branch # another local workbranch.. basically needed as svn branches (as any other remote branch) are read-only
git merge --squash my-merge-fun
git commit 'nice merge summary' # single parent, straight from the fresh svn branch
git dcommit # this will result in a 'svn commit' on the my-svn-target-branch
Упс, это слишком длинное, останавливаясь до слишком поздно.. Удачи.