Automatically synchronizing a Subversion repository and a Git repository

后端 未结 2 1933
终归单人心
终归单人心 2021-02-01 11:08

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.

W

2条回答
  •  北海茫月
    2021-02-01 11:40

    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  
      

      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/: 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 /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 /hooks/post-commit
      
          cd 
          . .git/hooks/svn-rebase-all
      
      chmod +x /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 and pushing to it, or using Subversion by checking out and committing to it.

提交回复
热议问题