バージョン管理のすゝめ

# 0.1. はじめに ver.0.1
　元々は学内団体向けの記事として作成しましたが、入門者向けに幅広く使えそうなので公開します。
　ゲーム制作でバックアップ撮らずに作業してたら、突然HDD死んでプロジェクトデータ消えた…みたいなことがありませんでしたか？
　(僕は昔USBでやらかしました… 死にたくなりました)
　このような悲劇的な事故を起こさないためにも日頃からバックアップをとる習慣をつけましょう。

# 1. はじめに ver.1.0
　じゃあバックアップはどうやって取ろうか？
　一定時間ごとにプロジェクトフォルダ圧縮して、ファイル名変えて…

　こんなことやってるともれなくファイル名が悲惨なことになるのでやめましょう。

- Backup
    - HogeProject20200904_01
    - HogeProject20200904_02
    - HogeProject20200906_Final
    - HogeProject20200906_Final_02
    - HogeProject20200906_Final_Final
    - HogeProject20200906_Final_Final_Fin
    - HogeProject20200906_Final_Final_Fin_02

　キリがなくなるのでやめます…

　今までこういう命名して苦労してきたって人も少なくないと思います。
　このような無駄な労力を避けるためにも、次に説明する**バージョン管理ツール**を採用するようにしましょう。

# 2. バージョン管理ツールとは
　`バージョン管理ツール`(version control system, 以下vcs)とはファイル群の変更履歴を管理するためのツールです。
　当たり前のように聞こえるかもしれませんが、大事なのは**変更履歴**を差分を取って管理するということです。
　算数あるいは数学で学んだ樹形図のように変更履歴を記録してくれます。
　ある段階まで遡ったり、パラレルワールドのように用途に合わせて分岐させることも可能です(詳細は後程)。
　
　また`はじめに`で書いたダメな例のようにバックアップを取るたびにすべてコピーしていては、容量が大変なことになりますよね？
　vcsを導入することでバックアップ時の**容量削減**にも繋がります。

　ここまでvcsのメリットについて紹介してきました。次は具体的なツールの説明をしていきます。

#3. Git
　おそらく今世の中で最も主流のvcsです。次に説明するSubversionなどと比較して`分散型`と位置付けられています(最初は覚えなくていいです)。

## 3.1. 下準備

　使用にはPCにGitを導入する必要があります。
　Windowsの人は[Git for Windows](https://gitforwindows.org/)のリンクに飛んでダウンロードしましょう。
　Macの人は元々入っているので何もしなくて大丈夫です。

　以下Windowsを基準に説明していきます。Macの場合の相違点は適宜説明していきます。

　Gitはコマンドを実行することで操作していきます。
　最初はよくわからない文字列ばかりで難しく思うかもしれませんが、実際覚えることは少ないので安心してくださいね。
　なお今回はUnityを想定して説明していきます。

　ここからの作業はWindowsなら`Git CMD`、Macなら`ターミナル`を開いて作業してください(以下ターミナルと呼びます)。
　
　まずターミナルでAssetsフォルダがある階層を開きます。
　![GitSample 2020_09_08 23_48_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327253/27f84c9f-4951-f457-fe8e-0594568feb5f.png)


　例えば写真のプロジェクトはG:/Develop/Unity/GitSampleにあるので、次のコマンドで移動できます。

```sh
cd/d G:/Develop/Unity/GitSample
```

## 3.2. バージョン管理しないリスト (.gitignore)
　Unityプロジェクトを構成するファイル一覧が掲載されています。
　このうち全てをバージョン管理する必要はないので、バージョン管理しないファイルリストを作成します。
　**.gitignore**というファイルを作成し、その中に記述します。

　ここでは一般的なUnityプロジェクトで使用されるものを掲載しておきます。
　導入する外部ツールなどに応じて適宜変更してください。

<details>
  <summary>.gitignore (例)</summary>
  <div>

```
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/Assets/AssetStoreTools*

# Visual Studio cache directory
.vs/

# vscode
.vscode/

# Autogenerated VS/MD solution and project files
ExportedObj/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.opendb

# Unity3D generated meta files
*.pidb.meta
*.pdb.meta

# Unity3D Generated File On Crash Reports
sysinfo.txt

# Builds
*.apk
*.unitypackage

# OS generated
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db

#log files, for some plugins
*.log

#python bytecode cache, for some plugins.
*.pyc
```

  </div>
</details>

## 3.3. リポジトリ初期化 (git init)

　次にこの階層(以下ディレクトリと呼びます)をGitで管理するために`初期化`します。

```sh
　git init
```

　Assetsフォルダがあるディレクトリまで移動し、上のコマンドを実行しましょう。
　このコマンドによりディレクトリがGitのために初期化されます。
　Gitが使える状態のディレクトリをGitリポジトリと呼びます。

## 3.4. Git管理下に追加 (git add)
　これでGitを使う準備ができました。次に管理する`ファイルを登録`します。　

```sh
git add .
```

　このコマンドを実行することで、.gitignoreに記載されていないすべてのファイルがGitの管理下に追加されます。

## 3.5. コミット (git commit)
　次はいよいよ変更履歴を記録していきます。

```sh
git commit -m "<commit message>"
```

　`<commit message>`にはコミットの理由やファイルの状態などを書き残しておきます (<>は不要です)。
　後々見返したときにわかりやすくするためです。
　このコマンドを実行すると現段階での変更情報が保存されます。

## 3.6. リモートリポジトリの追加 (git remote add)
　ここまでを実行することで、自分のPC上には変更履歴が記録されるようになっています。
　Gitでは外部サーバー上に`リモートリポジトリ`を追加し、変更履歴を共有することができます。
　外部サービスにはいろいろな種類がありますが、今回は`GitHub`を利用します。

　![Create a New Repository - Google Chrome 2020_09_09 11_09_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327253/4584b612-cf6e-3cfb-89c3-0b8c4dfc654a.png)

　`New`を押して上の写真のように設定します。
　`Create repository`を押し、リポジトリを作成します。

　続いてターミナルでの作業に戻ります。
　リモートリポジトリをローカル上のリポジトリで追加するには以下のコマンドを実行します。

```sh
git remote add origin <URL>
```

![Create a New Repository - Google Chrome 2020_09_09 11_25_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327253/57d4ba36-7f39-efe1-fa0a-e1c2a4faa3fa.png)

　URLには上の写真に記載されているURLを使用します (<>は不要です)。

## 3.7. リモートに反映 (git push)
　続いて今追加したリモートリポジトリにローカルリポジトリの変更を共有します。

```sh
git push origin master
```

　このコマンドを実行することでリモートリポジトリにコミットが反映されます。

## 3.8. 複数人での共有
　GitHubには`Collaborator`という機能があり、これを利用することで複数人で一つのリポジトリにpushすることができます。
　リポジトリのSettings -> Manage Accessからユーザーを追加できます。

　詳細は実演で説明します。
　リモートリポジトリを自分のPCに複製するにはクローンします。

```sh
git clone <URL>
```
 URLには上のリモートリポジトリの追加で使用したものと同じものです。

## 3.9. 他人の変更をローカルに反映 (git pull)
　他人がpushしたリポジトリへの変更を取り入れるには以下のコマンドを使います。

```sh
git pull origin  master
```

## 3.10. クライアントソフトの利用
　ここまでコマンドによる操作でGitを使用してきました。
　コマンド操作と同様の行程をGUIで可能にしたソフトがクライアントソフトです。
　
　以下いくらかツールを紹介します。

- `GitHub Desktop`
    - GitHubの公式クライアントソフトです。
- `Source Tree`
    - GitHubだけでなくBitBucketやGitLabなどにも対応しています。

## 3.11. [発展] ブランチ (branch)
　ブランチとは木の枝という意味ですが、Gitではコミットしたポイントから複数のラインで並行して編集ラインを立てることができます。
　またそれらを任意のタイミングで統合(マージ)することも可能です。
　正しく使うと機能ごとやリリースごとにブランチを切ることで強力な効果を発揮しますが、適当にやっても無駄に面倒になるだけなので使う前には勉強しておくことをお勧めします。
　興味がある人は`Git-flow`などで検索してみてもいいかもしれません。

## 3.12. [発展] バイナリファイルに注意
　最初に説明した通り、差分を取って管理することで時間や容量を抑えています。
　ここで注意が必要で、テキストファイルは差分が取れますがバイナリファイルは差分が取れません。
　よってバイナリファイルは変更が入るたびに丸ごと管理するようになっています。
　このためバイナリファイルの数や容量によっては`プッシュやプルに時間がかかる`ことも出てきます。
　あまりに時間がかかるようであれば、バイナリファイルはGit以外で管理するのがいいかもしれません。


## 3.13. 前の状態に戻す (git reset)
作業をしていて間違えたとき、以前のバージョンに戻したいことがあると思います。
その際は次のコマンドで任意のタイミングのコミットに戻ることができます。

```sh
git reset --hard <コミットID>

# コミットIDの確認方法
git log
# 長い英数字が出ています。それがコミットIDです。

# 直前の最新コミットに戻す方法
git reset --hard HEAD
```

# 4. Subversion
　SubversionもGitと同様、バージョン管理ツールの一つです。
　Gitと比較して`集中型`と位置付けられています。
　Subversionもコマンドで扱うことができますが、こちらはクライアントソフトを利用していきたいと思います。
　
　Windowsの人は[Tortoise SVN](https://tortoisesvn.net/)、Macの人は[Snail SVN](https://apps.apple.com/jp/app/snailsvn-lite-svn-for-finder/id1063090543?mt=12)がおすすめです。
　
　Gitと比較した際に特徴的な相違点は`リポジトリがリモート一つ`のみであることです。
　GitもSubversionもローカルにコピーして作業した後リモートに反映するという流れは同じです。
　ただしGitはローカルにコミットした後リモートにプッシュするのに対し、Subversionにはローカルリポジトリはただのコピーであり、直接`リモートリポジトリにコミット`するようになっています。

　基本的な使い方はGitと変わらないので、ここでは相違点を中心に説明します。

## 4.1. コミット&リモートへ反映 (commit)
　前述のとおりSubversionではリモートリポジトリに直接コミットするようになっています。
　ですのでGitのようにコミットしてからプッシュするのではなく、`コミットするだけでリモートに反映`することができます。

## 4.2. リポジトリをローカルにコピー (checkout)
　Gitではリモートリポジトリからローカルリポジトリを作成する際cloneしていました。
　Subversionでは`checkout`となっています。

　尤もgit cloneはローカルにもオリジナルのリポジトリを作成しているのに対し、Subversionではあくまでコピーなので正確には全く同じではないです。

## 4.3. リモートの変更を反映 (update)
　Gitでpullでしたが、Subversionでは`update`になっています。

---

力尽きたのでこの辺にしておきます。
Subversion編、要望あれば追記するかもです。