Попытка ответить на мой вопрос: использование git для svn merges кажется многообещающим.
Обновление: это не просто обещание, это большой успех. Короче, Линус был прав .
Только что завершили огромное слияние двух svn-веток, которые были разлучены в течение 1,5 лет; 3k файлы были изменены, получили множество конфликтов в SVN (~ 800, я думаю).
Я нашел git & git-svn спасателем:
- автоматическое разрешение конфликтов: для начала, оно дало намного меньше конфликтующих файлов (я думаю, половина)
- невероятная производительность
- отлично модель репо / ветвления , гибкие рабочие процессы: простое экспериментирование с различными подходами, такими как объединение по частям (по времени), всегда выполнение проверок работоспособности (компиляция и т. Д.); всякий раз, когда возникает проблема: просто вернитесь назад. Вы всегда можете сделать шаг назад, когда это необходимо.
- удобство использования, отличная оснастка:
git-log
(и базовые опции git-rev-parse
), ничто не может быть более мощным, чем это. Это также удобно: -p
дает вам различия за один раз; в svn вы получаете журнал, затем находите diff для этого "revision-1: revision" или используете неуклюжие пользовательские интерфейсы. Найти, когда в репо была добавлена / удалена строка, выполнить поиск по нескольким веткам одновременно
gitk
: чрезвычайно полезен для визуализации истории ветвей в сочетании с широкими возможностями поиска. Не видел ничего подобного в других инструментах, особенно не так быстро, как этот. Не берите в голову, что это в Tk, это просто блестяще
git gui
: отлично работает, даже если не самый сексуальный - отличная помощь новичку в поиске вещей
blame
: чудо. Да, он определяет, откуда исходит исходный сегмент (копирование, вставка и т. Д.)
mergetool
: гораздо более приятный опыт, чем запуск большого svn merge
, который затем останавливается каждый раз (т. Е. Каждые 5 минут), когда он сталкивается с конфликтом, нажмите «(p) ostpone», чем вручную искать конфликтующие файлы потом. Предпочтительный вариант этого встроенного в git gui
(для этого нужен крошечный патч ).
Обнаружил, что интегрированные внешние инструменты сравнения лучше настраиваются, чем в svn
.
- сменные драйверы слияния и точный контроль над ними
rebase
разрешено отфильтровывать более сложные части истории SVN
- распределение: нет необходимости приходить в офис при работе над этим, может пауза и шаг за шагом прогрессировать в поезде / самолете и т. Д.
- USB-накопитель с Unison сделал синхронизацию <-> дома кусок пирога
- это было бы невозможно без сумасшедшего сжатия git (5-летний проект с 26k коммитами, тоннами веток и двоичных файлов, проверка ствола svn: 1.9Gb => все это в полном репозитории git: 1.4Gb! )
Таким образом, это действительно может сделать разницу от кошмара к радости - особенно если вам нравится учиться (в этом случае требуются определенные усилия - я думаю, что выучите мотоцикл после велосипеда).
Несмотря на то, что я не могу заставить всех в компании немедленно переключиться - я действительно не собирался этого делать. Опять же, git-svn
спасает нас, применяя подход «первым делом». Но, учитывая реакцию коллег, переключение может произойти гораздо раньше, чем кто-либо ожидал:)
Я бы сказал - даже если мы забудем о слияниях и фиксациях, этот материал уже отлично подходит как интерфейс только для чтения для запросов, визуализации, резервного копирования и т. Д.
Оговорка:
"Не делать коммитов Git merge в
хранилище Subversion. диверсия
не обрабатывает слияния одинаково
как Git, и это вызовет проблемы.
Это означает, что вы должны держать свой Git
история развития линейная (т.е. нет
сливаясь с другими ветками, просто
перебазирования) «.
(последний абзац http://learn.github.com/p/git-svn.html)
Другим отличным источником является книга Pro Git , в разделе «Переключение активных веток» в основном говорится, что слияние работает, но dcommit
будет хранить только содержимое слияния, но история будет скомпрометирован (что нарушает последующие слияния), поэтому вы должны отбросить рабочую ветвь после слияния.
В любом случае, это имеет смысл, и на практике здесь легко избежать ловушек ... в SVN я обнаружил, что люди обычно вообще не объединяются, так что это можно рассматривать только как шаг назад, если вы пришли из git world в первом место.
Во всяком случае, dcommit просто работал для меня. Я сделал это на своем собственном рабочем месте svn, которое сохранил только для этого, поэтому избежал лишних конфликтов в этот раз. Тем не менее, я решил сделать окончательное слияние с этой рабочей ветки на ствол svn в svn (после синхронизации всего в git); --ignore-ancestry
дал лучшие результаты там.
Обновление: как я узнал позже, последние несколько шагов выше (дополнительная ветвь svn и слияние - игнорирование предков) легко избежать, просто сохраняя ветвь, от которой вы работаете, от линейной. Как Гейб говорит ниже, merge --squash
просто создает простой глупый SVN-дружественный коммит. Когда все готово к огромному слиянию (ям) в моей локальной ветке (что может занять несколько дней / недель), я бы просто:
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, пока мы не переключимся полностью. Я не могу ждать этого.
ОБНОВЛЕНИЕ : @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's 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 (щелчок правой кнопкой мыши по файлу в конфликте). Это немного ограничено, поэтому посмотрите мой маленький патч выше, который позволяет вам подключить сценарий оболочки, где вы можете вызывать любые mergetools, которые вы предпочитаете (я пробовал различные из них иногда параллельно, так как они вызывали удивительное количество горя ... но обычно Я застрял с kdiff3 ..
Когда шаг слияния проходит нормально (без конфликтов), фиксация слияния выполняется автоматически; в противном случае вы разрешаете конфликты, а затем
git commit # am usually doing this in the git gui as well.. again, lightning fast.
Последний этап. Обратите внимание, что до сих пор у нас были только локальные коммиты, пока мы не общались с сервером SVN.
Если вы не использовали --squash или другие приемы, теперь у вас есть график, на котором у вашего коммита слияния есть 2 родителя: советы ваших веток svn-mirror. Теперь это обычная ошибка: 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
Упс, это слишком долго, останавливается раньше, чем поздно .. Удачи.