VSSやTFSからGitへ移行したとき悩んだときに読んでほしいこと

# はじめに
VSS（Visual Source Safe）や TFS（Team Foundation Server）から Git へ移行すると、その考え方の違いを理解することに苦労する。

Gitを使い始めるにあたり、Git特有の用語や仕組みについて、すべてを最初から理解する必要はない。

必要なときに、その都度 覚えるのがよさそう。

ここでは、各フェーズでの理解の仕方をまとめる。

# VSS / TFS
- 中央集中型のVCS（Version Control System）
- サーバのデータベースに対して、各クライアントが接続し、直接ファイルを変更するイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/97edf243-2f79-07d1-5d82-f0001ee0f851.png)

# Git
- 分散型のVCS
- VSS/TFSと大きく異なるのは、各クライアントがローカルリポジトリというデータベースを持つところ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/6bb2c39b-d6ec-ac34-e352-299d83dab294.png)

## STEP1：VSS/TFSのように使う
まずは、VSS/TFS相当の使い方をおこなうステップ
細かいことは置いておいて、VSS/TFSと思って利用する場合は、この程度の理解で使い始めてOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/6e9e935b-88e1-94cc-7b7b-d05215929c94.png)

| VSS/TFS                                                      | Git                                                          |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| 1. 最新バージョンの取得<br/>2. チェックアウト<br/>3. ファイルを変更<br/>4. チェックイン | 1. クローン<br/>2. ファイルを変更する<br/>3. コミット<br/>4. プッシュ

- クローン（clone）
    - VSS/TFSの最新バージョンの取得のように、サーバから最新のファイル群を取得する
- コミット（commit）と プッシュ（push）
    - VSS/TFSのチェックインをするなら、コミット＆プッシュの両方をするんだな 程度に覚えておく

## STEP2：リポジトリを意識し始める
なんかローカルリポジトリに、リモートリポジトリにあるはずの履歴がないなぁ と疑問を感じ始めたら。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/617954f2-2fb9-90c3-607a-c7933db78e4b.png)

- リポジトリ
    - 履歴の情報をすべて持っている
- リモートリポジトリ
    - サーバにあるリポジトリ
- ローカルリポジトリ
    - ローカルPCにあるリポジトリ
- クローン（clone）
    - サーバからローカルリポジトリを作成。その後ローカルリポジトリから必要なファイル群が生成される
- コミット（commit）
    - 変更したファイルをローカルリポジトリに入れる
- プッシュ（push）
    - ローカルリポジトリにコミットされたものを、リモートリポジトリへ送る
- フェッチ（fetch）
    - ローカルリポジトリにリモートリポジトリから履歴情報のみを取得する（ファイルは何も変化しないので、お気軽に）


## STEP3：マージの登場
なんかプッシュするときにプルしろと怒られる。。。
VSS/TFSを使っているときはあり得ない状況なので、まずこれが理解できなかった。
そして、コンフリクト（衝突）もないのに、なぜマージという言葉が出てくるのか？

いろいろ難しいが、まずはこの状況でプルするときは、<b>『リベース（rebase）』のマージをする</b>と覚えておけばよいかと思う。
リベースにしておけば、履歴が1本で繋がる。
使っているGitクライアントによるが、基本的にリベースは標準無効なので、意識的に選択する必要がある。
これを忘れると、『なんか履歴の枝分かれが出たり出なかったりして見ずらい』となる。

## STEP4：master/head
### master
- gitでリポジトリを作成すると、デフォルトで作成されるものをmasterブランチと呼ぶ
- このmasterブランチを、プロジェクトの本流/マスターと位置づけることが多い

### head
- ローカルリポジトリでheadは現在いる場所（ブランチ）を示す
- リモートリポジトリでのheadは、クローンしたときのデフォルトのブランチを示す。つまり、リモートリポジトリからクローンしたとき、何も指定がないと通常masterブランチがチェックアウトされるのはこのためである。gitコマンドで変更できるようだが試したことはない。（https://git-scm.com/docs/git-symbolic-ref ）

## STEP5：ブランチのマージ
ブランチを作ってから作業完了するまでに、masterブランチに別の変更がコミットされている場合、何も考えずにコミットすると、履歴の分岐がブランチ作成から現在までになるが、できれば、masterブランチの最新から別れて戻るほうが後々分かりやすい。少し気を使った操作をしてあげないとこのような形にならないため、以下に手順の例を示す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/adf3f17c-98ec-ddd5-ee6c-58f41205f20e.png)
（M2の時点でBranchAを作成しB1,B2をコミット。その間masterブランチもM3,M4とコミットが進んでいる状態）

## 手順（GitクライアントアプリForkでの例）
### リベースでmasterの最新コミットへbranchの根本を移動しマージ
1. BranchAをmasterにrebase
BranchAに移動した状態で、masterを選択し、BranchAをrebase
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/9189b830-acd5-9bdd-98a8-606971d11412.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/406400bd-d7d6-47d6-a6ed-5f58f1073026.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/b64c97fe-ddae-5bc7-a0ca-4d9a55617740.png)

2. masterにBranchAをマージ (no fast forward)
masterに移動する
BranchAをmasterにmerge (no fast forward) する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/18308e62-df17-9450-fb45-8ebc6834c631.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/eb8a4e45-ffa5-3e63-f8ec-cf5904b91f91.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/cd098b17-ad73-da21-082f-d4a9ae65462a.png)

3. masterをpush
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/7afc24d9-272f-75ce-c426-5461c6525d03.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/c36644c4-41ac-3028-71c0-8248bc310889.png)

### 不要なbranch（ローカル/リモート）を削除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/2f4e8783-7126-5f79-51f2-bec31aae805d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/acb8b1c8-b98f-3fe6-30aa-3a130dcfebab.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/734fa8ba-3c82-c81c-e53e-445a17ffb710.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/b6e736a4-253e-6694-e747-c2ecad3d5ed6.png)


## STEP6：チェリーピック
リリースブランチ（BranchA）にmasterブランチの一部を取り込みたい場合があるが、そういうときは「チェリーピック」が利用できる。
以下、masterのM4のみをBranchAに入れるときの例。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/22c98096-de6f-58b8-10e5-19f65593a697.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/13ccd117-53cc-0f61-2538-fb445940d293.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/7b5346c0-53f8-187d-c4d8-1c81e05fb0a3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/1f70150c-5089-88b5-9348-9ed58bcc3fea.png)

## STEP7：マージ（squash）
開発ブランチ（BranchA）から、masterブランチへマージする際に、ブランチでのコミット履歴を1つにまとめてコミットしたいことがある。その場合は、margeのsquashを利用できる。
以下、BranchAのB1,B2,B3コミットを、masterへ1つのコミットとして入れるときの例。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/60c86c00-f133-eece-f64c-4cac7d634318.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/2ccea768-3330-eb12-7cfa-55c9b73d727f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/bf6a5c4f-73eb-b6a1-014d-3a7a5a14a5e2.png)
不要なブランチを削除すれば、下図のようになる（New Commit comment!!!と書いてある部分にはB1,B2,B3が含まれる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067025/a006d9a5-02b0-2f10-6969-067904d9ec9a.png)