はじめに

これは2017/06/03 に作成した過去記事の移植です。

CVSからGitの移行について

CVSリポジトリをGitリポジトリに変換する機会があったので、使用するコマンドなどをまとめます。 ここでは、まずCVSのリポジトリを作成し、それをGitリポジトリに変換し、履歴がどうなっているのかを確認します。

CVSリポジトリの作成

まずは、CVSのリポジトリ用のディレクトリを作成します。

CVSディレクトリ作成
1
2
3
[[email protected] horiba]mkdir cvsroot  
[[email protected] horiba]ls  
cvsroot  
CVSリポジトリの初期化
1
[[email protected] horiba] cvs -d /home/horiba/cvsroot/ init

treeコマンドでディレクトリを調べると以下のようになるはずです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[[email protected] horiba] tree  
.  
 -- cvsroot  
     -- CVSROOT  
        |-- Emptydir  
        |-- checkoutlist  
        |-- checkoutlist,v  
        |-- commitinfo  
        |-- commitinfo,v  
        |-- config  
        |-- config,v  
        |-- cvswrappers  
        |-- cvswrappers,v  
        |-- editinfo  
        |-- editinfo,v  
        |-- history  
        |-- loginfo  
        |-- loginfo,v  
        |-- modules  
        |-- modules,v  
        |-- notify  
        |-- notify,v  
        |-- rcsinfo  
        |-- rcsinfo,v  
        |-- taginfo  
        |-- taginfo,v  
        |-- val-tags  
        |-- verifymsg  
         -- verifymsg,v  

3 directories, 24 files  
CVSROOTの環境パス設定
1
2
3
[[email protected] horiba] CVSROOT=/home/horiba/cvsroot; export CVSROOT
[[email protected] horiba] echo $CVSROOT
/home/horiba/cvsroot
CVSリポジトリの作業場所を作成
1
2
3
4
5
6
7
[[email protected] horiba] mkdir work
[[email protected] horiba] cd work/
[[email protected] work] mkdir project
[[email protected] work] cd project/
[[email protected] project] echo "CVS initalize commit." > init.txt
[[email protected] project] cat init.txt
CVS initalize commit.
CVSリポジトリにインポートする

CVSに projectをインポートします。
書式は以下の通り

1
cvs import [モジュール名] [ベンダタグ] [リリースタグ]
1
2
3
4
[[email protected] project] cvs import -m "Project" project horiba project_0_1
N project/init.txt

No conflicts created by this import

CVSに projectをインポートします。

チェックアウトをする
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[[email protected] horiba] mkdir checkout_dir ←チェックアウト用のディレクトリを作成
[[email protected] horiba] cd checkout_dir/
[[email protected] checkout_dir] cvs checkout project ← cvsリポジトリ(projectモジュール)をチェックアウトする。
cvs checkout: Updating project
U project/init.txt
[[email protected] checkout_dir] ll ←チェックアウトできたか確認
合計 0
drwxr-xr-x 3 root root 31  6月  3 16:06 project
[[email protected] checkout_dir] cd project/
[[email protected] project] ll
合計 4
drwxr-xr-x 2 root root 48  6月  3 16:06 CVS
-rw-r--r-- 1 root root 22  6月  3 16:03 init.txt
[[email protected] project] cat init.txt ← 中身を確認
CVS initalize commit.
CVSリポジトリに新たにコミットをする
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[[email protected] project] echo "Add new line" >> init.txt
[[email protected] project] cat init.txt ←追加されていることを確認
CVS initalize commit.
Add new line
[[email protected] project] cvs diff ←リポジトリとの差分チェック
cvs diff: Diffing .
Index: init.txt
===================================================================
RCS file: /home/horiba/cvsroot/project/init.txt,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 init.txt
1a2
> Add new line ←ここが追加されている
[[email protected] project] cvs commit -m "Add new Line" ←コミットメッセージを添えてコミット
cvs commit: Examining .
Checking in init.txt;
/home/horiba/cvsroot/project/init.txt,v  <--  init.txt
new revision: 1.2; previous revision: 1.1
done
CVSリポジトリに新しいファイルを追加する
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
[[email protected] project] echo "New File" > newfile.txt
[[email protected] project] cvs update
cvs update: Updating .
? newfile.txt ← ?マークがついているため、CVSの追跡対象外ファイル
[[email protected] project] cvs add newfile.txt ←CVSの追跡対象にする
cvs add: scheduling file 'newfile.txt' for addition
cvs add: use 'cvs commit' to add this file permanently
[[email protected] project] cvs commit -m "Add newfile.txt"
cvs commit: Examining .
RCS file: /home/horiba/cvsroot/project/newfile.txt,v
done
Checking in newfile.txt;
/home/horiba/cvsroot/project/newfile.txt,v  <--  newfile.txt
initial revision: 1.1
done
[[email protected] project] cvs update
cvs update: Updating .
CVSリポジトリに新しいディレクトリを追加する

ディレクトリはコミットをしなくてもリポジトリに反映される。

1
2
3
4
5
6
7
8
9
[[email protected] project] mkdir src
[[email protected] project] cvs update
cvs update: Updating .
? src
[[email protected] project] cvs add src
Directory /home/horiba/cvsroot/project/src added to the repository
[[email protected] project] cvs update
cvs update: Updating .
cvs update: Updating src

ここまでがCVSの作業です。
テスト用にリポジトリを作成しましたが、実際はもっと巨大なリポジトリになっているはずです。

テスト用にブランチを作成
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[[email protected] project] cvs tag -b new_branch ← new_barnchというブランチを作成
cvs tag: Tagging .
T init.txt
T newfile.txt
cvs tag: Tagging src
[[email protected] project] cvs stat init.txt ←現在のブランチを確認
===================================================================
File: init.txt          Status: Up-to-date

   Working revision:    1.2     Sat Jun  3 07:12:34 2017
   Repository revision: 1.2     /home/horiba/cvsroot/project/init.txt,v
   Sticky Tag:          (none) ← Sticky Tagが(none)なので、現ブランチはtrunk
   Sticky Date:         (none)
   Sticky Options:      (none)

[[email protected] project] cvs update -r new_branch ← ブランチを切り替え(new_branch)
cvs update: Updating .
U init.txt
U newfile.txt
cvs update: Updating src
[[email protected] project] cvs stat init.txt
===================================================================
File: init.txt          Status: Up-to-date

   Working revision:    1.2     Sat Jun  3 07:26:46 2017
   Repository revision: 1.2     /home/horiba/cvsroot/project/init.txt,v
   Sticky Tag:          new_branch (branch: 1.2.2) ← new_branchになっている
   Sticky Date:         (none)
   Sticky Options:      (none)

[[email protected] project] echo "new branch" > branch.txt
[[email protected] project] cvs add branch.txt
cvs add: scheduling file 'branch.txt' for addition on branch 'new_branch'
cvs add: use 'cvs commit' to add this file permanently
[[email protected] project] cvs commit -m "Add branch.txt" ←ブランチにコミット
cvs commit: Examining .
cvs commit: Examining src
RCS file: /home/horiba/cvsroot/project/Attic/branch.txt,v
done
Checking in branch.txt;
/home/horiba/cvsroot/project/Attic/branch.txt,v  <--  branch.txt
new revision: 1.1.2.1; previous revision: 1.1
done

Gitリポジトリへの移行

cvs2gitのツール準備

https://github.com/mhagger/cvs2svn/releases ここから cvs2svn をダウンロードする
(リンク切れであったため修正した。上記のURLに読み替えて以下を作業すること)
解凍をし、make installを行う。

1
2
3
4
[[email protected] horiba] wget http://cvs2svn.tigris.org/files/documents/1462/49237/cvs2svn-2.4.0.tar.gz
[[email protected] horiba] tar zxvf cvs2svn-2.4.0.tar.gz
[[email protected] horiba] mv cvs2svn-2.4.0 cvs2git
[[email protected] horiba] cd cvs2git/
データの準備

CVSROOT 以下と移行したいリポジトリのディレクトリ以下をローカルにコピーしてくる
今回は、/home/horibaにimportというディレクトリを用意し、そこにいれる。

  • CVSROOT
  • インポートしたいプロジェクト
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
データをインポートさせたい場所に移動
[[email protected] horiba] ll  
合計 4
drwxr-xr-x  3 root root   20  6月  3 16:06 checkout_dir
drwxrwxr-x 10  501  501 4096  6月  3 17:04 cvs2git
drwxr-xr-x  4 root root   34  6月  3 16:03 cvsroot
drwxr-xr-x  2 root root    6  6月  3 17:17 import
drwxr-xr-x  3 root root   20  6月  3 16:00 work
[[email protected] horiba] cp cvsroot/CVSROOT/ import/ -R  
[[email protected] horiba] cp cvsroot/project/ import/ -R  
[[email protected] cvsroot] cd /home/horiba/  

データをインポートする  
[[email protected] horiba]# cvs2git --blobfile=git-blob.dat --dumpfile=git-dump.dat --username=horiba--encoding=utf-8 --fallback-encoding=utf-8 import/
----- pass 1 (CollectRevsPass) -----
Examining all CVS ',v' files...
import/CVSROOT/checkoutlist,v
import/CVSROOT/commitinfo,v
import/CVSROOT/config,v
import/CVSROOT/cvswrappers,v
import/CVSROOT/editinfo,v
import/CVSROOT/loginfo,v
import/CVSROOT/modules,v
import/CVSROOT/notify,v
import/CVSROOT/rcsinfo,v
import/CVSROOT/taginfo,v
import/CVSROOT/verifymsg,v
import/project/init.txt,v
import/project/newfile.txt,v
import/project/Attic/branch.txt,v
Done
Time for pass1 (CollectRevsPass): 0.024 seconds.
----- pass 2 (CleanMetadataPass) -----
Converting metadata to UTF8...
Done
Time for pass2 (CleanMetadataPass): 0.007 seconds.
----- pass 3 (CollateSymbolsPass) -----
Checking for forced tags with commits...
Done
Time for pass3 (CollateSymbolsPass): 0.007 seconds.
----- pass 4 (FilterSymbolsPass) -----
Filtering out excluded symbols and summarizing items...
Done
Time for pass4 (FilterSymbolsPass): 0.093 seconds.
----- pass 5 (SortRevisionsPass) -----
Sorting CVS revision summaries...
Done
Time for pass5 (SortRevisionsPass): 0.005 seconds.
----- pass 6 (SortSymbolsPass) -----
Sorting CVS symbol summaries...
Done
Time for pass6 (SortSymbolsPass): 0.004 seconds.
----- pass 7 (InitializeChangesetsPass) -----
Creating preliminary commit sets...
Done
Time for pass7 (InitializeChangesetsPass): 0.009 seconds.
----- pass 8 (BreakRevisionChangesetCyclesPass) -----
Breaking revision changeset dependency cycles...
Done
Time for pass8 (BreakRevisionChangesetCyclesPass): 0.009 seconds.
----- pass 9 (RevisionTopologicalSortPass) -----
Generating CVSRevisions in commit order...
Done
Time for pass9 (RevisionTopologicalSortPass): 0.009 seconds.
----- pass 10 (BreakSymbolChangesetCyclesPass) -----
Breaking symbol changeset dependency cycles...
Done
Time for pass10 (BreakSymbolChangesetCyclesPass): 0.007 seconds.
----- pass 11 (BreakAllChangesetCyclesPass) -----
Breaking CVSSymbol dependency loops...
Done
Time for pass11 (BreakAllChangesetCyclesPass): 0.008 seconds.
----- pass 12 (TopologicalSortPass) -----
Generating CVSRevisions in commit order...
Done
Time for pass12 (TopologicalSortPass): 0.007 seconds.
----- pass 13 (CreateRevsPass) -----
Mapping CVS revisions to Subversion commits...
Creating Subversion r1 (Project initialization)
Creating Subversion r2 (commit)
Creating Subversion r3 (commit)
Creating Subversion r4 (copying to tag 'project_0_1')
Creating Subversion r5 (commit)
Creating Subversion r6 (commit)
Creating Subversion r7 (copying to branch 'new_branch')
Creating Subversion r8 (commit)
Done
Time for pass13 (CreateRevsPass): 0.010 seconds.
----- pass 14 (SortSymbolOpeningsClosingsPass) -----
Sorting symbolic name source revisions...
Done
Time for pass14 (SortSymbolOpeningsClosingsPass): 0.005 seconds.
----- pass 15 (IndexSymbolsPass) -----
Determining offsets for all symbolic names...
Done.
Time for pass15 (IndexSymbolsPass): 0.003 seconds.
----- pass 16 (OutputPass) -----
Time for pass16 (OutputPass): 0.007 seconds.

cvs2svn Statistics:
------------------
Total CVS Files:                14
Total CVS Revisions:            15
Total CVS Branches:              2
Total CVS Tags:                  1
Total Unique Tags:               1
Total Unique Branches:           1
CVS Repos Size in KB:           12
Total SVN Commits:               8
First Revision Date:    Sat Jun  3 15:51:18 2017
Last Revision Date:     Sat Jun  3 16:27:39 2017
------------------
Timings (seconds):
------------------
0.024   pass1    CollectRevsPass
0.007   pass2    CleanMetadataPass
0.007   pass3    CollateSymbolsPass
0.093   pass4    FilterSymbolsPass
0.005   pass5    SortRevisionsPass
0.004   pass6    SortSymbolsPass
0.009   pass7    InitializeChangesetsPass
0.009   pass8    BreakRevisionChangesetCyclesPass
0.009   pass9    RevisionTopologicalSortPass
0.007   pass10   BreakSymbolChangesetCyclesPass
0.008   pass11   BreakAllChangesetCyclesPass
0.007   pass12   TopologicalSortPass
0.010   pass13   CreateRevsPass
0.005   pass14   SortSymbolOpeningsClosingsPass
0.003   pass15   IndexSymbolsPass
0.007   pass16   OutputPass
0.213   total

[[email protected] horiba]# ll
合計 20
drwxr-xr-x  3 root root    20  6月  3 16:06 checkout_dir
drwxrwxr-x 10  501  501  4096  6月  3 17:04 cvs2git
drwxr-xr-x  4 root root    34  6月  3 16:03 cvsroot
-rw-r--r--  1 root root 10158  6月  3 17:22 git-blob.dat
-rw-r--r--  1 root root  2554  6月  3 17:22 git-dump.dat
drwxr-xr-x  4 root root    34  6月  3 17:20 import
drwxr-xr-x  3 root root    20  6月  3 16:00 work

.datが作成されている
Gitリポジトリへ反映

反映するようのGitリポジトリを作成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[[email protected] horiba] mkdir git_repo
[[email protected] horiba]# cd git_repo/
[[email protected] git_repo]# git init
Initialized empty Git repository in /home/horiba/git_repo/.git/
[[email protected] git_repo]# cat ../git-blob.dat ../git-dump.dat | git fast-import
git-fast-import statistics:
---------------------------------------------------------------------
Alloc d objects:       5000
Total objects:           34 (         0 duplicates                  )
      blobs  :           15 (         0 duplicates          3 deltas of         13 attempts)
      trees  :           12 (         0 duplicates          5 deltas of         12 attempts)
      commits:            7 (         0 duplicates          0 deltas of          0 attempts)
      tags   :            0 (         0 duplicates          0 deltas of          0 attempts)
Total branches:           4 (         3 loads     )
      marks:     1073741824 (        22 unique    )
      atoms:             16
Memory total:          2344 KiB
       pools:          2110 KiB
     objects:           234 KiB
---------------------------------------------------------------------
pack_report: getpagesize()            =       4096
pack_report: core.packedGitWindowSize = 1073741824
pack_report: core.packedGitLimit      = 8589934592
pack_report: pack_used_ctr            =         15
pack_report: pack_mmap_calls          =          4
pack_report: pack_open_windows        =          1 /          1
pack_report: pack_mapped              =       7234 /       7234
---------------------------------------------------------------------
Gitリポジトリの反映確認
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
リポジトリ確認
[[email protected] git_repo] ll
合計 4
drwxr-xr-x 2 root root 4096  6月  3 17:25 CVSROOT
drwxr-xr-x 2 root root   39  6月  3 17:25 project

ログ確認
[[email protected] git_repo]# git log
commit cda9cc6531facb46b873267e9d313d923f1d5bce
Author: horiba <>
Date:   Sat Jun 3 07:16:13 2017 +0000

    Add newfile.txt

commit 0161fd85c89b575294a48a08e4b9eb96dfe38bf6
Author: horiba <>
Date:   Sat Jun 3 07:13:00 2017 +0000

    Add new Line

commit b67ce725fa1ad57d24cc99d19bf4a91d504c76d3
Author: horiba <>
Date:   Sat Jun 3 07:03:28 2017 +0000

    Project

commit 9069a0b5297af1a034086dd2d6b210f622ab74fd
Author: horiba <>
Date:   Sat Jun 3 06:51:18 2017 +0000

    initial checkin

ブランチ確認
[[email protected] git_repo]# git branch -a
* master
  new_branch
[[email protected] git_repo]#

チェックアウト時のログ確認
[[email protected] git_repo]# git checkout new_branch
Switched to branch 'new_branch'
[[email protected] git_repo]# git log
commit f5fd22bedc9541926bf5e672331c69d4cffff819
Author: horiba <>
Date:   Sat Jun 3 07:27:39 2017 +0000

    Add branch.txt

commit 49710aa5e3f06f97bfe6b70f571471c4faca8b40
Author: horiba--encoding=utf-8 <>
Date:   Sat Jun 3 07:16:14 2017 +0000

    This commit was manufactured by cvs2svn to create branch 'new_branch'.

    Sprout from master 2017-06-03 07:16:13 UTC horiba 'Add newfile.txt'
    Delete:
        CVSROOT/checkoutlist
        CVSROOT/commitinfo
        CVSROOT/config
        CVSROOT/cvswrappers
        CVSROOT/editinfo
        CVSROOT/loginfo
        CVSROOT/modules
        CVSROOT/notify
        CVSROOT/rcsinfo
        CVSROOT/taginfo
        CVSROOT/verifymsg

commit cda9cc6531facb46b873267e9d313d923f1d5bce
Author: horiba <>
Date:   Sat Jun 3 07:16:13 2017 +0000

    Add newfile.txt

commit 0161fd85c89b575294a48a08e4b9eb96dfe38bf6
Author: horiba <>
Date:   Sat Jun 3 07:13:00 2017 +0000

    Add new Line

commit b67ce725fa1ad57d24cc99d19bf4a91d504c76d3
Author: horiba <>
Date:   Sat Jun 3 07:03:28 2017 +0000

    Project

commit 9069a0b5297af1a034086dd2d6b210f622ab74fd
Author: horiba <>
Date:   Sat Jun 3 06:51:18 2017 +0000

    initial checkin

CVSROOTは、masterブランチに存在しているが、不要なので下記コマンドで削除しておく。
[[email protected] git_repo]# rm -fR CVSROOT/

あとは、Gitリポジトリを好きに、リモートに登録して、ブランチを全てプッシュしてあげれば良い。

移行について

CVSはファイル単位での履歴管理なので、どこでバグったかがわかりにくい。
また、修正差分がわかりにくい。
その点Gitはコミット単位での履歴管理なので、修正ファイルが一緒に差分として出せたりするので、とても便利。
Gitは積極的に使うべきであろう。ある程度の操作も覚えるべきだと思う。