What's "Git" ?

よく使い方を忘れるので、必要な時にサッと読み返せるように超完結にまとめておきます。

>勉強中の関連記事まとめ
>[自分用の勉強記事をまとめた目次　~擬似知識体系~](https://qiita.com/oekaki-hoho-ron/items/3194f560efc461ec03b0)

この記事はドットインストールのGit講座を参考にして、やったことを覚えるためのメモとして書いてます。知識として整理されていないので少しずつ自分なりの解釈に置き換えて記事を整理していく予定。

>参考文献
>[git入門（全22回） - ドットインストール](https://dotinstall.com/lessons/basic_git)

#Gitとは

分散型バージョン管理システム。ローカルのPCでファイルの編集作業や修正履歴を管理。ファイルの作成や修正をある程度の量をこなしたら履歴データベースに保存するためのシステム。

複数人でファイル編集する際に、修正作業が重複して上書きしてしまわないようアップロード時に警告がでたり、更新履歴を残し編集箇所の差分の確認できるようになる。

>[Git公式サイト](https://git-scm.com/)

# GitHubとは

Gitを用いたソフトウェア開発プロジェクトのための共有ウェブサービス。ソースコードの管理、レビュー、コラボレーションなどが可能。Gitはシステム、GitHubはGitを用いたサービス。

>[GitHub公式サイト](https://github.com/)

#gitのインストール

gitは公式サイトからダウンロードしたパッケージでインストールできる。Macユーザなら初期状態でインストール済みなのでこの作業は必要ない。

#作業のイメージ

gitで作業する際の3つの状態がある。

- 作業ディレクトリ
- ステージングエリア（インデックス）
- リポジトリ
    - ローカルリポジトリ
    - リモートリポジトリ

作業ディレクトリでは、ファイルの作成や修正の作業を行う。そこである程度の量の作業を進めるとき、途中経過を保存するのがステージングエリアに一時的に保存しておける。そして最終的にキリのいい意味のあるまとまりをリポジトリに保存することで、バージョンの履歴を綺麗に管理できる。

ローカルリポジトリは1人で作業する保存領域のようなもの。一方、リモートリポジトリはWEBやネットワーク上にあって、他人とファイルを共有しながら開発作業を行うための保存領域。簡単に言えば、ローカルは自分のPC、リモートはクラウド、というだけ。

#設定

###ユーザ登録
誰が管理したかわかる様にユーザ情報を登録。

```.zsh
$ git config --global user.name "Your Name"
$ git config --global user.email "your-address@gmail.com
```

###テキストカラー設定


```zsh
$ git config --global color.ui true
```

###設定リスト表示
`git config`で行ったユーザ登録やUI設定の内容を一覧する。

```zsh
$ git config -l
```

###ヘルプ

```zsh
$ git config --help

もしくは

$ git help config
```

###作業ディレクトリ作成
現在のディレクトリをgitで使うという宣言のようなもの。

```zsh
$ mkdir test
$ cd test
$ git init

> initialized empty Git repository in /Users/user_name/Desktop/test/.git/
```

###ステージングエリアに保存

```zsh
$ vim index.html    // 中身は適当にコーディング
$ git add index.html
```

```index.html
line 1
```

###リポジトリに保存
```zsh
$ git commit    // エディタが起動する
```

```vim
変更内容のメッセージを記入。例えば"initial commit"など。
:wq
```

```zsh
> [master (root-commit) c32ce90] initial commit
>  1 file changed, 1 insertion(+)
>  create mode 100644 index.html
```
###addとcommitをまとめて行う

```zsh
$ git commit -am "メッセージ"
```

###ログを確認する

```zsh
$ git log

> commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b (HEAD -> master)    // コミットID
> Author: Your Name <your-address@gmail.com>    // ユーザ情報
> Date:   Wed Nov 13 19:50:07 2019 +0900    // 更新日時
>
>     initial commit    // 修正内容のメッセージ
```

ログを一行で表示するオプション。

```zsh
$ git log --oneline

> c32ce90 (HEAD -> master) initial commit
```

変更内容の詳細を列挙するオプション。

```zsh
$ git log -p

> commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b (HEAD -> master)
> Author: Your Name <your-address@gmail.com>
> Date:   Wed Nov 13 19:50:07 2019 +0900
>
>     initial commit
>
> diff --git a/index.html b/index.html
> new file mode 100644
> index 0000000..89b24ec
> --- /dev/null              // 何もない状態から
> +++ b/index.html           // index.htmlが作成された
> @@ -0,0 +1 @@
> +line 1
```

どのファイルに変更を加えたかをコンパクトに表示するオプション。

```zsh
$ git log --stat

> commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b (HEAD -> master)
> Author: Your Name <your-address@gmail.com>
> Date:   Wed Nov 13 19:50:07 2019 +0900

>     initial commit

>  index.html | 1 +
>  1 file changed, 1 insertion(+)
```

###状況確認

どのファイルをどこ（作業ディレクトリ・ステージングエリア・リポジトリ）に保存したかを確認する。状況確認と次に取るべき行動を確認できる。

例えば`index.html`に変更を加えたとする。

```index.html
line 1
line 2
```

この状態だと`index.html`に2行目が追加されたことになるが、このことを忘れてしまったり再確認したいときがあるはず。そのときはステータスを表示してみればいい。

```zsh
$ git status

> On branch master    // マスターブランチにおいて
> Changes not staged for commit:    // ステージにもコミットにも変更なし
>   (use "git add <file>..." to update what will be committed)    // addでステージに上げるか
>   (use "git checkout -- <file>..." to discard changes in working directory)    // checkoutで破棄できるよ
> 
> 	modified:   index.html    // 変更されたファイル
> 
> no changes added to commit (use "git add" and/or "git commit -a")
```

###変更を破棄

修正内容を元に戻したい場合、ファイル名を指定して変更破棄できる。

```zsh
$ git checkout -- index.html
```

これで`index.html`の中身を確認すると、

```index.html
line 1
```

2行目が無かったことになっている。

###

`$ git log --stat`はどのファイルを変更したか。`$ git status`はどのファイルをどこに保存したか。ではどのファイルをどう変更したかを確認するにはどうするか。

```zsh
$ git diff

> diff --git a/index.html b/index.html
> index 89b24ec..7bba8c8 100644
> --- a/index.html
> +++ b/index.html
> @@ -1 +1,2 @@
>  line 1
> +line 2    // "line 2"という文字列が+されたという意味
```

ただし`$ git diff`はまだステージングエリアに上げていないファイルの変更点しか確認できない。一旦ステージングエリアに上げるために`$ git add`した後で`$ git status`をしてみると、

```zsh
$ git add index.html
$ git status

> On branch master    // マスターブランチにおいて
> Changes to be committed:    // コミットされる変更点
>   (use "git reset HEAD <file>..." to unstage)
> 
> 	modified:   index.html    // 変更されたファイル
```

ここで`$ git diff`をしても、すでに変更ファイルはステージングエリアに上げているので何も表示されない。

```zsh
$ git diff

>
```

そこに`--cached`のオプションをつけると、さっきの`$ git diff`で見たステージングエリアに上げる前の変更内容と同じ物が表示される。

```zsh
$ git diff --cached

> diff --git a/index.html b/index.html
> index 89b24ec..7bba8c8 100644
> --- a/index.html
> +++ b/index.html
> @@ -1 +1,2 @@
>  line 1
> +line 2
```

これでステージングエリアに上がっているけどまだコミットされていないファイルの変更点が確認できる。これは次のコミットでどのファイルがどう変更されるかの最終確認として使える。

###まとめてステージングエリアに上げる

1つのファイルなら`$ git add index.html`とファイル名を入力すればステージングエリアに上げられたが、ファイルが複数になると全てのファイル名をタイプするのは時間の無駄。そういうときは現在の作業ディレクトリ以下のディレクトリのファイル全てを`add`することができる`.`を使う。

```zsh
$ git add .
```

###addやcommitした後のファイル削除と移動

一旦ステージングエリアに上げたりコミットしたファイルを削除や移動する時、Linuxコマンドの`rm`や`mv`を使ってしまうとgitがファイルを見失ってしまうため、必ずgitコマンドとして実行する。

```zsh
$ git rm ファイル名
$ git mv ファイル名
```

###特定のファイルをアップロードしない設定

`.gitibnore`という設定ファイルを作成しておくことで、ステージングエリアやリポジトリに上げたくないファイルを除外することができる。バージョン管理の必要性、重いファイルのアップロード時間、共有したくないファイル、などを予め除外するのに活用できる。`.gitignore`を配置したディレクトリ以下のファイルに対して適用される。

例えば`index.html`はアップロードしたいけど`error.log`はバージョン管理する必要性が低いため除外するとする。

まずは`.gitignore`を作成して、`.gitignore`の内容には拡張子に`.log`の付くファイルを除外するという記述をする。

```zsh
vim .gitignore
```

```..gitignore
*.log
```

`.gitignore`は隠しファイルなので、ファイル一覧する際は`-a`オプションを付けることで作成されているかを確認。

```zsh
$ ls -a

> ./    ../    .git/    .gitignore
> error.log    index.html
```

ステータスを見てみると、`error.log`は未登録のファイル一覧にも表示されていないことがわかる。

```zsh
$ git status

> On branch master
> Changes to be committed:    // コミットで変更されるファイル
>   (use "git reset HEAD <file>..." to unstage)
> 
> 	modified:   index.html
> 
> Untracked files:    // 未登録のファイル
>   (use "git add <file>..." to include in what will be committed)
> 
> 	.gitignore
```

全てのファイルをステージングエリアに上げても、`error.log`は除外されたままになっている。

```zsh
$ git add .
$ git status

> On branch master
> Changes to be committed:
>   (use "git reset HEAD <file>..." to unstage)
> 
> 	new file:   .gitignore
> 	modified:   index.html
```

###最小限の手間でコミット

```zsh
$ vim index.html    // エディタを起動して変更を加える
$ git add .
$ git commit -m "変更内容を説明するメッセージ"
```

```zsh
$ git commit -m "2行目を追加"

> [master 642d91c] 2行目を追加
>  2 files changed, 2 insertions(+)    // 2つのファイルが変更された
>  create mode 100644 .gitignore    // 新規追加されたファイル
```

```zsh
$ git log

> commit 642d91cbbf1240a4d1de574048cd53b8012c8445 (HEAD -> master)
> Author: Your Name <your-address@gmail.com>
> Date:   Thu Nov 14 19:13:06 2019 +0900
> 
>     2行目を追加    // 変更内容を説明するメッセージ
> 
> commit  c32ce90c7677c2b97192e9585f2c5a1ebe4c355b
> Author: Your Name <your-address@gmail.com>
> Date:   Wed Nov 13 19:50:07 2019 +0900
> 
>     initial commit    // 前回のコミットの内容
```

###直前のコミット内容に変更を加える

ファイルに変更を加えてコミットしたが、ちょっとしたミスがあって再度ファイルに変更を加えたとする。大した変更ではないのでコミットメッセージも同じにしたいが、この変更のために`add`して`commit`するとほぼ同じ内容のログが残ってしまって煩わしくなる。

そこで直前のコミットの内容に変更を加えるという形でファイルを変更することで、このちょっとした変更を直前のコミットに含めることができる。

```zsh
$ vim index.html    // ちょっとした変更を加える
$ git add .
$ git commit --amend    // ちょっとした変更を直前のコミットに上書き
```

これにより、コミットが乱立せず、それぞれのコミットを意味のあるまとまりとして管理することができる。ちなみにコミットメッセージを変えたいときは`-m`を追加するだけ。

```zsh
$ git commit --amend -m "メッセージを変更"
```


###過去バージョンのコミットに戻る

`$ git reset`はHEADの位置を変更するコマンド。コミットした内容を取り消すためのコマンド。個人作業ではなく複数人でやってる場合、コミット段階ではまだリモートリポジトリにアップロードされていないため、コミットのバージョンを後戻りできることはファイル共有前に間違い修正するために必要なコマンド。

オプションによってインデックスやワーキングツリーの内容も変更できる。



```zsh
$ git log
commit 642d91cbbf1240a4d1de574048cd53b8012c8445 (HEAD -> master)
Author: Your Name <your-name@gmail.com>
Date:   Thu Nov 14 19:13:06 2019 +0900

    2行目を追加

commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b
Author: Your Name <your-name@gmail.com>
Date:   Wed Nov 13 19:50:07 2019 +0900

    initial commit
```

```zsh
$ git reset 何を戻すか どこまで戻すか
```

###ヴァージョンの概念

|対象|内容|
|---|---|
|HEAD|現在の最新コミットの状態|
|インデックス|addした時点でのファイルの状態|
|ワーキングツリー|現在のファイルの状態|



ワーキングツリーとはローカルで編集しているファイル群のこと。そこでいろいろと編集作業をしたものを段階的にアップロードしていくのがGitのシステム。ワーキングツリーに編集を加えたものが編集作業の最新地点。それをアップロードするための準備としてステージングエリア（インデックス）に登録する。その後でワーキングツリーのファイルを編集するとインデックスのファイルと違いが出るので、ワーキングツリーは「現在」のファイルの状態、インデックスは「addした時点」のファイルの状態という扱い。それと同じ様にHEADはステージングエリアからローカルリポジトリに上げるためにコミットした時点でのファイルの状態を指す。



###ブランチ

ブランチとは、根幹のプロジェクト（Masterブランチ）から分岐させて、本体に影響を与えず開発を行えるよう一旦バージョンを切り離す機能のこと。もし分岐したブランチで取り返しのつかない不具合が生じても切り離せばMasterブランチは無傷で残せる。

gitの段階わけについて再確認しておくと、ワーキングツリーとは手元にある作業ディレクトリにあるファイル群の状態のこと、インデックスとはステージングエリアに上げたコミット予備軍、そしてリポジトリにコミットしたものがバージョンアップ予定の内容。つまり、手元のファイルと、アップロード（commit）したファイルと、その中間（add）という状態があるということ。そして中間のaddとはあってもなくてもあまり関係のないものだが、ファイルごと編集を加えたいときにピンポイントファイル名を指定するために必要というもの。なぜならコミットとは意味のあるまとまりで管理するもので、しかも常にワーキングツリー全体をaddするとは限らず、ファイルごとに編集内容を分岐させるにはaddでファイル名を指定する。

HEADとは、特定のコミットを指す代名詞のこと。`HEAD`は最新のコミットIDと同義、`HEAD^`は2番目に新しいコミットIDと同義。要は、普通ならコミットの取り消しという作業は「最新か一つ前か」について考えるもので、それらのIDをいちいち調べなくても取り扱える様に代名詞としてHEADとHEAD^が使われているということ。なんならコミットIDさえ分かれば直接指定することができるので、HEADを使わずにコミットの取り消し作業を行うこともできるということ。

###具体的なコマンドの例

直前（最新）のコミットを取り消すという意味のコマンドはこうなる。

```zsh
$ git reset HEAD^
```

意訳すると「さっきコミットした段階での登録内容を、一つ前のコミットの状態に戻す」ということで、この際に「手元にあるファイルの状態はそのまま」維持される。つまり最新のコミットをする直前の状態まで戻すということ。

そして何をどこまで戻すかを指定するオプションコマンドを使うこともできる。

|どこまで戻すか|意味|
|---|---|
|HEAD|最新コミット|
|HEAD^|2番目に新しいコミット|
|コミットID（最低7桁以上）|任意のコミット|

コミットIDというのは`$ git log`した時に表示される`commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b`などのこと。

|何を戻すか|内容|意訳|
|---|---|---|
|--hard|HEADの位置、インデックス、ワーキングツリーの全てを変更する。|コミットについてのファイル編集する前段階まで戻す。|
|--mixed|HEADの位置、インデックスを変更。ワーキングツリーに影響しない。オプションが空白の場合は`--mixed`扱いとなる。|コミットする前段階まで戻す。|
|--soft|HEADの位置のみを変更。インデックスとワーキングツリーに影響しない。|addする前段階まで戻す。しかし、すでにaddされている時点で結局はコミットされてしまうため、意味合いとしては指定したコミットをなかったことにしているだけ。この処理は`$ git commit -amend`でできなかったメッセージ変更までやり直せるだけの処理と思えばいい。|
|master|masterブランチからファイルを引っ張ってきたときの状態まで戻す。|今日の作業は無かったことに。|

resetについてはパターンが限られているので別の記事で一通り検証してまとめた方が良さそう。

###ブランチについて

ブランチはさきほど説明した通り。現在作成されているブランチの一覧を確認するコマンドは下記。

```zsh
$ git branch

> * master
```

masterブランチから分岐させて新しい機能を開発したいときは、新規のブランチを作成する。

```zsh
$ git branch ブランチ名
$ git branch

> * master
>   test
```

このとき`*`がついている方が現在いるブランチとなる。ブランチを移動するコマンドは、

```zsh
$ git checkout test
> Switched to branch 'test'

$ git branch
>   master
> * test
```

新規ブランチの作成と、そのブランチへのチェックアウトを一括でやるには`checkout`コマンドに`-b`オプションをつければいい。このbはおそらくbranchコマンドの頭文字のb。

```zsh
$ git checkout -b test
> Switched to a new branch 'test'

$ git branch
>   master
> * test
```

このtestブランチのワーキングツリーに変更を加えたものをコミットした状況について見てみる。`script.js`を作成し、`add`して`commit`してログを表示してみる。

```zsh
$ vim script.js    // 内容は適当に記述
$ git add .
$ git commit -m "スクリプト追加"
> [test b511bbb] スクリプト追加
>  2 files changed, 1 insertion(+)
>  create mode 100644 .DS_Store
>  create mode 100644 script.js

$ git log
> commit b511bbb5373278a8425727cbab96bb2e22101c8e (HEAD -> test)
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 17:28:59 2019 +0900
> 
>     スクリプト追加
> 
> commit 642d91cbbf1240a4d1de574048cd53b8012c8445 (master)
> Author: Your Name <your-address@gmail.com>
> Date:   Thu Nov 14 19:13:06 2019 +0900
> 
>     2行目を追加
> 
> commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b
> Author: Your Name <your-address@gmail.com>
> Date:   Wed Nov 13 19:50:07 2019 +0900
> 
>     initial commit
```

スクリプト追加したコミットまで一覧された。ここでtestブランチからmasterブランチに移動してからログを表示すると下のようになる。

```zsh
$ git checkout master
> Switched to branch 'master'

$ git log
> commit 642d91cbbf1240a4d1de574048cd53b8012c8445 (HEAD -> master)
> Author: Your Name <your-address@gmail.com>
> Date:   Thu Nov 14 19:13:06 2019 +0900
> 
>     2行目を追加
> 
> commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b
> Author: Your Name <your-address@gmail.com>
> Date:   Wed Nov 13 19:50:07 2019 +0900
> 
>     initial commit
```

testブランチでスクリプトを追加した作業は、masterブランチでは除外されている。こうしてtestブランチとmasterブランチで異なる機能の開発を進めることで、根幹のプロジェクトへの影響を心配せずに安全に開発できる。分岐したブランチは後でmasterブランチに統合するかどうかを考えればいい。

###ブランチを統合する

分岐させたブランチの開発がいい感じなので、masterブランチに統合しても問題なさそうだと判断できたら、分岐させたブランチをmasterブランチにマージすることができる。

ではmasterブランチに移動して、testブランチでの変更をマージした状態でログを見てみる。

```zsh
$ git checkout master    // 母体となるブランチに移動
> Already on 'master'

$ git merge test    // 飲み込まれる側のブランチ名を指定
> Updating 642d91c..b511bbb
> Fast-forward
>  .DS_Store | Bin 0 -> 6148 bytes
>  script.js |   1 +
>  2 files changed, 1 insertion(+)
>  create mode 100644 .DS_Store
>  create mode 100644 script.js

$ git log
> commit b511bbb5373278a8425727cbab96bb2e22101c8e (HEAD -> master, test)
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 17:28:59 2019 +0900
> 
>     スクリプト追加
> 
> commit 642d91cbbf1240a4d1de574048cd53b8012c8445
> Author: Your Name <your-address@gmail.com>
> Date:   Thu Nov 14 19:13:06 2019 +0900
> 
>     2行目を追加
> 
> commit c32ce90c7677c2b97192e9585f2c5a1ebe4c355b
> Author: Your Name <your-address@gmail.com>
> Date:   Wed Nov 13 19:50:07 2019 +0900
> 
>     initial commit
```

masterブランチのログに全てのコミット履歴が取り込まれているのがわかる。

###ブランチの削除

マージされたブランチの変更は取り込んだので不要になる。`branch`コマンドには不要になったブランチを削除するオプションがある。

```zsh
$ git branch -d test
> Deleted branch test (was b511bbb).

$ git branch
> * master
```

このようにbranchコマンドに`-d`オプションをつけるとtestブランチが削除されてmasterブランチのみになっているのがわかる。

###複数ブランチで編集が重複してコンフリクトが起きた場合

gitでバージョン管理をする過程でコミットの履歴が残るから安全というのはわかるけど、同じファイルに異なる編集を加えたコミットはどっちが優先されるのかという疑問があるはず。結論から言うとどちらが優先されるかと言うと当然古い方のファイルで、編集の重複が起きている間はコミットできないというシステムになっている。この重複のことをコンフリクトといい、これを解消することでコミットできるようになる。

まず最初のコミットだけがされた状態を想定する。

```zsh
$ git log
> commit 2c7d2fe3b0c0211e530b2a376ac8c24c86eacc55 (HEAD -> master)
> Author: Your Name <your-address@gmail.com>
> Date:   Wed Nov 13 19:50:07 2019 +0900
> 
>     initial commit
```

勉強のためにコンフリクトを生じさせるために、新規ブランチを作成して編集をあえて重複させてみる。まずはtestブランチで`index.html`を変更する。

```zsh
git checkout -b test
> Switched to a new branch 'test'

$ vim index.html    // "line 1"を"line 1st"に変えてみる
$ git add .
$ git commit -m "line1からline1stに変更"
> [test 6fe95b7] line1をline1stに変更
>  1 file changed, 1 insertion(+), 1 deletions(-)
```

次にmasterブランチでも`index.html`を変更する。

```zsh
git checkout master
> Switched to a new branch 'master'

$ vim index.html    // "line 1"を"line first"に変えてみる
$ git add .
$ git commit -m "line1からline firstに変更"
> [master f67bbbf] line1をline firstに変更
>  1 file changed, 1 insertion(+), 1 deletion(-)
```

ではtestブランチをmasterブランチに取り込んでみるとどうなるか。

```zsh
$ git branch
> * master
>   test

$ git merge test
> Auto-merging index.html
> CONFLICT (content): Merge conflict in index.html
> Automatic merge failed; fix conflicts and then commit the result.
```

コンフリクトが起きたと言われてコミットに失敗する。ここでステータスを確認してみると、競合していることを指摘されている。

```zsh
$ git status
> On branch master
> You have unmerged paths.
>   (fix conflicts and run "git commit")    // 「競合を解消してcommitしてください」とのこと
>   (use "git merge --abort" to abort the merge)
> 
> Unmerged paths:
>   (use "git add <file>..." to mark resolution)
> 
> 	both modified:   index.html
> 
> no changes added to commit (use "git add" and/or "git commit -a")
```

では競合しているファイルの編集をしようとすると何か書かれている。

```zsh
$ vim index.html
```

```index.html
<<<<<<< HEAD
line first
=======
line 1st
>>>>>>> test
```

この状態で`index.html`を開くと勝手に加筆されている。masterブランチのHEADすなわち最新のコミットでは`line first`だったのにも関わらず、testブランチの方では`line 1st`になっているで、どちらか選ぶか、正しい形に書き直すように、という意味。今回はmasterブランチの内容を採用することにするので、`line first`以外の部分を削除して保存する。

```zsh
$ git add .

$ git commit -m "コンフリクトの解消"
> [master b5265bd] コンフリクトの解消

$ git log
> commit b5265bd71579e79f7a3c9415a9faee508355679d (HEAD -> master)
> Merge: d783f53 5ca42ae
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 19:21:18 2019 +0900
> 
>     コンフリクトの解消
> 
> commit d783f53f9269d8c59bfd2a3ca7366e59c9921433
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 18:41:39 2019 +0900
> 
>     line1をline firstに変更
> 
> commit 5ca42ae6fe0b961bc6de44b340c39f5783b51225 (test)
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 18:40:44 2019 +0900
> 
>     line1をline1stに変更
> 
> commit 3b730affbaa220f918800509a82c6d4c55f4f9d4
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 18:39:46 2019 +0900
> 
>     initial commit

$ git status
> On branch master
> nothing to commit, working tree clean
```

ステータスを見てもまだコミットしてない編集は存在しないとなっているので、これで解決。

###タグの追加

コミットのログにはそれぞれIDが割り当てられているが、さまざまな操作をするのにいちいちIDをコピペするのは面倒だし、IDを見ても何の変更をしたときのものなのか判断できない。そこでコミットIDごとにタグをつけて名前を与えることで管理しやすくすることができる。

直前のコミットにタグ付するのは単に`tag`コマンドにタグ名を書いて実行すればいい

```zsh
$ git tag ver1.0
```

`tag`コマンド単体で実行すると、現在作成されているタグ名が列挙される。

```zsh
$ git tag
> ver1.0
```

`show`コマンドでタグ名をしていするとコミットの内容を確認できる。内容の表示は`log`の表示と同じ。

```zsh
$ git show ver1.0
> commit b5265bd71579e79f7a3c9415a9faee508355679d (HEAD -> master, tag: ver1.0)
> Merge: d783f53 5ca42ae
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 19:21:18 2019 +0900
> 
>     コンフリクトの解消
```

直前のコミットID以外にタグを付けたいときは、タグ名の後にコミットID（最低7桁以上）を記述してやる。

```zsh
$ git tag ver0.9 d783f53f9269d8c59bfd2    // タグ名とコミットIDを指定

$ git tag
> ver0.9
> ver1.0
```

タグを削除するときは`tag`コマンドに`-d`オプションをつけてタグ名を指定する。

```zsh
$ git tag -d ver0.9
> Deleted tag 'ver0.9' (was d783f53)

$ git tag
> ver1.0
```

###コマンド省略のエイリアスの設定

gitコマンドの表記を省略する設定は、最初の方でユーザ登録などを行った`config`コマンドでできる。それに続けて`ailas.~`と続けることで省略形の設定ができる。

```zsh
$ git config --global ailas.co checkout    // checkoutをcoに省略
$ git config --global ailas.st status    // statusをstに省略
$ git config --global ailas.br brunch    // brunchをbrに省略
$ git config --global ailas.ci commit    // commitをciに省略
```

configファイルの内容確認は`-l`オプション。

```zsh
$ git config -l

> credential.helper=osxkeychain
> user.name=Your Name
> user.email=tour-name@gmail.com
> color.ui=true
> ailas.co=checkout
> ailas.st=status
> ailas.br=brunch
> ailas.ci=commit
> core.repositoryformatversion=0
> core.filemode=true
> core.bare=false
> core.logallrefupdates=true
> core.ignorecase=true
> core.precomposeunicode=true
```

#共同作業環境の構築

###共有リポジトリの登録

`init`コマンドに`--bare`オプション。

```zsh
$ git mkdir test.git    // 共有リポジトリ作成
$ cd text.git

$ git init --bare    // 共有リポジトリとして初期設定する
> Initialized empty Git repository in /Users/user-name/Desktop/test.git/
```

###リモートリポジトリの登録

とりあえずまずは開発者Aのローカルリポジトリを構築していく。

```zsh
$ mkdir test1
$ cd test1
$ git init
$ vim index.html    // line 1と記述
$ git add .
$ git commit -m "initial commit"

$ git status
> On branch master
> nothing to commit, working tree clean

$ git log
> commit 7b1644654a1a7f75170cb97af3a40ded49b30e34 (HEAD -> master)
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 21:04:26 2019 +0900
> 
>     initial commit
```

開発者Aのtest1の立場から共有リポジトリをリモートリポジトリとして登録する。別のリポジトリを登録するには`remote`コマンドを使う。`add`オプションは登録するという意味。`origin`はリモートリポジトリ名の指定。`~/test.git`は共有リポジトリのパス。

```zsh
$ git remote add origin ~/test.git

$ git config -l    // 設定情報を見ると登録されたことが確認できる
> credential.helper=osxkeychain
> user.name=Your Name
> user.email=your-address@gmail.com
> color.ui=true
> ailas.co=checkout
> ailas.st=status
> ailas.br=brunch
> ailas.ci=commit
> core.repositoryformatversion=0
> core.filemode=true
> core.bare=false
> core.logallrefupdates=true
> core.ignorecase=true
> core.precomposeunicode=true
> remote.origin.url=/Users/user-name/desktop/test.git    // 共有リポジトリのパス
> remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*    // なんかの情報
```

###リモートリポジトリの削除

リモートリポジトリの登録を解除するには`rm`オプションをつける。

```zsh
$ git remote rm origin
```

###共有リポジトリにアップロード

開発者Aがtest1リポジトリで編集を加える。`push`コマンドでtest1リポジトリのファイルを共有リポジトリに押し込む的な意味。

```zsh
$ git push origin master
> Enumerating objects: 3, done.
> Counting objects: 100% (3/3), done.
> Writing objects: 100% (3/3), 225 bytes | 225.00 KiB/s, done.
> Total 3 (delta 0), reused 0 (delta 0)
> To /Users/user-name/desktop/test.git
>  * [new branch]      master -> master
```

###共有リポジトリをダウンロード

開発者Aが共有リポジトリアップロードしたファイルを、開発者Bがtest2リポジトリにダウンロード。つまり共有リポジトリの内容を`clone`コマンドで複製するということ。

```zsh
$ cd ../
$ pwd
> /Users/user-name/desktop    // 現在のディレクトリを確認しただけ

$ git clone ~/desktop/test.git test2
> Cloning into 'test2'...
> done.

$ ls
> test.git/    test1/    test2/

$ git log
> commit 7b1644654a1a7f75170cb97af3a40ded49b30e34 (HEAD -> master, origin/master, origin/HEAD)
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 21:04:26 2019 +0900
> 
>     initial commit
```

###複数人でバージョン共有する方法

開発者AとBが共有リポジトリのファイルを共同編集するというシチュエーション。

- 共有リポジトリ
- test1（開発者Aのローカルリポジトリ）
- test2（開発者Bのローカルリポジトリ）

開発者Bがtest2で編集したものを共有リポジトリにアップロードする。

```zsh
$ vim index.html    // "line 2"を追加
$ git add .

$ git commit -m "line2を追加"
> [master c81cb31] line2を追加
>  1 file changed, 2 insertions(+), 1 deletion(-)

$ git push origin master
> Enumerating objects: 5, done.
> Counting objects: 100% (5/5), done.
> Writing objects: 100% (3/3), 267 bytes | 267.00 KiB/s, done.
> Total 3 (delta 0), reused 0 (delta 0)
> To /Users/user-name/desktop/test.git
>    da8d003..72e9a34  master -> master

$ git log
> commit 72e9a34610cb2c5cb4169d159212cb203274cebc (HEAD -> master, origin/master)
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 22:32:44 2019 +0900
> 
>     line2を追加
> 
> commit da8d003eae1630e94eec37ae5eef45fc09fa903e
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 22:28:35 2019 +0900
> 
>     initial commit
```

開発者Aが開発者Bの編集したファイルをtest1にダウンロード。

```zsh
$ cd ../test1

$ git pull origin master
> remote: Enumerating objects: 5, done.
> remote: Counting objects: 100% (5/5), done.
> remote: Total 3 (delta 0), reused 0 (delta 0)
> Unpacking objects: 100% (3/3), done.
> From /Users/user-name/desktop/test
>  * branch            master     -> FETCH_HEAD
>    da8d003..72e9a34  master     -> origin/master
> Updating da8d003..72e9a34
> Fast-forward
>  index.html | 1 +
>  1 file changed, 1 insertion(+)

$ git log
> commit 72e9a34610cb2c5cb4169d159212cb203274cebc (HEAD -> master, origin/master)
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 22:32:44 2019 +0900
> 
>     line2を追加
> 
> commit da8d003eae1630e94eec37ae5eef45fc09fa903e
> Author: Your Name <your-address@gmail.com>
> Date:   Fri Nov 15 22:28:35 2019 +0900
> 
>     initial commit
```

開発者Bと同じログが記録されていることがわかる。

###clone・push・pullでコンフリクトが起きた場合

`merge`のときと同じ様に編集箇所が重複したらコンフリクトが起きる。そのときはgitがちゃんと教えてくれるのでvimで同じ様に編集するだけ。

```zsh

```

#SSH接続

>参考文献
>[お前らのSSH Keysの作り方は間違っている](https://qiita.com/suthio/items/2760e4cff0e185fe2db9)
>[GitHubにssh接続できるようにする](https://qiita.com/0ta2/items/25c27d447378b13a1ac3)