Skip to content

Instantly share code, notes, and snippets.

@Busyrev
Last active November 6, 2018 12:08
Show Gist options
  • Save Busyrev/a530205abaa8caf69674667ba2a7e7d5 to your computer and use it in GitHub Desktop.
Save Busyrev/a530205abaa8caf69674667ba2a7e7d5 to your computer and use it in GitHub Desktop.

svn how we do it.

Это старая документация по работе с SVN, в данный момент код почти везде переехал в hg, однако, если вы в наши дни работаете с svn некоторые советы и рецепты отсюда вы можете найти полезными. Настоятельно рекомендую прочитать http://svnbook.red-bean.com/nightly/en/index.html целиком, и читать нужные разделы этой книги когда вы хотите сделать что-то из этих советов.

Почему svn:

  • репо design 700GB, только svn.
  • на дев сервере работает 70 человек, у многих чекаут нескольких проектов, в проекте хранитятся и ассеты: картинки, флешки. Размер чекаута имеет значение.
  • локальные ветки
  • Про локальные ветки: можно сделать что-то в локальной ветки и забыть на ноуте. Или HDD сгорел и всё. Наличие локальных веток располагает к локальным изменениям которых нет на сервере.
  • Вопросы с избирательным перекидыванием коммитов принципиально лучше не становятся.
  • Работа с ветками принципиально лучше не становится. (на самом деле таки становится)
  • Держать git/hg для кода и svn для ассетов, это точно хуже чем svn для всего (ага, в 2018 году на гитхабе используем git, во внутренней разработке hg и svn для ассетов, собери три vcs и получи ачивку!)
  • Ветвить разрешено только из одной точки. Обычно это корень репо. Категорически запрещается создавать мержинфо в любых подкаталогах!!! При обнаружении трубить вот все трубы и чинить. (можно если очень осторожно, но вообще лучше считать что нельзя)

есть ^/trunk ^/branches ^/tags

Определения

  • Дев инсталляция - инсталляция продукта для работы геймдизайнеров, художников и всех желающих для разработки и проверки функциональности.
  • QA инсталляция - инсталляция продукта для проверки функциональности стабилизированного состояния, для репетиции выкатки, это симуляция боя.
  • Бой - инсталляции продукта с которыми работают пользователи.

Для тех кто видел ветки и svn давно

  • ^
  • mergeinfo
  • --reintegrate

Тезисы нашего workflow

  • Мы девелопим всякие мелкие штуки в ^/trunk
  • Иногда мы делаем фичебранчи. Иногда не делаем.
  • Мы делаем стейбл теги.
  • Мы катим в бой только теги.
  • Мы никогда не коммитим в теги. Если надо добавить что-то в стабильный тег, то это новый стабильный тег. (Хотя бывают редкие исключения когда баг вылавливается в бою, там будет коммит с боя в тег потом мердж его в транк и потом из транка в стейблы).
  • Мы делаем хотфиксы в транке и мержим их в стейблы, а не наоборот. Объяснение: Фикс в первую очередь не должен потеряться потому сначала транк, а потом мерж в стейбл, иначе пофиксив в стейбле и удостоверившись что на QA и в бою всё работает можно забыть.
  • Мы фиксируем externals в стабильных ветках и бранчах
  • Стейблы порождаются из транка, а не из других стейблов, ибо наследование стейблов это система с накоплением ошибки. Если мы используем --record-only например или странные мерджи. Новый стейбл не наследует косяков предыдущих.
  • Мы хотим как-то помечать что бранчи реинтегрированы в транк //TODO рассмотреть как

Кейс 0. Мы наделали новых файлов, и хотим добавить их но не перечислять руками

  • Переходим в корень working copy
  • svn up // всегда надо апаться
  • svn st // смотрим что у нас, ревьювим, там со статусом ? только то что мы хотим закоммитить, если там есть с таким статусом что-то что мы не хотим коммитить то предварительно добавим это в svn:ignore
  • svn add --force . // рекурсивно добавит всё что не добавлено.
  • svn st // теперь ни одного файла с ? нету.

Кейс 1. Мы сделали так, что working copy в транке, есть какие-то локальные изменения (это может быть либо написали новое, либо мердж фичебранча.)

  • Переходим в корень working copy
  • svn up // всегда надо апаться
  • svn st // смотрим что у нас, ревьювим перед коммитом
  • svn info // всегда проверяем где мы находимся и куда коммитим, например мы в транке
  • svn ci -m 'super feature' // коммитим.
  • svn up // всегда надо апаться
  • Теперь мы идём на дев инсталляцию которая смотрит в транк и проверяем что всё ок.

Кейс 2. Теперь мы хотим что-то стабилизировать и протестировать.

  • svn up // всегда надо апаться
  • svn st // проверяем что working copy не содержит изменений
  • svn ls ^/branches //смотрим тут какие есть стейбл бранчи и выбираем в какой мы хотим это поместить. Обычно это последний. Или всего много и мы хотим новый

Если в существующий бранч

  • svn sw ^/branches/stable-3 // переключаемся на стейбл
  • svn pg svn:mergeinfo // смотрим какие коммиты из транка были уже смерджены, чтобы понять насколько глубоко надо смотреть историю транка
  • svn log -l n ^/trunk // смотрим что тут есть
  • svn merge ^/trunk -r n1:n2 // мержим в свою локальную working copy, это операция сторого локальная и если не нравится можно ревертнуть. Могут возникнуть конфликты, но редко.
  • тут нужно проверить что всё в принципе работает.
  • см Кейс 1.

Если в новый

  • svn pg svn:externals . // смотрим что с externals, с какой версией работал транк
  • svn cp ^/trunk ^/branches/stable-4 -m 'new branch for this fetures' // новый бранч для фич, это сразу удалённая операция
  • svn sw ^/branches/stable-4
  • svn ps ... // TODO // фиксируем externals
  • см Кейс 1.
  • svn up // всегда надо апаться
  • Теперь идём на QA инсталляцию и тестируем стейбл там.

Кейс 3. Мы хотим что-то выкатить в бой

  • svn ls ^/tags/ // смотрим какой стейбл тег есть последний, например stable-3.0
  • svn cp ^/branches/stable-3 ^/tags/stable-3.1
  • Теперь идём на QA инсталляцию и тестируем это там.
  • Теперь можно свичнуть в бою на этот тег

Кейс 4. Новый бранч. Мы хотим девелопить что-то в новом фиче бранче, или наделали что-то в working copy и хотим отправить в новый бранч.

  • svn up // всегда надо апаться

  • svn st // тут может быть и не пусто, но т.к. мы сделали ап, а cp это удалённая команда, свитч пройдёт гладко без конфликтов и косяков.

  • svn info // всегда проверяем где мы находимся

  • svn cp ^/trunk ^/branches/my-feature-branch -m 'branch for my crazy feature' //создаём бранч для фичи

  • svn sw ^/branches/my-feature-branch

  • девелопим.

  • Периодически синкаем транк к себе, Кейс 5. Дабы разруливать конфликты по мере возникновения, а не пачками потом. Опционально. Злобные буратины могут этого не делать и разруливать потом гору конфликтов.

Кейс 5. Синхронизация фичебранча с транком. // TODO лучше сформулировать

  • svn up // всегда надо апаться

  • svn st // тут должно быть чисто, если не чисто, идём в Кейс 1 и коммитим

  • svn info // всегда проверяем где мы находимся и куда коммитим, в данном случае мы в фичебранче

  • svn merge ^/trunk // просто синкануть всё что есть в транке. Тут могут возникнуть конфликты, разруливаем на месте.

  • svn st // смотрим что приехало, что все конфликты которые и были разрешены

  • svn ci -m "sync with trunk" // коммитим синк, можно, если не лень писать 'MFC n1:n2'

Кейс 6. Реинтеграция фичебранча назад в транк. Ключик --reintegrate с 1.8 не требуется.

  • svn up // всегда надо апаться
  • svn st // тут должно быть чисто, если не чисто, идём в Кейс 1 и коммитим
  • svn sw ^/branches/my-feature-branch // свичнемся на бранч, если не были в нём.
  • Делаем Кейс 5 для синка в транка. Этим мы сильно уменьшаем вероятность конфликта при merge.
  • svn sw ^/trunk // переключаемся на транк
  • svn merge ^/branches/my-feature-branch // мержим на свою working copy бранч, конфликтов быть не может т.к. мы только что синхронизировали бранчи. Может быть конфликт если от синка до текущего момента кто-то что-то коммитнул в транк
  • svn st //смотрим что всё хорошо
  • проверяем что оно в принципе работает
  • svn ci -m 'reintegrated feature' // коммитим всё это дело.
  • по желанию можно удалить фичебранч // TODO возможно не удаляем а маркируем как-то их
  • // TODO: рассмотреть можно ли продолжать работу в бранче

Кейс 7. Откатить ошибочный коммит

  • svn up // всегда надо апаться
  • svn st // проверяем что working copy не содержит изменений
  • svn info // всегда проверяем где мы находимся, например в транке
  • svn log -l 10 // смотрим на лог, например нам не нравится коммт 25, который на самом деле дифф между ревизиями 24:25
  • svn megre ^/trunk -r 25:24 // мержим этот же бранч на working copy в обратном порядке, svn понимает это именно так, применение диффа в обратную сторону, что по сути есть откат коммита
  • svn st // смотрим на всякий случай
  • svn ci -m 'reverted commit 25' //коммитим это

Кейс 8. Почему избирательные мержи коммитов в неправильном порядке могут быть опасны и почему за ними надо внимательно следить.

  • потому что при удалении несуществующей строки свн и глазом не моргнёт и пропустит мерж. при накате потом добавленной строки добавит // TODO

Кейс 9. Бранчей скопилось много, в транке mergeinfo стало неудобно большим. // TODO

Кейс 10. Как пометить коммит что он никогда не должен попасть в конкретный стейбл. --record-only и зачем он нужен. // TODO

Кейс 11. Удалил ветку и скопировал туда, без апа или с апом, рассмотрет // TODO

Кейс 12. Svn:ignore // TODO

Кейс 13. Sparse checkout

  • svn co svn://svn.crazypanda.ru/farmstory/client/trunk --depth=empty farmstory-client
  • cd farmstory-client
  • svn up --set-depth=infinity ai assets3d fla

Кейс 14. Методология поиска истории после переноса

тортойсом

ещё тортойс

  • http://service.crazypanda.ru/v/clip2net/h/M/kGhFX93HDS.png
  • Другой вариант это апнуться на версию до переноса и смотреть там любыми тулами
  • И ещё вариант svn diff -r NUMBER ^/path/to/file (именно удалённый путь) или svn log или что там может быть ещё надо

Кейс 15. У нас много изменений над транком, транк давно не апали, ап на локальной копии при водит к конфликтам, не хотим апать а хотим отправить в ветку.

  • svn info //смотрим ревизию

  • svn cp ^/trunk ^/branches/myTrash -r ревизию -m 'new branch for this fetures'

  • svn diff ^/trunk ^/branches/myTrash // тут убеждаемся что транк ушёл от того что мы скопировали

  • svn sw ^/branches/myTrash

  • svn ci -m 'blah blah'

  • мержить назад как обычно. Отдельно пояснить разницу между этим подходом и svn cp . ^/branches/myTrash т.к. в данном случае улетит прям твой бранч локальный без знания о том что он диф над веткой, потом заколебёшься мержить

Кейс 16. Создать папку удалённо не чекаутя весь уровень

  • // TODO: есть утверждение что --parents не требуется в данном случае
  • svn mkdir --parents ^/client/tags -m " Creating tags folder"

Кейс 17. Исправляем случайный один коммит в две ветки сразу

  • Проект устроен так: в транке несколько папок, каждая по сути сама по себе проект, например в данном случае проект и тесты. Ветвим только а верхнем уровне.

  • Случайно переключил только проект на новый фичебранч и коммитнул потом скопом одним коммитом в фичебранч код и тесты в транк. Это один коммит. Хотим пофиксить.

  • выглядит так http://service.crazypanda.ru/v/clip2net/N/2/itN5B76XIN.png

  • svn up

  • svn info // убеждаемся что мы в транке, смотри неудобный коммит

  • svn merge ^/client/trunk -r9405:9404 // реверсмёржим неудобный коммит

  • svn ci -m 'removing mistaken commit' // коммитим

  • svn sw ^/client/branches/soft-tutor // переключаемся на проблемную ветку

  • svn merge ^/client/trunk // полюбому синкаем потому что рассинхрон не нужен, видим что код который мы удалили из транка, удалён и в ветке.

  • svn ci -m 'sync with trunk' // коммитим в ветку всё синканутое

  • тут я сознательно развожу мерж коммиты отдельно. Поверьте так проще.

  • svn merge ^/client/trunk -r9404:9405 --ignore-ancestry // вот тут мы мержим заново то что было удалено, без --ignore-ancestry мёрж выходит пустым, потому что в мержинфо указано что эти коммиты уже смержены

  • svn ci -m 'fixing test' // коммитим уже поправленное.

  • Вуаля, факир был трезв и фокус удался. Реинтегрируется нормально и без проблем.

Кейс 18. Много изменений в локальной копии, много новых неверсионированных файлов, как чистить?

Кейс 19. Сделать svn cp сабдира в сабдир

svn cp --parents https://svn.example.org/svnroot/ph/org/trunk/repo https://svn.example.org/svnroot/ph/org/branches/foo/repo -m "Create a 'foo' branch of /trunk/repo"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment