6

私のプロジェクトにはネットワークファイルシステム上にSubversionリポジトリがあり、新しいチームがGitを使用してそれにアクセスし、それにコミットして更新を取得できるようにしたいと考えています。

私が念頭に置いているのはgit-svn、同じネットワークファイルシステム上にSubversionリポジトリの新しいベアクローンを作成し、2つのリポジトリが常に最新であることを確認することです。

これを行う方法は、おそらくSubversionと新しいGitリポジトリの両方にコミット後のフックを追加することです。これにより、それぞれが他方のリポジトリを更新します。

Subversionのコミット後フックには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 追跡ブランチを作成します。

    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 に送信する post-receive フックを作成します。

    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リポジトリを使用できます。中央リポジトリでもある1 つの非ベア リポジトリを使用することにしました。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 に答える