2011-04-07 125 views
5

我的项目有一个网络文件系统上的Subversion版本库,以及一个新的团队想使用Git从它来访问它,并能够承诺,并得到更新。自动同步Subversion版本库和一个Git仓库

我想到的是在同一个网络文件系统上创建Subversion版本库的新版本git-svn,并确保两个版本库始终保持最新。

做到这一点的方法可能是添加一个post-commit钩子两个颠覆和新的Git仓库,将每个更新其他的存储库。

颠覆post-commit钩子将包括git svn rebase,和GIT中一个git svn dcommit

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

我该如何解决这些问题? Subversion和Git钩子会是什么样子?

回答

12

这里是我想出来的:

  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. 确保没有非Subversion的跟踪分支在中央Git仓库创建:

    # 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称它为post-commit钩子:

    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,如this answer。 我选择使用一个非裸露的git-svn存储库,它也是中央存储库。

任何人都可以使用Git工作,方法是克隆<git_path>并推送到该项目,或使用Subversion签出<svn_url>并提交。

+0

'git config hooks.denycreatebranch false' @丹尼尔你的意思是“真”吗? – basin 2013-04-22 11:10:25

+0

@basin是的,我想是的。谢谢。 – 2013-04-22 12:57:08

4

你只有让每个开发者更好学习直接使用git-svn。 git和SVN模型之间的阻抗失配太多,无法实现您正在寻找的功能。只有这样才能使其工作得几乎可靠,唯一的办法是制定git-svn可能具有的相同类型的限制,但是可能会有更多移动部件可能中断。在我看来,你的版本控制系统并不是你想要的部分可靠的东西。

或者只是沟SVN干脆一路搬到混帐如果可能的话。

+1

我确实打算在某个时候将我的团队转移到Git上,但我认为git-svn允许的逐步移动是一个很大的优势。我想其他团队将不得不完成我的git-svn克隆副本,并使用git svn dcommit和git svn rebase自己。 – 2011-04-09 14:05:19

+2

如果多个git repos使用git-svn从中央svn repo推送/拉出(我相信这是推荐的),那么在这些git repos之间直接推/拉将会很困难。这是因为git分支在'git svn rebase'期间被重新设置。 – 2011-05-02 20:56:51

+0

这是正确的,并且它还使未来更加难以转换为纯粹的Git配置,因为每个人都必须通过创建补丁并将它们应用于来自新中央Git存储库的新克隆存储库来“迁移”其Git存储库。 – 2011-10-03 17:24:03