Help us understand the problem. What is going on with this article?

いろいろ残念なSVN職場で自分だけGitを使おうとして苦労した話

職場がいまだにSVNでツライのでgit-svnで自分だけGitを使おうとしたら、SVNリポジトリがいろいろ残念で苦労したという話です。
同じ環境の人は少ないとは思いますが、誰かの参考になれば。

環境

  • Windows 10
  • Gitの操作は基本的にBash for Git

SVNリポジトリの現状

  • リポジトリ構成が変則的
  • Shift-JISとUTF-8が混在

変則的なリポジトリへの対応

SVNリポジトリは、以下のような構成になっていました。trunkの下にbranchがあるのはいまだに納得いかない・・・

SVN_REPO/
    trunk/
        doc/
        src/       ← 実質的なトランク
        src_foo/   ← ブランチ
        src_bar/   ← ブランチ
        src_v001/  ← タグ
        src_v002/  ← タグ
        (以下、src_vXXXがいっぱい)
        tool/
    branches/
        hoge/      ← ブランチ
            doc/
            src/
            tool/
    tags/          ← 空っぽ

やりたいこと

  • trunk/src/をtrunkとしてgit-svnに取り込む
  • branches/hoge/src/trunk/src_*/をbranchesとして取り込む

手順

どうやらgit svn cloneのオプションだけで上記を実現するのは無理そうだったので、init後にconfigをいじってfetchすることで実現しました。

まずはinitします。

  • GitからSVNのリポジトリを見たときに区別がつくように、--prefixオプションを指定します。
  • srcディレクトリの下だけを対称とするので、-T trunk/srcと指定します。
  • ブランチは複雑なので後でconfigを編集するのですが、ここではconfigの雛形を作るために適当に-bオプションを指定します。
$ git svn init --prefix=svn/ -T trunk/src -b trunk/ http://SVN_REPO_URL

次に.git/configを編集します。

[svn-remote]branches =で始まる行を編集します。これはブランチの履歴情報などが保存されるパスを示していて、:の左側はリモート側のパスを、右側はローカル側のパスを意味するそうです。
今回はブランチが2箇所に別れているので2行に分けて指定します。*でワイルドカードが使えるので、1行目でtrunkの下のsrc_で始まるすべてのブランチをまとめて指定します。(今回の構成ではタグも一緒に取り込まれてしまいますが、気にしないことにします。)2行目でbranchesの下の任意のディレクトリの下のsrcディレクトリを指定します。
また、ローカルに作成されるブランチが、リモートリポジトリのどのブランチだったかの区別がつくように、片方をbranches_in_trunk、もう片方をstd_branchesとしました。

branches = trunk/src_*:refs/remotes/branches_in_trunk/*
branches = branches/*/src:refs/remotes/std_branches/*

最後にfetchします。

$ git svn fetch

これでトランクとブランチそれぞれのsrc以下を取り込むことができました。

$ git branch -r
svn/branches/hoge
svn/branches_in_trunk/src_foo
svn/branches_in_trunk/src_bar
svn/branches_in_trunk/src_v001
svn/branches_in_trunk/src_v002
svn/trunk

文字エンコード混在への対応

現状はSJISとUTF-8のファイルが混在していました。フォルダによって違うとかならまだしも、同じフォルダ内でもバラバラ。同名の.cと.hでも揃ってなかったりと、ひどい状況。
このままだとdiffが見づらくて仕方ありません。
SJISのファイルをGitで扱う方法をググるとiconvがよく使われているようですが、iconvは元のエンコードを指定する必要があるため、今回のケースでは使えません。
そこでnkfを使うことにしました。

手順

ローカルリポジトリのルートディレクトリに、.gitattributesという名前でファイルを作成して、下記を記述します。
これによって、指定した拡張子に対してdiffコマンドを使うときには"sjis"フィルターを適用するようになります。

*.c diff=sjis
*.h diff=sjis
*.cpp diff=sjis
*.hpp diff=sjis

次に、.git/configファイルにsjisフィルタを記述します。

[diff "sjis"]
    textconv = nkf -w8

これで、SJISとUTF-8が混在していても文字化け無くdiffを見れるようになりました。

ただ、git add -pなどのパッチ系コマンドは相変わらず文字化けするんですよね。解決策はまだ見つかっていません。ご存じの方、教えてください。
まあ、それよりエンコード統一しろよって話ですけどね。。。

usuiat
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした