Является ли git-svn dcommit после слияния в git опасным?


моя мотивация для опробования git-svn-это легкое слияние и ветвление. Затем я заметил, что человек git-svn (1) говорит:

запуск git-merge или git-pull не рекомендуется на ветке, которую вы планируете на внесение изменений через dcommit от. Subversion не представляет слияния в любом разумная или полезная мода; поэтому пользователи, использующие Subversion, не могут видеть слияния вы сделали. Кроме того, если вы объедините или вытащите из git ветвь, которая является зеркалом ветви SVN, dcommit может совершить этот не та ветка.

означает ли это, что я не могу создать локальную ветвь из svn/trunk (или ветви), взломать, слить обратно в svn/trunk, а затем dcommit? Я понимаю, что пользователи svn увидят тот же беспорядок, который сливается в svn pre 1.5.x всегда были, но есть ли другие недостатки? Последнее предложение меня тоже беспокоит. Люди обычно делают такие вещи?

6 132

6 ответов:

на самом деле, я нашел еще лучший способ с --no-ff опция на git merge. Вся эта техника сквоша, которую я использовал раньше, больше не требуется.

мой новый рабочий процесс теперь выглядит следующим образом:

  • у меня есть ветвь "master", которая является единственной ветвью, из которой я dcommit, и которая клонирует репозиторий SVN (-s предположим, что у вас есть стандартный макет SVN в репозитории trunk/,branches/, и tags/):

    git svn clone [-s] <svn-url>
    
  • я работаю в местном филиале "work" (-b создает ветку "работа")

    git checkout -b work
    
  • зафиксировать локально в ветке "работа" (-s закончить свое сообщение). В дальнейшем, я предполагаю, что вы сделали 3 локальные коммиты

    ...
    (work)$> git commit -s -m "msg 1"
    ...
    (work)$> git commit -s -m "msg 2"
    ...
    (work)$> git commit -s -m "msg 3"
    

теперь вы хотите совершить на сервере SVN

  • [в конце концов] спрятать изменения, которые вы не хотите видеть совершено на сервере SVN (часто вы комментировали какой-то код в главном файле только потому, что хотите ускорить компиляцию и сосредоточиться на данной функции)

    (work)$> git stash
    
  • перебазируйте главную ветвь с репозиторием SVN (для обновления с сервера SVN)

    (work)$> git checkout master
    (master)$> git svn rebase
    
  • вернитесь в рабочую ветвь и перебазируйтесь с master

    (master)$> git checkout work
    (work)$> git rebase master
    
  • убедитесь, что все в порядке, используя, например:

    (work)$> git log --graph --oneline --decorate
    
  • теперь пришло время объединить все три коммита из ветви "работа" в "мастер", используя этот замечательный --no-ff опции

    (work)$> git checkout master
    (master)$> git merge --no-ff work
    
  • вы можете заметить состояние журналов:

    (master)$> git log --graph --oneline --decorate
    * 56a779b (work, master) Merge branch 'work'
    |\  
    | * af6f7ae msg 3
    | * 8750643 msg 2
    | * 08464ae msg 1
    |/  
    * 21e20fa (git-svn) last svn commit
    
  • теперь вы, вероятно, хотите редактировать (amend) последняя фиксация для ваших парней SVN (в противном случае они будут видеть только одну фиксацию с сообщением " Merge branch "работа""

    (master)$> git commit --amend
    
  • наконец зафиксировать на сервере SVN

    (master)$> git svn dcommit
    
  • вернитесь к работе и в конечном итоге восстановите свои спрятанные файлы:

    (master)$> git checkout work
    (work)$> git stash pop
    

создание локальных ветвей определенно возможно с помощью git-svn. Пока вы просто используете локальные ветви для себя, а не пытаетесь использовать git для слияния между ветвями SVN вверх по течению, вы должны быть в порядке.

У меня есть ветка" master", которую я использую для отслеживания сервера svn. Это единственная ветка, из которой я dcommit. Если я делаю какую-то работу, я создаю ветку темы и работаю над ней. Когда я хочу совершить его, я делаю следующее:

  1. совершить все в ветку темы
  2. git svn rebase (разрешите любые конфликты между вашей работой и svn)
  3. git checkout master
  4. git svn rebase (это делает следующий шаг быстрого слияния, см. комментарии Аарона ниже)
  5. git merge topic_branch
  6. разрешить любые конфликты слияния (там не должно быть в этот момент)
  7. git svn dcommit

У меня тоже есть еще ситуация, когда мне нужно поддерживать некоторые локальные изменения (для отладки), которые никогда не должны подталкиваться к svn. Для этого у меня есть вышеупомянутая главная ветвь, но также ветвь под названием "работа", где я обычно работаю. Ветви темы разветвлены от работы. Когда я хочу совершить работу там, я проверяю master и использую cherry-pick, чтобы выбрать коммиты из рабочей ветви, которую я хочу совершить в svn. Это потому, что я хочу избежать совершения трех локальных изменений. Затем, я dcommit от мастера ветви и перебазировать все.

стоит работает git svn dcommit -n во-первых, чтобы убедиться, что вы собираетесь совершить именно то, что вы намерены совершить. В отличие от git, переписывать историю в svn сложно!

Я чувствую, что должен быть лучший способ объединить изменения в ветке темы, пропуская эти локальные изменения, чем использовать cherry-pick, поэтому, если у кого-то есть идеи, они будут приветствоваться.

простое решение: удалите ветку "работа" после слияния

короткий ответ: вы можете использовать git, как вам нравится (см. ниже для простого рабочего процесса), включая слияние. Просто убедитесь, что следовать каждому'git merge work "С"git branch-d work ' для удаления временной рабочей ветви.

фон объяснение: Проблема слияния/dcommit заключается в том, что всякий раз, когда вы "git svn dcommit" ветвь, история слияния этой ветви "сплющена": git забывает обо всех операциях слияния, которые вошли в эту ветвь: сохраняется только содержимое файла, но тот факт, что это содержимое (частично) пришло из определенной другой ветви, теряется. Смотрите:почему ГИТ внесение изменений через dcommit СВН потерять историю коммитов слияния для местных филиалов?

(Примечание: существует не так много, что git-svn может сделать об этом: svn просто не понимает гораздо более мощные слияния git. Итак, внутри SVN репозиторий эта информация слияния не может быть представлена каким-либо образом.)

но это весь проблема. Если вы удалите ветвь "работа" после того, как она была объединена в "главную ветвь", то ваш репозиторий git на 100% чист и выглядит точно так же, как ваш репозиторий svn.

мой рабочий процесс: Конечно, я сначала клонировал удаленный репозиторий svn в локальный репозиторий git (это может занять некоторое время):

$> git svn clone <svn-repository-url> <local-directory>

все затем работа происходит внутри "local-directory". Всякий раз, когда мне нужно получить обновления с сервера (например, "svn update"), я делаю:

$> git checkout master
$> git svn rebase

я делаю всю свою работу по разработке в отдельной ветке "работа", которая создается следующим образом:

$> git checkout -b work

конечно, вы можете создать столько ветвей для своей работы, сколько вам нравится, и объединить и перебазировать между ними, как вам нравится (просто удалите их, когда вы закончите с ними-как описано ниже). В моей нормальной работе, я совершаю очень часто:

$> git commit -am '-- finished a little piece of work'

следующий шаг (git rebase-i) является необязательным --- это просто очистка истории перед архивированием ее на svn: как только я достиг стабильного камня мили, который я хочу поделиться с другими, я переписываю историю этой ветви "работы" и очищаю сообщения фиксации (другим разработчикам не нужно видеть все маленькие шаги и ошибки, которые я сделал по пути --- просто результат). Для этого я делаю

$> git log

и скопируйте хэш sha-1 последнего коммита то есть жить в репозитории svn (как указано в git-svn-id). Тогда я звоню

$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb

просто вставьте SHA-1 хэш нашего последнего svn commit вместо моего. Вы можете прочитать документацию с помощью "Git help rebase" для получения подробной информации. Короче говоря: эта команда сначала открывает редактор, представляющий ваши коммиты ---- просто измените "pick" на "squash" для всех тех коммитов, которые вы хотите раздавить с предыдущими коммитами. Конечно, первая строка должна остаться в качестве "выбора". Таким образом, вы может сконденсировать ваши многочисленные маленькие коммиты в одну или несколько значимых единиц. Сохраните и выйдите из редактора. Вы получите другой редактор с просьбой переписать сообщения журнала фиксации.

чтобы внести изменения в репозиторий svn, я делать:

$> git checkout master
$> git svn rebase

теперь мы вернулись в старую ветку "master", обновленную со всеми изменениями, которые произошли за это время в репозитории svn (ваши новые изменения скрыты в ветке "work").

если есть изменения, которые могут конфликтовать с вашими новыми изменениями "работы", вы должны решить их локально, прежде чем вы можете подтолкнуть свою новую работу (см. подробности ниже). Затем мы можем нажать наши изменения в svn:

$> git checkout master
$> git merge work        # (1) merge your 'work' into 'master'
$> git branch -d work    # (2) remove the work branch immediately after merging
$> git svn dcommit       # (3) push your changes to the svn repository

Примечание 1: команда 'git branch-d work' это довольно безопасно: он позволяет только удалять ветви, которые вам больше не нужны (потому что они уже объединены в вашу текущую ветку). Если вы выполняете эту команду по ошибке, прежде чем объединить свою работу с веткой "master", вы получите сообщение об ошибке.

примечание 2: обязательно удалите свою ветку с помощью "git branch-d work"между слияние и внесение изменений через dcommit: если вы попытаетесь удалить ветку после внесение изменений через dcommit, вы получите сообщение об ошибке: когда вы делаете 'в Git с SVN внесение изменений через dcommit', git забывает, что ваша ветвь была объединена с "мастером". Вы должны удалить его с помощью "git branch-D work", который не выполняет проверку безопасности.

теперь я сразу создаю новую ветку "работа", чтобы избежать случайного взлома на ветке "мастер":

$> git checkout -b work
$> git branch            # show my branches:
  master
* work

интеграция вашей "работы" с изменениями на SVN: Вот что я делаю, когда "git svn rebase" показывает, что другие изменили репозиторий svn, пока я работал над своей "работой" филиал:

$> git checkout master
$> git svn rebase              # 'svn pull' changes
$> git checkout work           # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master            # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed

$> git checkout master         # try again to push my changes
$> git svn rebase              # hopefully no further changes to merge
$> git merge integration       # (1) merge your work with theirs
$> git branch -d work          # (2) remove branches that are merged
$> git branch -d integration   # (2) remove branches that are merged
$> git svn dcommit             # (3) push your changes to the svn repository

существуют более мощные решения: Представленный рабочий процесс упрощен: он использует полномочия git только в каждом раунде "update/hack / dcommit" - - - но оставляет долгосрочную историю проекта такой же линейной, как и репозиторий svn. Это нормально, если вы просто хотите начать использовать git merges в небольших первых шагах в устаревшем проекте svn.

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

Грег Хьюгилл ответ на вершине не является безопасным! Если какие-либо новые коммиты появились на транке между двумя "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.

git svn fetch
git checkout remotes/trunk -b big-merge
git merge --squash svn-branch

на данный момент у вас есть все изменения из svn-ветви, сжатой в один фиксатор, ожидающий в индексе

git commit

Перебазируйте локальную ветвь git на главную ветвь git, затем dcommit, и таким образом похоже, что вы сделали все эти коммиты последовательно, чтобы люди svn могли видеть это линейно, как они привыкли. Поэтому, предполагая, что у вас есть локальная ветвь под названием topic, вы можете сделать

git rebase master topic

который затем будет воспроизводить ваши коммиты над главной веткой, готовой для вас к dcommit