自动同步Subversion存储库和Git存储库 [英] Automatically synchronizing a Subversion repository and a Git repository

查看:84
本文介绍了自动同步Subversion存储库和Git存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目在网络文件系统上有一个Subversion版本库,一个新团队希望使用Git访问它,并且能够承诺并从中获取更新。



我想到的是在同一个网络文件系统上创建一个新的 git-svn clone的Subversion版本库,并确保这两个版本库总是相互关联。



这样做的方式可能是为Subversion和新的Git存储库添加一个post-commit钩子,将每个更新其他的仓库。



Subversion post-commit钩子将包含 git svn rebase 和Git一个 git svn dcommit



问题是,我将不得不使用某种锁来确保不是一个承诺要存储库而其他人也承诺,因为他们总是必须在任何提交之前同步。这有几个缺点,其中包括提交Subversion或推送到Git存储库所需的时间(它必须等待挂钩完成),以及某些用户可能无法运行 git svn (因为它没有安装在他们的机器上),这意味着他们无法在提交/推送时更新其他存储库。



<我怎样才能解决这些问题? Subversion和Git钩子的样子是什么?

解决方案

以下是我想到的:


  1. 创建 git-svn 存储库(如果它尚不存在):

      git svn init --std-layout< svn_url> < GIT-s​​vn_path> 

    自动创建 master 分支以跟踪 trunk


  2. 为了避免与Subversion跟踪分支产生混淆,请使原始Subversion分支显示作为远程/ svn /<分支名称> :转至新创建的 git-svn / p>

      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分支的跟踪分支:$($ s $ s $ s $ s $ s $ s $ s $ s $ s $ s $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
    git branch $ BRANCH remotes / svn / $ BRANCH
    done


  4. 确保在中央Git存储库上没有创建非Subversion跟踪分支:

     #钩子使用/ 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忽略
    git config receive.denyNonFastForwards true
    git config push.default当前

    然后创建post-receive钩子来重置并发送提交给Subversion:

      cat .git / hooks / post-receive 

    #!/ bin / sh

    日期>> ; receive.log
    git reset --quiet --hard
    读取LINE
    do
    BRANCH = $ {LINE ## * /}
    echo更新$ BRANCH
    git checkout --quiet --force $ BRANCH
    git svn dcommit
    完成2>& 1 | tee -a receive.log
    git checkout --quiet --force master

    chmod + x .git / hooks / post-receive

    重置是必须的,因为否则当前分支在每次接收后都会过期。


  6. <最后,创建钩子以获取Subversion的更新:

      cat .git / hooks / svn-rebase-全部

    #!/ bin / sh

    日期>> .git / svn-rebase.log
    git reset --quiet --hard
    for REF in .git / refs / heads / *
    do
    BRANCH = $ {REF# #* /}
    echo更新$ BRANCH
    git checkout --quiet --force $ BRANCH
    git svn rebase
    完成2>& 1 | tee -a .git / svn-rebase.log
    git checkout --quiet --force master

    chmod + x .git / hooks / svn-rebase-all

    然后从Subversion post-commit hook中调用它:

      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> 并提交给它。


My project has a Subversion repository on a network file system, and a new team would like to access it using Git, and be able to commit to it and get updates from it.

What I have in mind is to create a new bare git-svn clone of the Subversion repository on the same network file system, and make sure the two repositories are always up to date with respect to each other.

The way to do this is probably to add a post-commit hook for both Subversion and the new Git repository, that will each update the other's repository.

The Subversion post-commit hook will include git svn rebase, and the Git one git svn dcommit.

The problem is that I will have to use some kind of lock to make sure no one commits to either repository while other is also being committed to, because they always have to be in sync before any commit. This has several disadvantages, among them the time it will take to commit to Subversion or to push to the Git repository (it has to wait for the hook to finish), and the fact that some users may not be able to run git svn (because it's not installed on their machine), which means they can't update the other repository when committing/pushing.

How can I solve these problems? What will the Subversion and Git hooks look like?

解决方案

Here is what I've come up with:

  1. Create the git-svn repository if it doesn't exist already:

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

    The master branch is created automatically to track the trunk.

  2. To avoid name ambiguities with Subversion-tracking branches, make the original Subversion branches show as remotes/svn/<branch name>: go to the newly-created git-svn repository and run

    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. Create a Subversion-tracking branch for each Subversion branch:

    for BRANCH in $(svn ls <svn_url>/branches/); do
        git branch $BRANCH remotes/svn/$BRANCH
    done
    

  4. Make sure no non-Subversion-tracking branches are created on the central Git repository:

    # 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. Allow pushing to the central Git repository:

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

    And create the post-receive hook to reset and send the commits to 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
    

    The reset is necessary, because otherwise the current branch is out-of-date after each receive.

  6. Finally, create the hook to get updates from 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
    

    And call it from the Subversion post-commit hook:

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

Instead of using a single git-svn central repository, one can use a bare central Git repository and an intermediate non-bare git-svn repository, as in this answer. I chose to use one non-bare git-svn repository which is also the central repository.

Anyone can work on the project using Git by cloning <git_path> and pushing to it, or using Subversion by checking out <svn_url> and committing to it.

这篇关于自动同步Subversion存储库和Git存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆