Git vs Subversion

そもそも何が出来るのか。何をしていないのか

  • ファイルの状態を意味単位で管理する事が出来る
    • ファイルを書き換えるごとに勝手に保存するシステムではない。人間が自発的にファイルの状態にコメントをつけて管理していく
  • ファイルを過去の状態に戻す事が出来る
    • ただしコミットした時の状態にしか戻せない
  • 複数のバージョンのファイルを維持出来る
    • 状態Aから分岐した状態B、状態B'、状態B''などを同時に維持する事が出来る

できること

調べた端から書いていこうね。
空白は概念として存在しない箇所です。

できること Git Subversion 備考
中央リポジトリ作成 git init --bare 'リポジトリ名.git' svnadmin create 'リポジトリ名' リポジトリ名のフォルダがカレントディレクトリに作成されます
中央リポジトリからファイルを初めて持ってくる git clone 'リポジトリ名' svn checkout 'リポジトリ名' リポジトリ名にはsshなどが使用できます
コミット git add 'コミットしたいファイル名'; git commit; svn add '管理対象にするファイル名'; svn commit; ブランチに対してコミットを行います。svn addは不要な場合があります
ステージングエリア git add コミットするファイルを指定します
ブランチ作成 git branch 'ブランチ名' svn copy 'svnの管理対象となっているディレクトリ名' 'ブランチとして作成するディレクトリ名'; svn commit; Gitとsvnのブランチ管理の方法はかなり違うように思われます
ブランチへの移動 git checkout 'ブランチ名' cd
あるいは、普通にファイラなどで移動
svnはフォルダ自身がブランチのようです
ブランチの削除 git branch -d 'ブランチ名' svn remove 'ブランチとなるフォルダ'; svn commit;
コンフリクト発生時の対応 コンフリクトが起きたファイルを書き換え、git add 'ファイル'; git commit
git checkout –theirs .
git checkout –ours .
コンフリクトが起きたファイルを書き換え、svn resolved 'ファイル名'、svn commit
変更前のファイル、変更後のファイル、中央リポジトリ上最新の3つのファイルを自動生成されるので、それらをリネームした上で、svn resolved 'ファイル名'、svn commit
ファイルロック svn lock 'ファイル名'
ファイルを特定のコミットまで戻したい(1:バージョンを下っていく) git logで戻りたいコミットのハッシュをコピペする→「git branch 'ブランチ名' ハッシュ値 svn merge -r 現在のリビジョン:戻りたいリビジョン 'リポジトリ名'」
ファイルを特定のコミットまで戻したい(2:ブランチを破棄する) git branch -d 'ブランチ名' svn rm 'フォルダ名'; svn commit 何かをやる前にブランチを作り、作業に失敗したらブランチを丸ごと破棄するスタイルです
中央リポジトリに修正したファイルを送る git push svn commit
管理外にしたいファイルを指定したい .gitignoreファイルを.gitファイルと同じディレクトリに入れる svn propset svn:ignore
タグを付ける git tag 'タグ名' svn copy 'タグとして作成するディレクトリ名'
コミット前の修正を消して元に戻したい git checkout 'ファイル名'
git stash
svn revert 'ファイル名' git checkoutとsvn revertは、自分のPC上にある修正をなかった事にするものです。状態が記録されないので注意が必要です。git stashは現在の変更を一時的に保存/書き戻しが出来るコマンドで、「git checkout .」より安全です
コミット間で変更のあったファイルのみを抽出する git archive --format=zip --prefix=projectname/ HEAD `git diff --name-only ブランチ名` -o '保存するファイル名' 可能。参考:http://rontan.sakura.ne.jp/2010/04/tips_tortoisesvn_export/:url

中央リポジトリとはなんですか

作成されたファイルを集約するための置場のようなものです。
ファイル置場ですが、普通にアクセスしてもファイルそのものがそこに存在するわけではないようです。

分散型と集約型ってなんですか

そんなの気にするな。バージョン管理システムの良し悪しはそれで決まるものではありません。

コミットとはなんですか

簡単にいうとCtrl + sです。
コミットを行うと、その状態でファイルを保存してくれます。
何かが発生してファイルの状態を戻したい場合、コミット単位でファイルを戻す事が出来ます。
コミットはブランチに対して行います。

マージとはなんですか

2つある何かを合体させて1つにする事です。
ブランチAとブランチBをマージすると、マージする側に差分を加筆してくれます。

コンフリクトとはなんですか

ブランチAとブランチBに不整合があって上手くマージできない場合、コンフリクトという状態になります。
コンフリクトが発生した場合は、人間の手でファイルを修正し、コミットし直さなければなりません。

その他概念

概念 Git Subversion
中央リポジトリからローカルへのダウンロード 必要なものだけ 管理対象全て(ブランチ、タグ込み)
ブランチ コミットの別名 ファイルのコピー
タグ コミットの別名 or 状態のコピー ファイルのコピー

良さそうなクライアントはありませんか

Git
クライアント名 Win Mac URL 備考
SourceTree http://www.atlassian.com/ja/software/sourcetree/overview Mac版、Windows版とどちらも使いやすく見やすいです
msysGit https://code.google.com/p/msysgit/ WindowsCUIクライアント。あればあったで便利
GitHub for Windows http://windows.github.com/ 見た目爽やか。ただし機能が限定されているため、コマンドを打つ時の補助に使うような感じです。コマンドラインからGitを使いたい場合はこれを入れるとやりやすいでしょう
EGit http://www.eclipse.org/egit/ Eclipseプラグイン。右クリックメニューで各種操作を行います
Subversion
クライアント名 Win Mac URL 備考
TortoiseSVN http://tortoisesvn.net/ Windowsのファイラを使う事を前提としたクライアント。右クリックメニューで操作が行えます。直感的でとても分かりやすいです
Subversion (SVN) Team Provider http://www.eclipse.org/subversive/ Eclipseプラグイン。こちらも右クリックメニューで操作が行えます。ブランチを駆使しようとすると、ビルドパスの関係でとても使いづらい

どうやって使うんですか

簡単な流れ
やること Git Subversion 備考
中央リポジトリを立てる git inti --bare 'リポジトリ名.git' svnadmin create 'リポジトリ名' Gitでは中央リポジトリの末尾に.gitを入れる習慣があるようです
中央リポジトリから各位のPCにファイルを落とす git clone 'リポジトリ名' svn checkout 'リポジトリ名' 中央サーバを立てた場合、リポジトリ名にsshを使用する事もできます
ファイルを追加/修正します…
ファイルを追加した場合 svn add '追加したファイル名' svn add *で追加したファイルを全て選択する事が出来ます
ファイルの追加、変更をステージングにaddする git add '追加/変更したファイル名' git add .とすれば一気にステージングにaddする事も可能です
ファイルをコミットする git commit -m 'コミットメッセージ' svn commit -m 'コミットメッセージ' コミットをする事で、そのブランチ上の状態を保存する事が出来ます
変更内容を中央リポジトリに送信する git push Subversionはコミット時に送信されます
おしまい
ちょっと高度な流れ
やること Git Subversion 備考
...ファイルを落とすまでは省略します...
作業用ブランチを作成します git branch '作業用ブランチ名' svn copy 'ブランチを作成するディレクトリ名' Gitでは、ブランチはコミットに対する参照のようなものです
Subversionでは、コマンド名の通りファイルをそのままコピーします
作業用ブランチに移動します git checkout '作業用ブランチ名' 普通にディレクトリを移動します
ファイルを追加/修正します…
ファイルを追加した場合 svn add '追加したファイル名'
ファイルの追加、変更をステージングにaddする git add '追加/変更したファイル名' git add .とすれば一気にステージングにaddする事も可能です
ファイルをコミットする git commit -m 'コミットメッセージ' svn commit -m 'コミットメッセージ' コミットをする事で、そのブランチ上の状態を保存する事が出来ます
とりあえずやる svn update svn updateを行われないと最新の情報を取得出来ず、マージの時に上手くいかない場合があるようです
移動前のブランチに移動します git checkout '移動前のブランチ名' 普通にディレクトリを移動します git checkoutすると修正前の状態に戻りますが、変更はちゃんと残っています
ブランチをマージします git merge '作業用ブランチ名' svn merge '作業したディレクトリ名'」 移動前のブランチに、作業した内容を加筆します
マージした結果をコミットします svn commit -m 'コミットメッセージ' Gitはmergeと同時にコミットされたものとして扱われます
変更内容を中央リポジトリに送信する git push Subversionはコミット時に送信されます
おしまい

所感

導入して何が得なのか?
  • いつ、何をどう変更したのかが追えます
  • よくあるパターン

プロジェクトマネージャー「ファイルサーバのこのディレクトリに、修正したファイルを置いていこう! 何か実装する時はファイルサーバのやつコピーしてからやってね! みんなこのルールを守ってね!」
プログラマ・デザイナ「はーい」


複数人で色々実装し、納品直前になって…
プログラマ・デザイナ「あれ、やったはずの修正が消えてるんだけど?」


_人人人人人人人人人人人人人人人人人人人_
> やったはずの修正が消えてるんだけど? <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

  • ファイルの単純上書きでは何をやったかが追えません
    • 追えないため、一度やった修正を再度行わなければなりません
      • 減っていくやる気(ブラウザが落ちてブログ記事が消失した時の喪失感)
      • 時間がないためやっつけ対応で品質が低下
      • 社内社外を問わずあらゆる人間の信用が失墜
    • もしバージョン管理システムを使って、こまめにコミットして記録を作っておけば…
      • 誰が何を修正したかが追える
      • 修正が消えても前のコードを追えるため、マージしたり、戻したり出来る
      • 社内社外を問わずあらゆる人間の信用が損なわれない。やったね!


もちろんですが、バージョン管理システムも使い方が悪ければ当然追えません。こまめなコミットは必要でしょう。
しかし、単純にファイルを上書きするだけの原始的な管理よりもずっと安心出来ます。

ファイルロックさえかければコンフリクトは発生しないのか

発生します。
ファイルロックは「他人から特定ファイルのコミットが行えないよう妨害する」であって、「ロックをかけたら全ての人間がそのファイルをいじれない」ではありません


設定次第ではファイルロックをかけた人以外は読み込み専用ファイルにする事が出来ます。
ただ普通に読み込み専用ファイルになるだけなので、ファイルの読み込み・書き込み設定を変えると普通に書き換えは可能です。
//しかもなんだかread onlyになったりならなかったりするような気がする
参考:http://hide.xsv.info/tips/svnmanual/filelock/:url

マージ時の優秀さはGitの方が上

単純にメソッド一個追加しただけでSubversionはすぐコンフリクト扱いします。
Gitの場合、上手くひとまとめにしてくれます。