Автоматическая синхронизация хранилища Subversion и Git - PullRequest
6 голосов
/ 08 апреля 2011

В моем проекте есть хранилище Subversion в сетевой файловой системе, и новая команда хотела бы получить к нему доступ с помощью Git, иметь возможность фиксировать его и получать от него обновления.

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

Способ сделать этовозможно добавить хук после фиксации для Subversion и нового репозитория Git, который будет обновлять репозиторий другого.

Хук после фиксации Subversion будет включать git svn rebase, а Git one git svn dcommit.

Проблема в том, что мне придется использовать какую-то блокировку, чтобы никто не фиксировал ни один из репозиториев, в то время как другой также был зафиксирован, потому что они всегда должны быть синхронизированы перед любой фиксацией.У этого есть несколько недостатков, среди которых время, которое требуется для фиксации в Subversion или отправки в репозиторий Git (он должен ждать завершения хука), и тот факт, что некоторые пользователи могут не иметь возможности запускать git svn(потому что он не установлен на их компьютере), что означает, что они не могут обновить другой репозиторий при фиксации / отправке.

Как я могу решить эти проблемы?Как будут выглядеть хуки Subversion и Git?

Ответы [ 2 ]

13 голосов
/ 04 октября 2011

Вот что я придумал:

  1. Создайте репозиторий git-svn, если он еще не существует:

    git svn init --std-layout <svn_url> <git-svn_path>
    

    Ветвь master создается автоматически для отслеживания trunk.

  2. Чтобы избежать двусмысленности имен в ветвях отслеживания Subversion, сделайте так, чтобы исходные ветви Subversion показывались как remotes/svn/<branch name>: перейдите во вновь созданный репозиторий git-svn и запустите

    git config svn-remote.svn.fetch trunk:refs/remotes/svn/trunk
    git config svn-remote.svn.branches branches/*:refs/remotes/svn/*
    git config svn-remote.svn.tags tags/*:refs/remotes/svn/tags/*
    
    rm .git/refs/remotes/*
    git svn fetch
    
  3. Создание ветви отслеживания Subversion для каждой ветви Subversion:

    for BRANCH in $(svn ls <svn_url>/branches/); do
        git branch $BRANCH remotes/svn/$BRANCH
    done
    
  4. Убедитесь, что в центральном репозитории Git не созданы ветки без отслеживания Subversion:

    # Used by hooks/update:
    git config hooks.denyCreateBranch true
    git config hooks.allowDeleteBranch false
    
    cp .git/hooks/update.sample .git/hooks/update
    chmod +x .git/hooks/update
    
  5. Разрешить отправку в центральное хранилище Git:

    git config receive.denyCurrentBranch ignore
    git config receive.denyNonFastForwards true
    git config push.default current
    

    И создайте перехват после получения для сброса и отправки коммитов в Subversion:

    cat .git/hooks/post-receive
    
        #!/bin/sh
    
        date >> receive.log
        git reset --quiet --hard
        while read LINE
        do
            BRANCH=${LINE##*/}
            echo Updating $BRANCH
            git checkout --quiet --force $BRANCH
            git svn dcommit
        done 2>&1 | tee -a receive.log
        git checkout --quiet --force master
    
    chmod +x .git/hooks/post-receive
    

    Сброс необходим, потому что в противном случае текущая ветвь устарела после каждого получения.

  6. Наконец, создайте ловушку для получения обновлений от Subversion:

    cat .git/hooks/svn-rebase-all
    
        #!/bin/sh
    
        date >> .git/svn-rebase.log
        git reset --quiet --hard
        for REF in .git/refs/heads/*
        do
            BRANCH=${REF##*/}
            echo Updating $BRANCH
            git checkout --quiet --force $BRANCH
            git svn rebase
        done 2>&1 | tee -a .git/svn-rebase.log
        git checkout --quiet --force master
    
    chmod +x .git/hooks/svn-rebase-all
    

    И вызовите его из ловушки пост-фиксации Subversion:

    cat <svn_path>/hooks/post-commit
    
        cd <git_path>
        . .git/hooks/svn-rebase-all
    
    chmod +x <svn_path>/hooks/post-commit
    

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

Любой может работать над проектом, используя Git, клонируя <git_path> и нажимая на него, или используя Subversion, проверяя <svn_url> и фиксируя его.

4 голосов
/ 08 апреля 2011

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

В качестве альтернативы, можно просто отказаться от SVN и, если возможно, полностью перейти к git.

...