Моя мотивация попробовать git-svn - это легкое слияние и ветвление. Затем я заметил, что мужчина git-svn (1) говорит:
Запуск git-merge или git-pull НЕ рекомендуется в ветке, из которой вы планируете выйти. Subversion не представляет слияния каким-либо разумным или полезным способом; таким образом, пользователи, использующие Subversion, не могут видеть сделанные вами слияния. Более того, если вы объединяете или извлекаете ветку git, которая является зеркалом ветки SVN, dcommit может зафиксировать неправильную ветку.
Означает ли это, что я не могу создать локальную ветку из svn / trunk (или ветки), взломать, объединить обратно в svn / trunk, а затем dcommit? Я понимаю, что пользователи svn увидят тот же беспорядок, который всегда был в svn pre 1.5.x, но есть ли другие недостатки? Последнее предложение меня тоже беспокоит. Люди обычно делают такие вещи?
--mergeinfo=<mergeinfo>
опция, которая может передавать информацию о слиянии в SVN. Не уверен, как это следует использовать, хотя.Ответы:
На самом деле, я нашел еще лучший способ с
--no-ff
опцией git merge. Вся эта техника игры в сквош, которую я использовал раньше, больше не требуется.Мой новый рабочий процесс теперь выглядит следующим образом:
У меня есть филиал «мастер» , который является единственной отраслью , что я dcommit из и что клон репозитория SVN (
-s
предположим , у вас есть стандартное расположение SVN в хранилищеtrunk/
,branches/
иtags/
):Я работаю на местном филиале "Работа" (
-b
создает филиал "Работа")фиксировать локально в ветке "работа" (
-s
чтобы подписать ваше сообщение о коммите). В дальнейшем, я полагаю, вы сделали 3 локальных коммитовТеперь вы хотите зафиксировать на сервере SVN
[В конце концов] спрятать изменения, которые вы не хотите видеть зафиксированными на сервере SVN (часто вы комментировали некоторый код в основном файле только потому, что вы хотите ускорить компиляцию и сосредоточиться на конкретной функции)
перебазировать основную ветку с хранилищем SVN (для обновления с сервера SVN)
вернитесь в рабочую ветку и выполните ребаз с мастером
Убедитесь, что все в порядке, например:
Теперь пришло время объединить все три коммита из ветви "работа" в "мастер", используя эту замечательную
--no-ff
опциюВы можете заметить статус журналов:
Теперь вы, вероятно, захотите отредактировать (
amend
) последний коммит для ваших SVN-парней (в противном случае они увидят только один коммит с сообщением "Merge branch 'work'"Наконец зафиксировать на сервере SVN
Вернитесь к работе и в конечном итоге восстановите ваши спрятанные файлы:
источник
--no-ff
опцией, вы явно создаете коммит слияния (коммит с двумя родителями) вместо ускоренной перемотки вперед. Чтобы гарантировать, что все коммиты в ветви svn-tracking являются коммитами с одним родителем, все слияния должны быть либо ускоренными (--ff-only
может помочь в этом), либо, если транк изменился за вашей спиной, а--squash
, верно?git svn dcommit
переписывает git commit, который вы ей даете. Это означает, что вы теряете своего другого родителя, и теперь в вашем git-репо нет записи, в которую вы когда-либо объединяли эту веткуmaster
. Это также может оставить ваш рабочий каталог в несогласованном состоянии.git merge --no-ff work -m "commit message"
вместо дополнительногоgit commit --amend
шагаСоздание локальных веток определенно возможно с помощью git-svn. Пока вы просто используете локальные ветки и не пытаетесь использовать git для слияния между ветвями SVN верхнего уровня, все будет в порядке.
У меня есть «главная» ветка, которую я использую для отслеживания сервера SVN. Это единственная ветка, из которой я делаю коммит. Если я делаю какую-то работу, я создаю ветку тем и работаю над ней. Когда я хочу зафиксировать это, я делаю следующее:
У меня также есть другая ситуация, когда мне нужно сохранить некоторые локальные изменения (для отладки), которые никогда не должны передаваться в SVN. Для этого у меня есть вышеупомянутая основная ветка, но также есть ветка под названием «работа», где я обычно работаю. Тематические ветки разветвлены от работы. Когда я хочу зафиксировать работу там, я извлекаю master и использую cherry-pick, чтобы выбрать коммиты из рабочей ветки, которые я хочу зафиксировать в svn. Это потому, что я хочу избежать фиксации трех локальных изменений. Затем я делаю коммит из ветки master и перебазирую все.
Стоит побежать
git svn dcommit -n
сначала, чтобы убедиться, что вы собираетесь совершить именно то, что намереваетесь совершить. В отличие от git, переписывать историю в svn сложно!Я чувствую, что должен быть лучший способ объединить изменения в ветке темы, пропуская эти локальные изменения изменений, чем использование cherry-pick, поэтому, если у кого-то есть какие-либо идеи, они будут приветствоваться.
источник
Простое решение: удалить ветку 'работа' после слияния
Краткий ответ: Вы можете использовать git так, как вам нравится (простой рабочий процесс см. Ниже), включая слияние. Просто убедитесь, что следите за каждым ' git merge work ' с ' git branch -d work », чтобы удалить временную рабочую ветку.
Фоновое объяснение: проблема слияния / dcommit заключается в том, что всякий раз, когда вы 'git svn dcommit' ветвь, история слияния этой ветки 'сплющивается': git забывает обо всех операциях слияния, которые были в этой ветке: сохраняется только содержимое файла, но тот факт, что этот контент (частично) пришел из определенной другой ветки, теряется. Смотрите: Почему git svn dcommit теряет историю коммитов слияния для локальных веток?
(Примечание: git-svn мало что может с этим поделать: svn просто не понимает гораздо более мощных git-слияний. Таким образом, внутри svn-хранилища эта информация о слиянии не может быть представлена каким-либо образом.)
Но это все проблема. Если вы удалите ветку 'work' после того, как она будет объединена с 'master веткой', то ваш репозиторий git будет на 100% чист и выглядит точно так же, как ваш svn-репозиторий.
Мой рабочий процесс: Конечно, я сначала клонировал удаленный svn-репозиторий в локальный git-репозиторий (это может занять некоторое время):
Вся работа происходит внутри «локального каталога». Всякий раз, когда мне нужно получить обновления с сервера (например, 'svn update'), я делаю:
Я делаю всю свою работу по разработке в отдельной ветке 'работа', которая создается следующим образом:
Конечно, вы можете создать столько веток для вашей работы, сколько захотите, а также объединять и перебазировать их между собой по своему усмотрению (просто удалите их, когда закончите с ними - как описано ниже). В своей обычной работе я совершаю очень часто:
Следующий шаг (git rebase -i) не обязателен - он просто очищает историю перед тем, как архивировать ее на SVN: Как только я достиг стабильного мили, которым хочу поделиться с другими, я переписываю историю этой «работы» разветвляйте и очищайте сообщения коммита (другие разработчики не должны видеть все маленькие шаги и ошибки, которые я сделал на пути - только результат). Для этого я делаю
и скопируйте хэш sha-1 последнего коммита, который находится в репозитории svn (как указано в git-svn-id). Тогда я звоню
Просто вставьте хэш sha-1 нашего последнего SVN-коммита вместо моего. Вы можете прочитать документацию с помощью git help rebase для получения подробной информации. Вкратце: эта команда сначала открывает редактор, представляющий ваши коммиты ---- просто измените 'pick' на 'squash' для всех тех коммитов, которые вы хотите раздавить с предыдущими коммитами. Конечно, первая строка должна оставаться в качестве «выбора». Таким образом, вы можете сконцентрировать ваши многочисленные маленькие коммиты в одну или несколько значимых единиц. Сохраните и выйдите из редактора. Вы получите другой редактор с просьбой переписать сообщения журнала коммита.
Вкратце: после того, как я закончу «взлом кода», я массирую свою ветку «работа», пока она не увидит, как я хочу представить ее другим программистам (или как я хочу увидеть работу через несколько недель, когда я просматриваю историю). ,
Чтобы отправить изменения в репозиторий svn, я делаю:
Теперь мы вернулись к старой ветке 'master', обновленной со всеми изменениями, произошедшими за это время в репозитории svn (ваши новые изменения скрыты в ветке 'work').
Если есть изменения, которые могут конфликтовать с вашими новыми «рабочими» изменениями, вам нужно разрешить их локально, прежде чем вы сможете отправить свою новую работу (подробности см. Ниже). Затем мы можем отправить наши изменения в SVN:
Примечание 1. Команда 'git branch -d work' довольно безопасна: она позволяет вам удалять только те ветки, которые вам больше не нужны (потому что они уже объединены с вашей текущей веткой). Если вы выполнили эту команду по ошибке до объединения вашей работы с веткой 'master', вы получите сообщение об ошибке.
Примечание 2: Обязательно удалите ветку с помощью 'git branch -d work' между слиянием и dcommit: если вы попытаетесь удалить ветку после dcommit, вы получите сообщение об ошибке: Когда вы делаете 'git svn dcommit', git забывает, что ваша ветвь была объединена с 'master'. Вы должны удалить его с помощью 'git branch -D work', который не выполняет проверку безопасности.
Теперь я немедленно создаю новую ветку 'работа', чтобы избежать случайного взлома ветки 'master':
Интеграция вашей «работы» с изменениями в svn: Вот что я делаю, когда «git svn rebase» показывает, что другие изменили репозиторий svn, когда я работал над моей веткой «работа»:
Существуют более мощные решения: представленный рабочий процесс упрощен: он использует возможности git только в каждом раунде «update / hack / dcommit» - но оставляет долгосрочную историю проекта столь же линейной, как и хранилище svn. Это нормально, если вы просто хотите начать использовать git merges небольшими первыми шагами в старом проекте svn.
Когда вы познакомитесь с git merging, не стесняйтесь исследовать другие рабочие процессы: если вы знаете, что делаете, вы можете смешивать git merges с svn merges ( используя git-svn (или аналогичный) просто для того, чтобы помочь с svn merge? )
источник
git merge --squash work
, почему бы не сделать это? Я могу видеть выполнение коммитов сквоша в ветви перед слиянием, если вы создаете более одного «пика» (скажем, у вас есть 8 коммитов, и вы превращаете каждый из 4 коммитов в 1, а слияние 2 коммитов - с мастером). Также, когда я обновляю свою ветку 'работа', я делаюrebase
это проще, чем создание другой ветки для моей ветки и выполнение слияний ...Ответ Грега Хьюгилла сверху небезопасен! Если между двумя «git svn rebase» в транке появятся какие-либо новые коммиты, слияние не будет происходить быстро.
Это может быть обеспечено использованием флага «--ff-only» для git-merge, но я обычно не запускаю «git svn rebase» в ветке, а только «git rebase master» (предполагая, что это только локальный филиал). Тогда после этого «git merge thebranch» будет гарантированно ускорен.
источник
Безопасный способ объединить svn-ветки в git - это использовать git merge --squash. Это создаст единый коммит и остановит вас, чтобы добавить сообщение.
Допустим, у вас есть тема svn branch, которая называется svn-branch.
к этому моменту все изменения из svn-ветви сведены в один коммит, ожидающий в индексе
источник
Перебазируйте локальную ветку git на главную ветку git, затем dcommit, и, таким образом, похоже, что вы сделали все эти коммиты последовательно, чтобы svn люди могли видеть это линейно, как они привыкли. Итак, если у вас есть локальная ветка с названием topic, вы можете сделать
который затем воспроизведет ваши коммиты через главную ветку, готовую для вас
источник