Як мені розповісти 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

3
просто додавши це посилання на документи як посилання на kernel.org/pub/software/scm/git/docs/git-svn.html
slf

1
З .git / config досить легко зрозуміти, як віддалені гілки можна налаштувати з одного / декількох сховищ.
Mikael Lepistö

6
Якби я міг підкреслити це як вісім разів, я би. Нарешті, спосіб додати svn гілку, додану в нестандартному місці!
Тім Кітінг

7
Я потрапляю fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.на крок оформлення каси.
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.

Якщо ви хочете отримати лише конкретні гілки замість УСІХ, є приємний приклад у 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, перед тим, як встановити ці налаштування, можливо, ви захочете виконати скидання gn svn.
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нарешті отримати повну історію з правильним підключеним графіком.
starlocke

8
ЦЕ ПОВИНЕН БУТИ ПРИЙМАНОГО ВІДПОВІДЬ! @janos, ти щойно врятував мені години головного болю! Якщо ви коли-небудь приїдете до Індії, я вивезу вас на пиво!
Roopesh Shenoy

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

Можливо, я це якимось чином зіпсував, але я дотримувався вказівок у відповіді віянгуса, і це майже вийшло . Єдина проблема полягала в тому, що новобранця, здавалося, не розгалужується від стовбура. У gitk це було свого роду "плаваюче" все самостійно; вона не мала спільного предка зі стовбуром.

Рішенням цього було:

  1. Знайдіть SHA1 останнього комітету, який стався на стовбурі до створення гілки.
  2. Знайдіть SHA1 першого комітету на новій гілці (повідомлення, ймовірно, "Створено нову гілку, скопійовану з магістралі @ 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, тому, будь ласка, запропонуйте вдосконалити цей метод.


2
Дякую, це звучить корисно. Близько 5. Можливо, "git-update-ref refs / remotes / newbranch <new-SHA>" є більш безпечним варіантом.
inger

Просто спробував шлях в'янгуса знову, і це спрацювало чудово. Я залишу це все одно, оскільки це може бути для когось цінним ...
MatrixFrog

1
Рішення vjangus завжди створює нову гілку, від'єднану від стовбура. Я припускаю, що це тому, що сам SVN не має поняття про те, як копіюється фактичний вміст.
bogdan.mustiata

Мій досвід роботи з великим репо-git-svn полягає в тому, що гілки svn завжди створюються в git, відірваному від стовбура. Має бути якийсь спосіб їх з'єднання, але я не знайшов часу, щоб це зрозуміти. AFAIK, ви не можете відновити гілку гіта, підключену до гілки svn, тому що це зіпсує логіку dcommit. Ми щойно навчилися з цим жити.
Спенсер

7

Спрощення відповіді vjangus:

Якщо ви використовуєте стандартний макет у 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 журнал - стоп-копія 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 / remote / trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Слідом за батьком з do_switch
    Успішно стежив за батьком
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs / remote / newbranch)

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

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / пульти / newbranch

Крок 3. Створіть нову локальну гілку, відстежуючи віддалену:

    # git checkout -b git-newbranch -t newbranch
    Перевірка файлів: 100% (413/413), зроблено.
    Відділення git-newbranch створене для відстеження місцевих посилань / віддалених / нових галузей.
    Переключився на нову галузь 'git-newbranch'

Після цього нарешті я дозволив мені зрозуміти ( show-refнеоціненно)! Для тих, хто застряг із помилковим посиланням на віддалені гілки, ви можете видалити їх (мені довелося це зробити, git branch -d newbranchа потім змусити видалити рефрижератор .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

[Редагувати] Іноді, здається, потрібно запустити витяг із параметром --all для отримання знову доданих гілок:

git svn fetch --all -r 10000:HEAD

4

Замість того, щоб мати справу з примхами git-svn, ви можете спробувати SubGit .

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

  1. Натискання нових комісій:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Отримання вхідних змін

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Створення нової філії:

    git-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 .


1
Недоліком SubGit є те, що він створює два сховища - одне svn та одне сховище git "тінь". Це може бути проблемою для величезних сховищ SVN ...
Udo,

@Udo якщо у сховищі SVN є кілька проектів, можна вказати лише один із них і синхронізувати його з репозиторієм Git. У цьому випадку немає необхідності перетворювати все сховище Subversion в Git. Але якщо в цьому сховищі є великий проект SVN, він може конвертувати не всю історію цього сховища, а історію, починаючи з мінімальної редакції. Це дозволяє зменшити розмір перекладеного сховища Git.
vadishev

1
@Udo - будь-яка компанія, яка не бажає купувати їх сервер сховища на жорсткому диску, має свої пріоритети зіпсованими. Але більшість місць з величезними сховищами сприймають свої сховища досить серйозно, а вимоги до дискового простору для сховищ, як правило, не є головною проблемою, навіть для компаній, що мають десятиліття історії та десятки мільйонів рядків коду та сотні тисяч версій. Це найбільш конкретна форма їх основних інтелектуальних активів, і дисковий простір досить недорогий. Це може призвести до необхідності оновлення RAID-контролера, але навіть так, підвищення продуктивності ...
Боб Кернс

@Bob Kerns - Справа в тому, що SVN та Git "розумними за розміром" і не сумісні. Це не питання збереження диска чи так. Але ви можете працювати з величезним сховищем SVN, тому що зазвичай потрібно перевірити лише кілька файлів / проектів. Але ви не можете клонувати величезний сховище Git - це не приносить задоволення принаймні ;-) Під "величезним" я маю на увазі кілька Gigs.
Удо

2

Щоб додати відповідь vjangus, яка мені допомогла, я також вважаю корисним використовувати git grafts для прив’язки гілок до стовбура у відповідній точці - що дозволяє git переглядати історію та виконувати злиття правильно.

Це просто випадок додавання рядка до .git/info/graftsхешів:

<initial branch commit> <parent commit in trunk>

напр.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Заслуга http://evan-tech.livejournal.com/255341.html

(Я додав би це як коментар, але мені недостатньо репутації.)


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

Тоді ви автоматично перейдете на своє відділення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.