Как мне сообщить git-svn об удаленной ветке, созданной после того, как я получил репо?

193

Я использую git-svnдля работы с центральным хранилищем Subversion моей компании. Недавно мы создали новую функциональную ветку в центральном репо.

Как мне рассказать об этом Git? Когда я запускаю, git branch -rя вижу только те ветки, которые существовали, когда я запускал fetchрепозиторий Subversion для инициализации моего репозитория Git?

Хэнк Гей
источник
Ответы отсюда: stackoverflow.com/questions/13376917/… также могут быть полезны.
Томаш Гандор

Ответы:

294

Вы можете вручную добавить удаленную ветку,

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch
vjangus
источник
3
просто добавив эту ссылку в документ в качестве ссылки на kernel.org/pub/software/scm/git/docs/git-svn.html
slf
1
Из .git / config довольно легко понять, как можно настроить удаленные ветви из одного / нескольких репозиториев.
Микаэль Леписто
6
Если бы я мог поднять это как восемь раз, я бы сделал. Наконец, способ добавить ветку SVN, которая добавлена ​​в нестандартном месте!
Тим Китинг
7
Я получаю fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.на шаге Git Checkout.
phpguru
17
@phpguru Попробуйте убрать флаг опции -t, чтобы он стал 'git checkout -b local-newbranch newbranch', не забудьте включить префикс удаленного компьютера в newbranch (например, origin / newbranch).
mj1531
96

Если вы хотите отслеживать ВСЕ удаленные ветви SVN, то решение так же просто, как:

git svn fetch

Это позволит получить ВСЕ удаленные ветви, которые еще не были выбраны.

Дополнительный совет: если вы сначала извлекли только ствол, а затем хотите отследить ВСЕ ветви, то отредактируйте, .git/configчтобы это выглядело так, и снова запустите git svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

Ключевые моменты urlдолжны указывать на корень хранилища, а пути, определенные в fetchи branchesдолжны быть относительноurl .

Если вы хотите выбрать только определенные ветви вместо ALL, есть хороший пример git svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

В старых версиях после того git-svn, как вы указали такие ветки, вы не сможете получать новые ветки git svn fetch. Один из обходных путей - добавление дополнительных fetchстрок, например:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

Другой обходной путь @AndyEstes: отредактируйте .git/svn/.metadataи измените значение branches-maxRevили tags-maxRevна ревизию до того, как были созданы какие-либо вновь указанные ветви или теги. Как только вы это сделаете, запустите, git svn fetchчтобы отследить новую удаленную ветку svn.

Янош
источник
1
Если вы уже получили ревизию, в которой выполнялось svn-ветвление, прежде чем устанавливать эти настройки, вы можете выполнить git svn reset.
kcm1700
3
Редактирование .git/svn/.metadataбыло очень полезным! Я добавлял в свою ветку дополнительные ветки .git/config, которые git svn fetchне улавливались - потому что номер редакции метаданных был «слишком далеко вперед». В одном случае был выбран только последний коммит из ветви. Я вручную избавился от неисправной ветви (переименованной .git/svn/refs/remotes/svn/qa/XYZк .git/svn/refs/remotes/svn/qa/XYZ~, уронил свое существование в .git/packed-refsи т.д.) ... взял в «ранний» номер версии для метаданных ... Ран , git svn fetchчтобы , наконец , получить полную историю ж / правильно, связной графа.
Старлок
8
ЭТО ДОЛЖНО БЫТЬ ПРИНЯТЫМ ОТВЕТОМ! @janos, ты только что избавил меня от головной боли! Если ты когда-нибудь приедешь в Индию, я возьму тебя на пиво!
Рупеш Шеной
1
Или: git svn fetch --all.
kenorb
1
Этот ответ удивителен, потому что он отвечает на 7 вопросов, на которые я не нашел ответов, и делает это без написания 6-страничного рассказа.
Дрой
53

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

Хэнк Гей
источник
7
@mitjak Почему это не правильный ответ, если это решение? Я не понимаю тонкости ответа.
rholmes
«решение», возможно, не «решение»
slf
1
@rholmes: Я почти уверен, что mitjak означает, что это решение вашей проблемы, но не ответ на вопрос, который вы задали. (Потому что вы задали неправильный вопрос; поскольку вы неправильно поняли проблему в то время.)
Майк Нельсон,
Это работает, когда ветвь существовала в тот момент, когда вы клонировали svn-репозиторий в git. Это не будет работать, если ветка в репозитории svn была создана впоследствии.
Петр Гладких
3
Работает нормально, когда ветка создавалась после клона, делаю это все время.
Тим Готье
15

Может быть, я как-то испортил это, но я следовал инструкциям в ответе Вьянгуса, и это почти сработало. Единственная проблема состояла в том, что newbranch, казалось, не был отделен от ствола. В gitk это было своего рода «плавающее» все само по себе; у него не было общего предка с туловищем.

Решение этого было:

  1. Найдите SHA1 последнего коммита, который произошел в транке перед созданием ветки.
  2. Найдите SHA1 первого коммита в новой ветви (возможно, сообщение «Создана новая ветка, скопировано из trunk @ 12345» или что-то в этом роде)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- не должно быть выхода. Если вывод есть, возможно, вы выбрали неправильные коммиты.
  4. git checkout local-newbranchтогда git rebase <sha1 from step 1>. Это переместится local-newbranchна новое дерево, ноremotes/newbranch все равно будет отключено.
  5. Перейдите к файлу .git/refs/remotes/newbranchи отредактируйте его, чтобы он содержал полный SHA1 нового коммита (на перебазированном newbranch), который соответствует старому коммиту, на который он в данный момент указывает. (Или может использоватьgit-update-ref refs/remotes/newbranch <new-SHA> . Спасибо, Пингер.)
  6. В следующий раз , когда вы git svn dcommitна newbranch, вы получите кучу сообщений о нем обновляемых некотором журнале. Я думаю, это нормально.

Я рекомендую держать gitk --allвсе время открытым и обновлять его, чтобы следить за тем, что вы делаете. Я все еще новичок в git и git svn, поэтому, пожалуйста, предложите усовершенствования этого метода.

MatrixFrog
источник
2
Спасибо, это звучит полезно. Около 5. вероятно, «git-update-ref refs / remotes / newbranch <new-SHA>» является более безопасным вариантом.
Зингер
Просто попробовал путь Вьянгуса снова, и это сработало отлично. Я все равно оставлю это здесь, так как это может быть ценным для кого-то ...
MatrixFrog
1
Решение vjangus всегда создает новую ветку, отсоединенную от магистрали. Я предполагаю, что это из-за того, что сам SVN не имеет ни малейшего представления о том, как копируется фактический контент.
bogdan.mustiata
Мой опыт работы с большим репозиторием git-svn заключается в том, что svn-ветки всегда создаются в git, отделенном от ствола. Должен быть какой-то способ соединить их, но я не потратил время, чтобы понять это. AFAIK, вы не можете перебазировать ветку git, которая связана с веткой svn, потому что это испортит логику dcommit. Мы только что научились жить с этим.
Спенсер
7

Упрощение ответа Вьянгуса:

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

  1. Найти ветку-копию ревизии в SVN
  2. Получить эту ревизию с помощью git-svn
  3. Создать новый локальный филиал отслеживания удаленного

Пример. URL-адрес SVN есть svn+ssh://gil@svn.myplace.com/repo. Я ищу ветку SVN newbranch. Локальная ветка git (отслеживание удаленного newbranch) будет git-newbranch.

Шаг 1: найдите редакцию ветки-копии

    # svn log - остановка при копировании svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch | хвост -4
    r7802 | кто-то | 2014-03-21 18:54:58 +0000 (пт, 21 марта 2014 г.) | 1 строка

    ветвление ГОЛОВА в новый филиал
    -------------------------------------------------- ----------------------

Таким образом, точка ветвления в SVN - это версия 7802.

Шаг 2: Получить ревизию

    # git svn fetch -r 7802
    Найдена возможная точка ветвления: svn + ssh: //gil@svn.myplace.com/repo/trunk => svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch, 7801
    Найден родительский филиал: (refs / remotes / trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Следующий родитель с do_switch
    Успешно последовал родитель
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs / remotes / newbranch)

git-svn сделал всю работу и теперь знает о пульте:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / remotes / newbranch

Шаг 3: Создайте новую локальную ветку, отслеживающую удаленную:

    # git checkout -b git-newbranch -t newbranch
    Проверка файлов: 100% (413/413), сделано.
    Ветка git-newbranch настроена для отслеживания локальных ссылок refs / remotes / newbranch.
    Перешел на новую ветку 'git-newbranch'
Джил Гамильтон
источник
После этого, наконец, позволил мне понять ( show-refбесценно)! Для тех, кто застрял с ошибочной ссылкой на удаленные ветки, вы можете удалить их (я должен был сделать, git branch -d newbranchа затем принудительно удалить ссылку ref .git/svn/refs/remotes/newbranch), а затем начать заново с шага 2 (выше).
tutuDajuju
5

Я не нашел никакой документации об этой функции, но похоже, что конфигурация git svn поддерживает несколько записей выборки. Таким образом, вы также можете добавлять ветки отдельно, без необходимости добавления другой записи удаленного svn-репозитория в вашу конфигурацию или использования подстановочных знаков для получения всех веток определенного каталога.

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

т.е.

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

и вы просто хотите вручную выбрать некоторые ветви, которые будут включены в ваш репозиторий git.

Сначала вы можете запустить свой репозиторий только с транком без каких-либо дополнительных веток:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

После этого вы должны увидеть следующую конфигурацию:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

когда вы хотите получить новую ветку из MyRepo, вы можете просто добавить новые записи в конфигурацию:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

Или вы можете отредактировать ту же конфигурацию в .git / config

Чтобы получить новые ветки после добавления их в конфигурацию, просто запустите:

git svn fetch -r 10000:HEAD

[Edit] Иногда кажется необходимым запустить fetch с параметром --all, чтобы получить новые добавленные ветки:

git svn fetch --all -r 10000:HEAD
Микаэль Леписто
источник
4

Вместо того, чтобы иметь дело с причудами git-svn, вы можете попробовать SubGit .

Нужно установить SubGit в хранилище Subversion. После этого можно использовать стандартный рабочий процесс git вместо специальных команд git-svn:

  1. Нажатие новых коммитов:

    ГИТ-SVN:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Получение входящих изменений

    ГИТ-SVN:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Создание новой ветки:

    ГИТ-SVN:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

См. Документацию SubGit для более подробной информации.

vadishev
источник
1
Недостатком SubGit является то, что он создает два репозитория - один svn и один «теневой» git-репозиторий. Это может быть проблемой для огромных репозиториев SVN ...
Udo
@Udo, если в SVN-репозитории есть несколько проектов, можно указать только один из них и синхронизировать его с Git-репозиторием. В этом случае нет необходимости конвертировать весь репозиторий Subversion в Git. Но если в этом хранилище есть огромный проект SVN, он может преобразовать не всю историю этого хранилища, а историю, начиная с некоторой минимальной ревизии. Это позволяет уменьшить размер переведенного репозитория Git.
Вадишев
1
@Udo - у любой компании, не желающей покупать свой сервер репозитория жесткий диск, есть свои приоритеты. Но большинство мест с огромными репозиториями относятся к своим репозиториям довольно серьезно, и требования к дисковому пространству для репозиториев, как правило, не являются серьезной проблемой, даже для компаний с десятилетиями истории, десятками миллионов строк кода и сотнями тысяч пересмотров. Это наиболее конкретная форма их основных интеллектуальных активов, а дисковое пространство довольно недорогое. Это может вызвать необходимость обновления RAID-контроллера, но даже в этом случае увеличение производительности ...
Боб Кернс,
@Bob Kerns - Дело в том, что SVN и Git по размеру не совместимы. Это не вопрос дискового хранилища или около того. Но вы можете работать с огромным SVN-репозиторием, потому что обычно вам нужно извлечь только несколько файлов / проектов. Но вы не можете клонировать огромный репозиторий Git - по крайней мере, это не смешно ;-) Под "огромным" я имею в виду несколько концертов.
Удо
2

Чтобы добавить к ответу vjangus, который мне помог, я также счел полезным добавить использование git-графтов для привязки веток к стволу в соответствующей точке - что позволяет git правильно просматривать историю и выполнять слияния.

Это просто случай добавления строки .git/info/graftsс хешами:

<initial branch commit> <parent commit in trunk>

например.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Кредит http://evan-tech.livejournal.com/255341.html

(Я бы добавил это как комментарий, но у меня недостаточно репутации.)

Хэддон CD.
источник
0

Если вы не выберете действительный макет, вы не сможете оформить удаленную ветку.

Вот что я делаю:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

После этого вы можете переключиться на удаленную ветку:

git checkout --track -b branch_name branch_name

Тогда вы автоматически переключитесь на свою ветку.

MikeHoss
источник