Git・GitHubはこれで完璧！（ではない。）

GitとGitHubについて勉強した内容をまとめておきます。

間違いとかあれば、どしどしコメントしてくださいませ。

##gitの概要
**・gitはバージョン管理システム。ゲームで言うところの、セーブをするツール。**
・gitはファイルを`差分`ではなく、`スナップショット`として記録している。

###簡単なgitの流れ
1.ワークツリー（ローカル）でファイルを変更
2.ステージに追加（`git add <ファイル名>`）する
3.ローカルリポジトリ（.gitディレクトリ）に変更履歴をコミット（スナップショットとして記録）する。（`git commit`）
4.GitGub上のリモートリポジトリにプッシュする。（`git push <リモート名> <ブランチ名>`）

###gitのデータの持ち方
・リポジトリに`圧縮ファイル`・`ツリー（スナップショット）`・`コミット`を持っている。
・`圧縮ファイル`は`git add`した時に保存される。
・`ツリー`はコミットした時に保存される。
・`コミット`も当然、コミットした時に保存される。

各コミットは1つ前のコミットの内容を持っている。

例えば、`コミット2`は`parentにコミット1`を持っている。

##gitのインストール確認

```
git --version
```

##gitの設定確認

```
git config --list
```

また、`homeディレクトリ`直下の`.gitconfig`にgitの設定情報が保存されている。

##gitファイルの作成
プロジェクトに作業ディレクトリを変更して、下記コマンドを実行。

```
git init
```

これで、`.gitディレクトリ`が作成され、さらにその中に、`設定ファイル（config）`などが作成される。

##gitコマンドにエイリアスをつける

```
git config --global alias.<エイリアス名（ショートカット名）> <コマンド名>
```

オプション`--global`を付ければ、プロジェクトではなく、パソコン全体の設定が変更される。

##GitHub上のプロジェクトをコピー

```
git clone [githubのURL]
```

##ワークツリーの変更をステージ（インデックス）に追加する
＊ステージまたはインデックスと呼ばれるようです。

```
git add
```

##ワークツリー（ファイル）の変更を記録する（コミット）

```
git commit

git commit -m "メッセージ内容" //メッセージをつける

git commit -v //変更内容を確認できる
```

##現在のファイルの変更状況を確認する

```
git status
```

これで、
・ワークツリーとステージの状況
・ステージとローカルリポジトリの状況
が、表示される。

##変更した差分を確認する

```
git diff //ワークツリーとステージの差分
git diff <ファイル名>

git diff --stafe //ステージとローカルリポジトリの差分
```

##変更履歴を確認する

```
git log

git log --oneline //一行で表示

git log -p index.html　//ファイルの変更差分だけを表示

git log -n <コミット数> //表示するコミット数を指定
```

##ファイルの削除を記録する

```
git rm <ファイル名> //ファイル削除
git rm -r <ディレクトリ名>　//ディレクトリを削除

git rm --cached <ファイル名> //git上からのみ削除。ワークツリーには残る。
```

##ファイルの移動/ファイル名の変更を記録

```
//ファイルの移動
git mv <ファイル名> <ディレクトリ名>
```

```
//ファイル名の変更
git mv <旧ファイル> <新ファイル> 

//上記は下記の3つのコマンドを合わせたもの。
mv <旧ファイル> <新ファイル> 
git rm <旧ファイル>
git add <新ファイル> 
```

##リモートリポジトリの追加

```
git remote add origin 追加したいリポジトリ（GitHubで作ったリモートリポジトリのURL）
```

##リモートリポジトリにプッシュする

```
git push origin master

git push <リモート名> <ブランチ名>
```

masterはデフォルトのブランチ名のこと。

##gitで管理しないファイルの設定方法

`.gitignoreファイル`に設定する。

書き方は下記の通り。
・`#`以降はコメント。
・除外するファイル名を指定
・ルートディレクトリを指定する場合は`/`を記述。（例：/index.html）
・ディレクトリ以下を除外するときは最後に`/`を記述。（例：dir/）
・ワイルドカードも使える。`/`以外を指定できる。（例：*/*.html）

##ファイルの変更を取り消す

下記コマンドを実行することで、最新のステージの内容とファイルの内容を同じにする。

```
git checkout --<ファイル名>
git checkout --<ディレクトリ名>

git checkout --. //全ての変更を取り消す
```

`--`はブランチ名とファイル名が被ってもGitが判別できるようにするためのもの。

##ステージに追加した変更を取り消す

裏側では、ローカルリポジトリの最新情報（直前のコミット）の内容でステージの内容を上書きすることで、`ステージの変更を取り消す`という処理を実現している。
**ステージへの変更を取り消しているだけなので、ワークツリーの内容は変更されない。**

```
git reset HEAD <ファイル名>
git reset HEAD <ディレクトリ名>

git reset HEAD . //全ての変更を取り消す
```

##直前のコミットを修正する

**注意：リモートリポジトリにプッシュした内容は変更してはいけない（複数人でしている場合に困る事があるから。）**

```
//git addでステージに追加してから、下記コマンドの実行で直線のコミットを編集できる
git commit --amend
```

##リモートリポジトリの確認

```
git remote //設定しているリモートリポジトリ

git remote -v //URLも表示される
```

##リモートリポジトリの複数

```
git remote add <リモート名> <リモートURL>
```
##リモートから情報を取得する（フェッチ）

リモートリポジトリからローカルリポジトリ（`remotes/リモート/ブランチ`）にファイルをコピーする。
**ワークツリーには反映されない。**

```
git fetch <リモート名>
git fetch origin
```

##リモートから情報を取得してマージする（プル）

`git pull`を使えば、リモートリポジトリの内容をローカルリポジトリに反映して、ワークツリーにも反映させる。

```
git pull <リモート名> <ブランチ名>
git pull origin master //一般的には←のコマンドになる

git pull //省略形

//上記は下記2つのコマンドと同じことをしている。
git fetch origin master
git merge origin/master
```

##fetchとpullの使い分け

基本は`fetch`を使うのがオススメ。
プルだと、今自分がいるブランチにファイルが統合される。

例えば、hogeブランチをリモートから取得して、マージしようとした時に、pullだと間違ってmasterブランチにhogeブランチの内容を統合してしまう可能性がある。

##リモートの詳細情報を表示する

```
git remote show <リモート名>
git remote show origin
```

##リモート変更・削除

```
//リモートの変更
git remote rename <旧リモート> <新リモート>

//リモートの削除
git remote rm <リモート名>
```

##ブランチとは
**ブランチは複数機能を開発するために使われるもので、複数人で開発する時に重要となってくる。**

**役割としては、コミットを指し示すポインター的なことをしてくれる。**

* * *
例えば、`コミット3`のブランチに`master`と`hoge`があり、自分は`masterブランチ`で作業している時に、新たにコミットすると`コミット4`ができて、`masterブランチはコミット4示す`ようになる。`hogeブランチ`は`コミット3`を示しているまま。この時、HEADは`masterブランチ`を示す。

次に`hogeブランチ（コミット3を示している）`で作業して、新たにコミットすると、`コミット4'`ができて、`hogeブランチはコミット4'を示す`ようになる。この時、HEADはhogeブランチを示す。

こんな感じで、ブランチごとに作業をすると、コミットを分ける事ができるので、Aさんはこっちの機能を開発、Bさんは違う機能を開発みたいなことを同時にできるようになる。

* * *

###HEADについて
HEADは今作業しているブランチを指し示すポインター。

###ブランチを利用した開発の流れ
・masterブランチはリリース専用のブランチにする
・開発する時は他のブランチを作成する

例えば、Aさんは`hoge1ブランチ`で、Bさんは`hoge2ブランチ`で開発を進める。`hoge1ブランチ`での開発が終了したら、`masterブランチ`にマージする。また新たな機能を実装する時は`masterブランチ`からブランチをきって、`hoge3ブランチ`を作成する。というような感じ。

###ブランチを追加する

```
git branch <ブランチ名>
```

###ブランチの一覧を表示する

```
git branch　

git branch -a　//リモートリポジトリも表示
```

###どのブランチがどのコミットを指しているかを確認する

```
git log --oneline --decorate
```

別に`--oneline`は一行で表示するというだけなので、なくてもOK。でもあった方がわかりやすいよ。

###ブランチを切り替える

```
git checkout <既存のブランチ名>

//ブランチを新規作成しつつ、切り替える
git checkout -b <新規作成するブランチ名> 
```

###ブランチ（名）の変更・削除

```
//ブランチ名の変更
git branch -m <ブランチ名>

//ブランチの削除
git branch -d <ブランチ名>

//強制削除
git branch -D <ブランチ名>

```

##マージ（merge）とは
マージは他の人が変更した内容を自分のワークツリーに反映させること。

###変更をマージする方法

```
git merge <ブランチ名>
git merge <リモート名/ブランチ名>
```

###マージには3種類あるよ

**・Fast Foward（早送りになるマージ）**
ブランチが枝分かれしなかった時は、ブランチのポインタが前に進むだけ、ということ。

例えば、自分はmasterブランチで作業している。自分の休憩中に誰かが、hogeブランチで作業して、コミットした。自分はhogeブランチで変更した内容をmasterブランチに取り込む。この場合、masterブランチがhogeブランチに追いついただけになるよねって話らしいです...

**・Auto Merge（基本的なマージ）**
枝分かれして開発していた場合はマージコミットという新しいファイルを作成する。

**・コンフリクト**
↓
##コンフリクトとは
コンフリクトとは同じファイルの同じ行を同時に編集した時にマージしようとすると、どっちを優先すべき？という競合が発生する事。

###コンフリクトの解消方法

コンフリクトが発生したファイルを確認して、最終的にどっちを優先したいのか手動で書き換えればOK。簡単。



###コンフリクトの確認方法
コンフリクトが発生している場合は、`git status`コマンドで確認できる。

```
git status

//実行結果
both modeified: test.php
```

###コンフリクト関連の予防策

・複数人で同じファイルを変更しないようにする
・pullやmergeする前に変更中の状態をなくしておく（commitしておく。）
・pullする時は、pullするブランチに移動してからpullするようにする。

##GitHubについて

###プルリクエストとは

プルリクエストとは自分の変更したコードをリポジトリに取り込んでもらうように申請する機能。

手順としては、
1.masterブランチを最新に更新する（`git pull origin master`）
2.ブランチを作成（`git checkout -b <ブランチ名>`）
3.ファイルを変更
4.変更をコミット（`git add & git commit`）
5.GituHubへプッシュ（`git push <リモート名> <ファイル名>`）
6.プルリクエストを送る
7.コードレビュー
8.プルリクエストをマージ
9.ブランチを削除
という手順。

##作業を一時避難する方法
【前提】
作業が途中でコミットしたくないけど、別のブランチで作業しないといけないので、作業を一時避難する。

まずはファイルを変更して、下記コマンドを実行。
すると、変更した内容がワークツリーから消えて、stash
に保存される。

```
//下記はどっちも同じ
git stash
git stash save 
```

###stash（避難した作業）の一覧を確認する

```
git stash list
```

###stash（避難した作業）の復元

```
//最新の作業を復元
git stash apply

//ステージの状況も復元する
git stash apply --index

//特定の作業を復元する
git stash apply <スタッシュ名>
```

###stash（避難した作業）を削除する

```
//最新の作業を削除する
git stash drop

//特定の作業を削除する
git stash drop <スタッシュ名>

//全作業を削除する
git stash clear
```

##タグについて
タグとはコミットを参照しやすくするためにわかりやすい名前をつけるもの。

###タグを作成する

```
//最新のコミットにタグを付ける
git tag <タグ名>

//特定のコミットにタグを付ける
git tag <タグ名> <コミット名>

//注釈版タグ
git tag -a <タグ名>

//ファイルを開かずメッセージを書く
git tag -a <タグ名> -m "<メッセージ>"
```

###タグの一覧を表示する

```
git tag
```

###タグデータの表示

```
git show <タグ名>
```

###タグをリモートリポジトリに送る

```
git push <リモート名> <タグ名>

//タグをリモートに一斉送信
git push origin --tags
```