一般社団法人 全国個人事業主支援協会

COLUMN コラム

SVNからGitへの移行作業メモ

やったことと困ったことのメモ書き。

git-init

ローカルリポジトリの作成。
SVNとGitのフォルダ構成を合わせるので一苦労。
Gitの”スタンダードレイアウト”と定義されている構成なら良いのだが、そんなにうまくいくはずはない。

Repository (Git スタンダードレイアウト)
└Product
 ├trunk
 ├tags
 └branches

移行しようとしたSVNの構成

Repository (SVN移行対象)
├trunk
│├ProductA
│└ProductB
├branches
│├ProjectA
││└ProductA
││└ProductB
││└tags
││ └ProductA-ST
│├ProjectB
││└ProductA
..

GitリポジトリをProduct単位で作る

git svn init --prefix=svn/ --trunk={trunk-ProductA}

branchは .git/config を直接編集

[svn-remote "svn"]
url = {SvnRootURL}
fetch = {/trunk/ProductA}:refs/remotes/svn/trunk
fetch = {/branches/ProjectA/ProductA}:refs/remotes/svn/dev-projectA
..

perlでエラー?

git for windows で移行するもなぜかうまくいかない。
調べると version 2.27 ではうまくいかず、2.26.2 ならうまくいくらしい。
git for windows バージョン落として再インストール。

git-fetch

cloneはエラーが出ると残念な感じになるのでfetch。
fetchもいいがいかんせん時間がかかる。
しかも git svn fetch -r 1:HEAD でエラーになったらエラーになったところから再開、なんてずっと見てなきゃいけないじゃないか。
どうにか時間短縮を.. で考えたのがSVNのRevision分だけfetchする。
svn log -q --stop-on-copy {SvnURL}
で 変更履歴が取れるので、ここからRevisionを抜き出して
git svn fetch -r {Revision}:{Revision}
を実行。これだと割とほったらかしても何とかなりそう。

bash
※前提条件:Revision番号は5桁固定

#!/bin/env bash
revlist=()
for list in `svn log -q --stop-on-copy {SvnURL}`; do
if [ "`echo $list | grep -E -a r[0-9]{5}`" ]; then
revlist+=(`echo $list | sed -e "s/^r\[0-9]\{5\}\).*$/\1/g"`)
fi
done
sorted_rev=( $( printf "%s\n" "${revlist[@]}" | sort ) )
echo ${sorted_rev[@]}
for ((i=0; i<${#sorted_rev[@]}; i++)); do
git svn fetch -r ${sorted_rev[$i]}":"${sorted_rev[$i]}
done
git svn fetch -r HEAD:HEAD

git-fetchのエラー

いろんな理由で発生するが、一番困ったのが 1回でfetchできる容量に制限あり? かわからないが大量のコミットを数回分読み込むと止まってしまう。
http.postedbufferで容量増やせば.. では解消されず、たどり着いたのが 1Commit 1fetch。
SVNの変更履歴がうん万とあると、まぁまぁ効果あるんじゃないかと。

git-checkout

Gitのブランチを作る作業。
git checkout master
とだけ実行すると、masterには 1Commit分しか記録が残っておらず途方にくれた恥ずかしい経験をした。
おそらく、最初のfetch分が ローカルのmasterブランチに登録され、それ以外は svn/* に登録されているだけ。
svn/* を Gitのブランチへ変換するために コマンドは省略せずに記載する

svn/trunkを ローカルのtrunkブランチに変換し、
その後 masterにマージして trunkは削除

git checkout -b trunk svn/trunk
git checkout master
git merge trunk
git branch --delete trunk

git checkout -b dev-projectA svn/dev-projectA
..

git-filter-branch

コミット履歴の中身を書き換える禁じ手。SVNからGitへの移行後、並行運用しようと思うなら使ってはいけない。
これを実行したら二度と戻れないので取扱い注意。

git filter-branch -f --tree-filter "{command}" HEAD --all

用途1 フォルダ構成を変えたい

ブランチ直下に SVNのファイルをそのまま配置するのではなく、src/ProductA みたいにしたい、の例

git filter-branch -f --tree-filter "mkdir src; git mv -k * src/;" HEAD --all

用途2 文字コードを変えたい

sjis→utf-8に変えたい、とかそんな例。

<convert.sh>
#!/bin/env bash
for file in `\find . \( -name "*.sh" -or -name "*.php" -or -name "*.js" -or -name "*.css" \)`; do
if [ "`nkf --guess $file | grep Shift_JIS`" ]; then
nkf -w --overwrite $file
fi
done
</convert.sh>

git filter-branch -f --tree-filter "convert.sh" HEAD --all

コマンドは 1行で書かなくてもよい

git filter-branch -f –tree-filter “{command}” HEAD –all
の {command} が 1行にするのが大変なら別ファイルに外だししてもOK (参考: 用途2 文字コードを変えたい)

git-push

ローカルリポジトリに思い通りのファイルが出来たらリモートへプッシュ。

git push -u origin --all

SVNとGitの違い

SVNからGitへ移行した際の一番大変だったのは実はここ。
SVN脳に慣れすぎててGitが良くわからなかった。

SVNのブランチ・タグのファイルの持ち方とGitのファイルの持ち方が全く違う。
リモート?ローカル?プッシュ?フェッチ?プルリク?????
な日々が懐かしく感じる今日この頃。

最初はとっつきにくいけど、ここは頑張って覚えるしかない。

 

フォークでブランチ作ってね

 

言葉って難しい。

The following two tabs change content below.

山﨑 昭博

最新記事 by 山﨑 昭博 (全て見る)

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア