GitとSubversionを併用する
仕事ではSubversion(以下、svn)を使っているのだが、これをgitに置き換えたい。
とはいえ、いきなり全体をgitに移行するのはキツそうなので、以下のようなプロセスを踏もうと思う。
(1) 自分の環境だけgitを使えるようにする(中央リポジトリはsvn)
(2) 他のメンバー(数名規模)もgitを使えるようにする(中央リポジトリはsvn)
(3) 中央リポジトリをsvnからgitに変える
このエントリでは上記(1)の経緯を書きとめておく。
現状
・以下のように中央にsvnリポジトリが存在していて、各人がそこからチェックアウトしている
・各人はチェックアウトした「svn作業コピー」から「作業用ディレクトリ」にコピーしている(cpやrsyncで)
・各人の「作業用ディレクトリ」のhtdocsはdev環境としてブラウザから閲覧可能
・各人の「svn作業コピー」と「作業用ディレクトリ」は一致しない(バージョン管理しないファイルが沢山ある)
・各人の「svn作業コピー」と「作業用ディレクトリ」の差分管理がとにかく大変な状況
自分の環境だけでもgitにおきかえたい。方法として以下の3つが思いついたので、それぞれ試してみた。
最終的に「(C) git-svnを使う」ことになったのだが、折角なのでそこまでの経緯を記録しておく。
(A) 「svn作業コピー」を「gitリモートリポジトリ」として使う
以下のようにsvn作業コピーをgitリモートリポジトリ(bareではないワーキングツリーを持つリポジトリ)にして、gitローカルリポジトリからpull/pushする形を考えた。
結果: 不採用
理由: gitのリモートリポジトリは基本的にbareリポジトリであることが推奨されるため。
# svnリポジトリからチェックアウトしてsvn作業コピーを作る $ svn checkout [svnリポジトリ] [svn作業コピー] # svn作業コピーをgit管理下におく(gitリモートリポジトリを兼任させる) $ cd [svn作業コピーのトップ] $ git init # svnの管理下から.gitと.gitignoreを除去 # ※設定用のエディタにはvimを使用した # ※参考: http://log.xinu.jp/2011-07-25-1.html $ export svn_EDITOR="vim" $ svn propedit svn:ignore ./ .git .gitignore # 確認 $ svn status $ svn status --no-ignore # gitの管理下から.svnを除去 $ vim .gitignore .svn # 確認 $ git status # gitにコミットする $ git add . $ git commit -m 'init' # 作業ディレクトリ(gitローカルリポジトリ)に移動し # svn作業コピー(gitリモートリポジトリ)からcloneする $ cd [作業ディレクトリ|gitローカルリポジトリ] $ git clone [svn作業コピー|gitリモートリポジトリ] # なんらかのファイルに変更を加えた後、pushする $ git add . $ git commit -m 'test' $ git push # エラーが出る! (略) remote: error: refusing to update checked out branch: refs/heads/master remote: error: By default, updating the current branch in a non-bare repository remote: error: is denied, because it will make the index and work tree inconsistent remote: error: with what you pushed, and will require 'git reset --hard' to match remote: error: the work tree to HEAD. remote: error: remote: error: You can set 'receive.denyCurrentBranch' configuration variable to remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into remote: error: its current branch; however, this is not recommended unless you remote: error: arranged to update its work tree to match what you pushed in some remote: error: other way. remote: error: remote: error: To squelch this message and still keep the default behaviour, set remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'. (略)
(B) 「svn作業コピー」を「gitローカルリポジトリ」として使う
以下のようにsvn作業コピーをgitローカルリポジトリとして使う構成を考えた。
gitリモートリポジトリを別途用意して、それを中間地点としてpull/pushするような構成。
結果: 不採用
理由: 一応できたが、何度もpushやpullをする必要があって面倒。また複雑なのでミスも多くなりそう。
# >>> ここから $ svn checkout file:hoge fuge $ cd [svn作業コピーのトップ] $ git init $ export svn_EDITOR="vim" $ svn propedit svn:ignore ./ .git .gitignore $ vim .gitignore .svn $ git add . $ git commit -m 'init' # <<< ここまでは1.と同じ # gitのbareリポジトリを作る $ mkdir [git_bareリポジトリの] $ cd [git_bareリポジトリ] $ git clone --bare [svn作業コピー] # svn作業コピーに移動し、作成したgitのbareリポジトリをgitリモートリポジトリに設定する $ cd [svn作業コピー] $ git remote add [リモートリポジトリ名] [git_bareリポジトリ] # 作業用のディレクトリにcloneする $ cd [作業用ディレクトリ] $ git clone [git_bareリポジトリ] # 作業用ディレクトリでなんらかのファイルに変更を加えた後、pushする $ git add . $ git commit -m 'test' $ git push # svn作業コピーでgit pull $ cd [svn作業コピー] $ git pull # svnの状態を確認 $ svn status -u
(C) git-svnを使う
結果として定石通りにこれを採用した。
自分の環境での問題は、git管理下におきたくないファイルが異常に沢山あること。
そこで.gitignoreファイルをかなり丁寧に指定した。
.gitignoreの指定方法にについてはこちらのエントリにまとめた。
また、以下のサイトを参考にして作業した。
git svn cloneをやるときは--prefix svn/をつけるべき - DQNEO起業日記
Git - Git と Subversion
# 現在の作業用ディレクトリをいったん退避 $ mv [作業用ディレクトリ] [旧作業ディレクトリ] # 新しい作業用ディレクトリを作成し、git管理下に $ mkdir [新作業用ディレクトリ] $ cd [新作業用ディレクトリ] $ git init # git-svnがインストールされているか確認。なければインストール $ git svn --version # subversionのリポジトリを取り込む # <注意!>過去のコミット数が多いと、死ぬほど時間がかかる場合がある(数日かかる場合もあるらしい)ので注意 # 自分の環境では、1000コミットくらいあるリポジトリが15分くらいだった $ git svn clone -s --prefix svn/ [svnリポジトリ(trunkはつけない)] [clone後ディレクトリ名] # svnリポジトリの情報確認 # svnリポジトリのログ確認 $ git svn info $ git svn log # .gitignoreを細かく指定 $ vim .gitignore 色々な設定 # 旧作業用ディレクトリを新作業用ディレクトリに上書き $ cp -R [旧作業用ディレクトリの内容] [新作業用ディレクトリ] # 確認 git status
実運用
こちらのブログに掲載されている内容が大変参考になりました。
git-svnを使うときのベストプラクティス - Life goes on
git-svnの使い方を覚えた - idesaku blog