6

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

我的想法是git-svn在同一个网络文件系统上创建一个新的 Subversion 存储库的裸克隆,并确保两个存储库相对于彼此始终是最新的。

这样做的方法可能是为 Subversion 和新的 Git 存储库添加一个 post-commit 挂钩,这将各自更新对方的存储库。

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

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

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

4

2 回答 2

13

这是我想出的:

  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-tracking 分支:

    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
    

    并创建 post-receive 挂钩以重置并将提交发送到 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库,如本答案所示。我选择使用一个非裸git-svn存储库,它也是中央存储库。

任何人都可以通过克隆<git_path>和推送来使用 Git 来处理项目,或者通过签出<svn_url>和提交来使用 Subversion。

于 2011-10-04T08:58:53.257 回答
4

最好让每个开发人员直接学习使用git-svn。git 和 SVN 模型之间的阻抗不匹配太多,无法稳健地实现您正在寻找的东西。你可以让它几乎可靠地工作的唯一方法是制定相同类型的限制git-svn,但有更多可能会损坏的活动部件。在我看来,你的版本控制系统并不是你想要部分可靠的东西。

或者,如果可能的话,完全放弃 SVN 并一直迁移到 git。

于 2011-04-08T03:38:54.063 回答