Gitを触り始めてからGitHubにpushするまでの流れを誰よりも丁寧に説明する

[前回](https://qiita.com/gakisan8273/items/d2d52a12ad553a82b94b)は、そもそもGitでバージョン管理するメリットはなんなのかを説明しました。

おさらいはこちらから。
[なぜ僕らはGitでバージョン管理をするのか](https://qiita.com/gakisan8273/items/d2d52a12ad553a82b94b)

メリットはこうでしたね？

- **セーブ機能「コミット」により過去の状態に戻れる**
- **他人にコードの意図を伝えやすくする**

なんとなーく理解できたのではないでしょうか。


じゃあ**早速Gitを触ってみよう！**
…と思ったはいいが、**どうすればいいかわからない！！！**

そもそも**ターミナルの使い方**よくわからないし？
**コマンド**って何？

なんか**GitHub**ってのも使うみたいじゃん！

初学者というのは、**熟練者が当たり前と思っているところに疑問を持つ**ものです。
この記事ではそれらを丁寧に潰していきます。

**チュートリアルっぽくなってるので、是非手を動かしながら理解していってください。**

忙しい人は、[こちらに要点をまとめておきました](#まとめましょう)のでどうぞ。

## 前提
- Macユーザーが対象です（Windowの人は多少読み替えてください）
- Gitがインストールされているものとします（Macなら既にインストールされています）
- GitHubアカウントを持っているものとします（ググって説明記事をなぞれば大丈夫です）
- GitとGitHubを連携して使います（GitHubの説明はあとで）

## この記事のゴール
- **Git**と**GitHub**を扱うための**ターミナル操作**ができるようになる
- **コミット**できるようになる
- GitHubと自分のコードとを**同期する**ことができる
- 上記までの**コマンドの意味を理解**できる

たったここまでに達するにも、様々な記事では**省略されている分かりにくい箇所がいくつもあります**。
それらを**丁寧に説明していきます**ので、ゆっくりと進んでいきましょう！！！！

## 超ざっくりターミナルの使い方
Qiitaやブログなどでこんな表記を見たことがあると思います。

```:Qiitaでよくある表記
$ git commit -m 'first commit' 
先頭の$ってなに！？
```
いきなり出てくる`$`って何者！？


先頭の`$`は、**ターミナルでこのコマンドを打つよ！**という意味です。
**`$`は実際にターミナルに打ちません**！ややこしいですね。


```:実際にターミナルに打つべきコマンド
git commit -m 'first commit'
$ はつけないよ！！
```
`$`がついていたら、ターミナルで打つコマンドなんだなーと覚えておいてください。

さて、ターミナルで`pwd`と打って実行してみてください。
現在ターミナルが指しているフォルダ（カレントフォルダ）が表示されます。

```:現在のフォルダを出力する
$ pwd
```
どこのフォルダでコマンドを実行するか、がとても重要です。
後述しますが、`git`コマンドを実行するには`.git`があるフォルダにいる必要があります。

カレントフォルダを変えるには、`cd フォルダの場所`を実行します。

```:カレントフォルダを変更する
$ cd フォルダの場所
```
フォルダの場所（パス）の指定方法はググってください！！！
[このへん](https://qiita.com/ryouzi/items/f9dee1540a04a0bfb9a3)がとても参考になります。


## コマンドとは
先ほどから**コマンド**という言葉が出てきています。
コマンドとはその名の通り、**命令を出して何らかの処理をする**ものです。

### コマンドの指定方法
#### 1単語
`ls`や`pwd`のように1単語で指定できるものがあります。
OSの基本的な操作が多いですね。

#### 複数の単語
`git commit`のように、**複数の単語を繋いで使うこと**もあります。
この場合、`ツール名` `コマンド名`という関係になっています。
つまり、`git`というツールの`commit`というコマンドを実行する、ということですね。

#### オプション
 `-a` のように `-（英字）` を付与することで、コマンドにオプションを指定することができます。
具体例で言うと…

```:オプションなし
$ ls
カレントフォルダにあるファイルとフォルダを一覧表示する
```

```:オプションあり
ls -a
カレントフォルダにあるファイルとフォルダを一覧表示する（隠しファイルも表示する）
```
こんな感じに使います。

#### 引数
プログラミングの引数と同じように、コマンドにも引数があります。
先ほどの例`git commit -m 'first commit'`で言うと、`'first commit'`が引数ですね。

```:
$ git commit -m 'first commit'
ツール名 コマンド名 オプション 引数

```

さて、そろそろGitの使い方に入っていきたいのですが、
その前に**GitとGitHubの違い**について軽く説明をしておきます。

## GitとGitHubとの違い
### Git
前回の記事で説明した通りの**バージョン管理ツール**です。**便利**。
**ローカル（各自のPC）**でバージョンを管理するもの。

### GitHub
**Gitをみんなで共有するため**のツール。**便利**。
各自がローカルで管理しているGitをオンラインで結びつける（hub）役割をする。
**リモート（GitHubのサーバー）**でバージョンを管理する。

各自が**ローカルで行った変更をGitHubに反映する**ことで、**開発チーム全員が同じコードを共有できる**ようになります。
その他、デプロイ（本番サーバにソースコードを反映すること）をGitHubと連携して出来たりなんだり、素敵なメリットがいっぱいあります。
**とりあえずGitとセットで使っておこう！！**


## リポジトリとは

### リポジトリ
ソースコードが入っていて**Gitで管理しているフォルダ**のことです。
なぜかかっこよくこう呼びます。こわがらないで。

### リモートリポジトリ
**GitHub上のリポジトリを、リモートリポジトリ**と呼びます。
リモート（remote: 遠くの、遠隔の）なので、**オンラインのリポジトリ**という意味ですね。
**リモートリポジトリを複数人で共有する**ことで、全員が同じバージョンのコードを扱えます。

### ローカルリポジトリ
反対に**自分のPC上のリポジトリを、ローカルリポジトリ**と呼びます。
ローカル（local: 地元の、現地の）なので、自分個人のリポジトリという意味ですね。
基本的にコミットなどの**Gitコマンドは、カレントフォルダをこのローカルリポジトリに設定しないと実行できません**。


## Gitを始めよう！！！
よーーーーやく、Gitを触っていきます！！！！


### ローカルリポジトリを作成しよう
**ローカルリポジトリ**とは、自分の**PC上の（ローカル）ソースコードが入っているフォルダ（リポジトリ）**でしたね。
みなさん、ある一つのシステムごとにソースコードをフォルダ分けしているかと思います。
それらをリポジトリにしていきましょう。

**え？もうフォルダでまとめているからリポジトリじゃないの？**

そう思いますよね。でも違うんです。
**Git管理をしてはじめてリポジトリとなります。**
このフォルダを**Gitで管理しろ！という命令**をGitに出さなければなりません。
そう、**コマンド**を使います。

まずはターミナルでのカレントフォルダをソースコードが入っているフォルダに移動してください。

```:カレントフォルダの移動
$ cd ソースコードが入っているフォルダのパス
```

次にカレントフォルダをGit管理する命令を出します。
**初めてのGitコマンド！**やったね！

```:ローカルリポジトリ作成
$ git init
```
`git`ツールの`init (initialize: 初期化する)`コマンドを使いました！！！！
**このフォルダはGit管理され、ローカルリポジトリとなる**ことができました。

このコマンドで何が起こったのでしょうか？
`ls`コマンドを使ってリポジトリの中身を見てみましょう。

```:ls…カレントフォルダの中身をリストで表示する
$ ls

（ファイル名がずらーっと並ぶ）
```
何も変わったことは無いように見えます。
それでは`ls -a`と、 `-a` オプションをつけてもう一度。
このオプションをつけると隠しファイルも表示します。

```:-aオプションをつけると隠しファイルも表示する
$ ls -a

.git (ファイル名がずらーっと並ぶ)
```

`.git`というファイルが表示されたと思います。
**`.git`があるフォルダをGitは管理します。**これで**フォルダがリポジトリとなることができた**のです。
つまり、**`git init` とは`.git`を生成するコマンド**ということです！！

**ローカルリポジトリとなったので、他のGitコマンドを使える**ようになりました！
早速バージョン管理していきましょう！

## コミットしてみよう
今は、Git管理はしているけども**まだ何もコミット（セーブ）していない**状態です。
いよいよコミットするときがきました！！**`git commit`**！！！！！

```
$ git commit

（色々表示される）
nothing added to commit but untracked files present
```

なんか表示されましたね。これ、**コミットできていません**。
`nothing added to commit but untracked files present`
`何もコミットするために追加されてないよ。でも未追跡ファイルがあるよ。`

なんのこっちゃ…と思いますが、実はコミットする前に**「何をコミットするのか」を指定する**必要があります。
そのコマンドがこちら、**`git add`** ちゃんです。

### 何をコミットするのか決めよう
以下のように、`git add`**で何をコミットするのかを指定**します。
その後に`git commit`でコミットします。

```
$ git add コミットしたいファイル名
```

ファイル名を全て指定するのは面倒なので、**全てをコミットするファイルと指定する場合は`git add .`**と書けます。
今回は全てをコミットしたいので、このコマンドを打ってみてください。

```
$ git add .
```
そして、`git status`を実行してください。

```
$ git status

On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
     new file:   (ファイル名)
     new file:   (ファイル名)
     ...
```
色々とファイル名が表示されましたね？
これらのファイルをコミットする準備ができた、ということです。
`git status`は何を`git add`したかを確認するコマンドです。**必ずしも実行する必要はない**です。

ちなみに、`git add`でコミットの準備をすることを「ステージング」と呼びます。


#### 実際にコミットしてみよう
待ちに待った**`git commit`**！！！！！！

```
$ git commit
```
なんか妙な画面が出てきたと思います。こんなの。

```:コミットメッセージ入力画面
（ここにコミットメッセージを入力します）
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
#       new file:   ~~~~
#
```
これは**コミットメッセージをする画面**です。
ターミナル上で、**vi**または**vim**というエディタが起動しています。
ここでコミットメッセージを入力し、エディタのコマンドで保存すると、コミットが完了します。
わかりにくいですね。

とりあえずやってみましょう。手順はこんな感じです。
（vi、vim以外のエディタの方は何とかしてください）

1. キーボードのiを押して入力モードに変更
2. first commit と入力（これがコミットメッセージになります）
3. キーボードのescを押してコマンドモードに変更
4. `:wq` と入力してエンターキー（保存して閉じるコマンドです）

vimの操作の詳細に関しては[このへん](https://qiita.com/one-a/items/a4e1d5a736d8408fd089)を参照ください。

実際の画面はこんな感じ。この画面でエンターを押すと保存され閉じられます。
<img width="548" alt="スクリーンショット 2020-06-26 8.48.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455830/33333c9e-23e1-cd40-cf7f-bc68e3789247.png">

はいこれで**ようやくコミットが完了**しました！！おめでとうございます！！
あとは編集したら都度`git add` `git commit`をしていきます。

ちなみに…`git commit -m コミットメッセージ`とすれば、エディタを開くことなくコミットメッセージを書くことができます。お好きな方をどうぞ。


#### なぜコミットの前に git add を挟むのか？ 
こんな疑問を持った方もいるのではないでしょうか？
僕は持ちました。**直接コミットすりゃいいじゃん**。

前回ちょろっと説明したとおり、**コミットを細かくして他人にコードの意図を伝えるため**です。
**仮に`git add`がなく、編集してあるものをすべて`git commit`するしかない仕様**を考えてみましょう。

---
あなたは2つの新規機能を開発しています。それぞれ新規ファイルが1つずつ必要です。
順調に実装が進み、無事2機能・2ファイルを書き終えました！
**ここまでコミットをしていなかった**のでコミットしとこう…

---

`git add`が無いと、**2ファイルを同時にコミットする**ことになります。
つまり、**`git add .`しかできないということと同じ**です。

```
$ git add .
$ git commit -m '新機能1と2を実装' 
```
**1コミットに意味の違う2ファイルが含まれます**。
**どちらのファイルがどちらの機能なのか、分かりにくい**ですよね？

**`git add`がある場合**だとこうできます。

```
$ git add (1ファイル目)
$ git commit -m '新機能1実装'

$ git add (2ファイル目)
$ git commit -m '新機能2実装'
```
編集済みのファイルが複数あっても、このように**コミットを分けることが可能**です。

編集しながら適切な単位でコミットできれば理想なのですが、実際はそういきません。
ある程度編集して、**後からコミットすることが日常茶飯事です。**

コミットの目的の一つは**「人にコードの意図を伝えること」**でした。
**`git add`でコミットの単位を適度に分割する**ことでその目的を達成できます。

（`git add -p`を使えばファイル単位でなく行単位でコミットする箇所を選択できます。詳しくはググってみてください。）


## GitHubと連携しよう！
**Gitの真価を発揮するには、GitHubと連携すべき**です。（異論は認めます）
連携していきましょう！！

### リモートリポジトリを作る
リモートリポジトリとは、**GitHubにあるリポジトリ**のことでしたね。
みなさん自分のGitHubアカウントを持っていると思います。ない人は作っといてください。

自分のGitHubアカウントにリモートリポジトリを作り、ローカルリポジトリと紐付けていきます。

![スクリーンショット 2020-06-24 18.59.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455830/e95a673c-7afa-5a4a-32db-75210912baec.png)

右側の`New`を押してください。
そうすると、↓の画面になります。

![スクリーンショット 2020-06-24 19.21.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455830/f81635ae-84c3-ddaf-782f-e3c3d32f07e7.png)


リポジトリの名前、説明を入力。
Public（誰でもアクセスできる）かPrivate（自分しかアクセスできない）かはお好みで。
今回、`Initialize this repository with a README`の**チェックはつけないで**ください。

（チェックをつけると`Readme.md`というファイルがリモートリポジトリに生成されます。この記事の一番最後に行う`git push`の時に不都合が起こるので、チェックはしないでください。）

![スクリーンショット 2020-06-24 19.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455830/9e13a452-0dc5-2250-eef4-12b36b56273f.png)

こんな画面が出てきたと思います。
これだけで**リモートリポジトリが作成できました**！しかし、中身はまだ何もありません。

これからすることは、上記画像の一番下`...or Push an existing repository from the command line`の対応と同じです。
まずはリモートリポジトリとローカルリポジトリを紐づけていきます。

### リモートリポジトリとローカルリポジトリを紐づける
ローカルリポジトリにリモートリポジトリのURLを教えてあげます。

そのためのコマンドは`git remote add リモート名 リモートURL`です。
**「リモートリポジトリを追加するよ！ その名前は`リモート名`で URLは `リモートURL`だよ！ 」**ってことですね。
実際のコマンドはこうなります。

```
$ git remote add origin git@github.com:(GitHubユーザー名)/(Repository name).git
（originについては後述）
```
---
補足：(Repository name) はここ↓で指定したものです

![スクリーンショット 2020-06-24 19.25.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455830/e5c595c5-4049-836b-8627-a7b8daa537cb.png)

---

**`リモート名`？　なんで`origin`にするの？**と思いますよねー
`リモート名`とは、`リモートURL`のリポジトリの別名です。**上記のRepository nameとは違う**ので注意してください。
これを**`origin`にするのがGitHubのデフォルト**なのです。そうしておくと、様々なコマンドでリモート名を省略することができます。
大人しく**`origin`にしておきましょう**。

さて、コマンドを改めて載せておきます。（さっきと同じコマンドです）

```
$ git remote add origin git@github.com:(GitHubユーザー名)/(Repository name).git
```
ターミナルで実行してください。
何も表示されず、何も起こっていないように見えます。

`git remote -v`を実行してみましょう。
これは、ローカルリポジトリに紐づいているリモートリポジトリのURLを表示するコマンドです。

```
$ git remote -v

origin	git@github.com:(GitHubユーザー名)/(Repository name).git (fetch)
origin	git@github.com:(GitHubユーザー名)/(Repository name).git (push)

```
このように表示されればリモートリポジトリが紐づいています。

### リモートリポジトリにローカルリポジトリの内容を反映する

ようやくここまできました。長かった…
今の状況を整理するとこうです。

- リモートリポジトリ
    - 作成したが、**空**
- ローカルリポジトリ
    - 作成済み
    - ファイルがある
    - **コミットしたファイルもある**
    - **リモートリポジトリと紐づいている**

ローカルリポジトリで**コミット（セーブ）したファイルを、リモートリポジトリに反映**してあげましょう。
そのコマンドは **`git push -u origin head`** ！！！！！！！！！

```
$ git push -u origin head

To github.com:(ユーザー名)/(Repository name).git
 * [new branch]      head -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
```
**「コミットした変更をリモートリポジトリに`push`（反映）するよ！
宛先はリモート名が`origin`のリモートリポジトリね！
`push`するのは`head`、つまり最新のコミットまでを頼むね！」**
 
（`git push -u origin master` でも「今は」同じ結果になります。`ブランチ`を理解してから使い分けましょう。）
（`head`については別の記事で詳しく解説します。今は丸暗記でOKです。）
（`-u`オプションをつける意味については、[この記事](https://qiita.com/shumpeism/items/1b8027c8905ca826416d)などを参照ください。このことを今は理解できなくていいです。）

これで**リモートリポジトリに反映**されました！！！
確認してみましょう。

GitHubの右上にある自分のアイコンをクリックし、`your repositories`を選択してください。
![スクリーンショット 2020-06-24 23.41.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455830/12db111e-5347-65be-bba3-30f4a98e65ed.png)

そして、先ほど作成したリモートリポジトリを開いてみると…
![スクリーンショット 2020-06-24 23.43.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455830/6206a37f-0871-4c1e-bd70-52952728985e.png)
ファイルが追加されているはずです！
（僕は test と test2 というファイルを`push`しました）

これで**ローカルリポジトリの変更をリモートリポジトリに反映**する、つまり**同期**することができるようになりました！！！

これでようやく**Git/GitHubを使うスタートライン**です。
この記事での説明はこれでおしまい。（長いし…）

次の記事では、逆に**リモートブランチの内容をローカルリポジトリに反映する方法**や**`ブランチ`**について書こうと考えています。

## まとめましょう
これまでに学んだことをざっくりと。

### Gitを始めてからリモートリポジトリに同期させるまでの流れ

こんな感じ。

0. コードが格納されているフォルダを用意する
1. git init で**ローカルリポジトリを作る**
2. git add で**コミットするファイルを指定**する
3. git commit で**コミット（セーブ）**
4. GitHub上に**リモートリポジトリを作る**
5. git remote add で**ローカルリポジトリとリモートリポジトリを紐づける**
6. git push -u origin head でローカルリポジトリで**コミットしたものをリモートリポジトリに反映して同期**


### 用語とコマンド

- **Git**
  - バージョン管理をするためのツール
- **GitHub**
  - Gitをオンラインで共有するためのツール 
- **リポジトリ**
    - Gitで管理されているフォルダ
- **リモートリポジトリ**
    - オンライン（GitHubとか）にあるリポジトリ
- **ローカルリポジトリ**
    - 個人のPCにあるリポジトリ
- **git init**
    - 自分のPCにある（ローカル）フォルダをGit管理するためのコマンド
    - このコマンドによりフォルダがリポジトリとなる
    - `.git`が生成される
- **git add**
    - コミット（`git commit`）するものを選択するコマンド
    - `git add`することを「ステージング」と呼ぶ
    - `git add .`で全ての変更を選択できる
- **git status**
    - 何をステージングしたかを確認できるコマンド
    - 確認なので、このコマンドを実行しなくても可
- **git commit**
    - `git add`した変更をセーブするコマンド
    - **gitの主役**
    - コミット単位で過去の状態に戻ったりできる
- **git remote add**
    - ローカルリポジトリとリモートリポジトリを紐づけるコマンド
    - ローカルリポジトリにリモートリポジトリのURLを登録する
    - このコマンドを実行してからGitHubと連携ができるようになる
- **git push**
    - ローカルリポジトリでコミットした変更をリモートリポジトリに反映するコマンド
    - このコマンドによりローカルとリモートが同期できる

## さいごに
いろんな説明記事を見て、それらをなぞれば`push`までたどり着くことは簡単にできます。
しかし実行している内容を細かく体系立てて説明していた記事は見当たりませんでした。
僕は実際にGit/GitHubを使っているとき**「いつも打っているこのコマンドは何をしているんだろう？」**という疑問がよく出てきました。
この記事では自分が辿ってきた疑問を全て潰してきたつもりです。
これからGitを触る人・Gitを使ってるが実はよく分かっていない人にとって参考になれば幸いです。

例によりこの記事は初心者向けなので、厳密には違う説明の箇所もあります。
しかし初心者としてはこの理解で十分です。疑問に思う時が来たその時は、自分で調べてより正確に理解してみましょう。

あれ？ブランチの説明はないの？ と思った方もいるかと思います。
ブランチを理解するには、まずこの記事の内容の理解が必要と感じているので、前段階としてこれを説明しました。
次の記事ではブランチも説明していくつもりです！！！！！

そもそもなんでGitを使うの？バージョン管理をするの？って人は、まさにこの記事を参照下さい。
・[なぜ僕らはGitでバージョン管理をするのか](https://qiita.com/gakisan8273/items/d2d52a12ad553a82b94b)


2020/12/08追記
ブランチの解説記事書きました！！！！
[初心者がしっかりと理解できるようにGitのブランチを説明する](https://qiita.com/gakisan8273/items/0e0ad1fee2a7c623f8d6)

よかったら[Twitter](http://twitter.com/gakisan8273)もフォローしてね。