やったことと困ったことのメモ書き。
ローカルリポジトリの作成。
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
..
git for windows で移行するもなぜかうまくいかない。
調べると version 2.27 ではうまくいかず、2.26.2 ならうまくいくらしい。
git for windows バージョン落として再インストール。
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
いろんな理由で発生するが、一番困ったのが 1回でfetchできる容量に制限あり? かわからないが大量のコミットを数回分読み込むと止まってしまう。
http.postedbufferで容量増やせば.. では解消されず、たどり着いたのが 1Commit 1fetch。
SVNの変更履歴がうん万とあると、まぁまぁ効果あるんじゃないかと。
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
..
コミット履歴の中身を書き換える禁じ手。SVNからGitへの移行後、並行運用しようと思うなら使ってはいけない。
これを実行したら二度と戻れないので取扱い注意。
git filter-branch -f --tree-filter "{command}" HEAD --all
ブランチ直下に SVNのファイルをそのまま配置するのではなく、src/ProductA みたいにしたい、の例
git filter-branch -f --tree-filter "mkdir src; git mv -k * src/;" HEAD --all
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
git filter-branch -f –tree-filter “{command}” HEAD –all
の {command} が 1行にするのが大変なら別ファイルに外だししてもOK (参考: 用途2 文字コードを変えたい)
ローカルリポジトリに思い通りのファイルが出来たらリモートへプッシュ。
git push -u origin --all
SVNからGitへ移行した際の一番大変だったのは実はここ。
SVN脳に慣れすぎててGitが良くわからなかった。
SVNのブランチ・タグのファイルの持ち方とGitのファイルの持ち方が全く違う。
リモート?ローカル?プッシュ?フェッチ?プルリク?????
な日々が懐かしく感じる今日この頃。
最初はとっつきにくいけど、ここは頑張って覚えるしかない。
フォークでブランチ作ってね
言葉って難しい。