Git コマンドとGitHub入門

# はじめに
この記事は、エンジニア経験1年の大学生が実務で勉強になったこと、詰まったことをまとめています。間違っている箇所などがございましたら、指摘していただけると幸いです。

# 背景
普段何気なく使用しているgitですが、gitにはいろいろなコマンドが用意されており、いつも使うコマンド以外はあまり理解できていませんでした。同期のインターン生に教えていただくことがあったので、このタイミングで、gitについてもう一度学習しようと思い、記事にしました。

# Gitの歴史
Gitはバージョン管理システムの1つで、世界最大級のオープンソースソフトウェアの1つであるLinuxのカーネルのソースコードを効率的に管理するために作られた。Linuxの生みの親であるリーナス・トーバルズ氏が2005年に開発をスタートした。

# GitHub
GitHubにソースコードをホスティングすることで複数人の開発者と協働してコードをレビューしたり、プロジェクトを管理しつつ開発を行うことができる。アメリカのカリフォルニア州サンフランシスコ市に拠点を置くGitHub社によって保守されている。主な開発者であるクリス・ワンストラスが元々Gitのファンで、オープンソースの開発をしていた。当時、オンラインでコードをシェアすることができなかったので、他の開発者とコードをシェアできるGitHubを開発した。

# GitHubはリモートリポジトリとローカルリポジトリがある
リポジトリはファイルやディレクトリの状態を保存する場所。
リポジトリは自分のPC内にある「ローカルリポジトリ」とサーバなどネットワーク上にある「リモートリポジトリ」の2箇所にある。

# ローカルは３つのエリアに分かれる
ワークツリー、ステージ、リポジトリが存在する。

#### ワークツリー
- ファイルを手元で変更する作業場
- ステージに変更を追加する


#### ステージ
- コミットする変更を準備する場所
- 一旦、変更を追加する

#### リポジトリ
- スナップショットを記録する場所

# ローカルリポジトリの作成
ローカルリポジトリの作成は二種類ある。
1つ目は新しいリポジトリを作成する方法、２つ目はリモートリポジトリをコピーして作成する方法。

### 新しくリポジトリを作成する方法

#####1. 新規でディレクトリを作成し、そのディレクトリに移動する

```
$ mkdir hogehoge

$ cd hogehoge
```

#####2. リポジトリの初期化を行う

```
$ git init
```

.gitディレクトリが作成され、リポジトリ、インデックスファイル、設定ファイルなどgitで必要なファイルが作成される。


### リモートリポジトリをコピーして作成する方法


#####1. 他の人が作成したリポジトリをコピーする

```
$ git clone <URL>
```
URLは`git clone`したいリポジトリから取得できる

![スクリーンショット 2022-02-05 18.58.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880196/a5b6062d-1317-81cd-f8a2-bfc1369f34de.png)

# リモートリポジトリ(GitHub)を新規追加する

```
$ git remote add origin <リモートリポジトリURL>
```
`origin`という名前で、リモートリポジトリを登録できる。今後、`origin`という名前でGitHubリポジトリにアップしたり、取得したりできるようになる。


# Gitコマンド

### git add
```
$ git add .   # 変更した全てのファイルをステージに追加する
```
ワークツリーの変更をステージに追加する。


### git commit
```
$ git commit -m "メッセージ"
```
ステージに追加された変更をリポジトリに記録する。


### git status
```
$ git status
```
変更されたファイルを確認できる。
ステージに追加されていない変更やリポジトリに追加されていない変更が確認できる。
`git add`や`git commit`前に使用することが多い。


### git diff
```
# git add する前の変更差分
$ git diff
$ git diff <ファイル名>

# git add した後の変更差分
$ git diff --staged
```
ワークツリーとステージ間の変更差分を確認するときは、`git diff`で確認する。
ステージングとリポジトリ間の変更差分を確認するときは、`git diff --staged`で確認する。


### git log
```
$ git log

# 1行で表示する
$ git log --oneline

# ファイルの変更差分を表示する
$ git log -p <ファイル名>

# 表示するコミット数を制限する
$ git log -n <コミット数>
```
変更履歴を確認する。


### git rm
```
# ファイルごと削除
$ git rm <ファイル名>
$ git rm -r <ディレクトリ名>

# ファイルを残したいとき
$ git rm --cached <ファイル名>
```
`git rm`はコミットされたファイルも削除され、ワークツリーのファイルも削除される。
ワークツリーからは削除したくないが、gitの記録からだけ削除したい場合は`git rm --cached`を使う。
`git rm --cached`は間違えてパスワードなどの情報を上げてしまった場合などに使用する。


### git mv 
```
$ git mv <旧ファイル><新ファイル>

# 以下のコマンドと同じ
$ mv <旧ファイル><新ファイル>
$ git rm <旧ファイル>
$ git add <新ファイル>
```
ファイル名の変更を記録し、ステージに追加する。


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

# 初回のpushする際に、実行する
$ git push -u origin <ブランチ名>
```
リモートリポジトリ(GitHub)にプッシュすることができる。`-u`オプションは初回に実行することで、次回以降`git push`だけでプッシュすることができるようになる。


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

# 全変更を取り消す
$ git checkout --.
```
ファイルの変更を取り消す。ワークツリーの変更を取り消す。`git checkout -b`とは違う。`--`になっていることに注意。


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

# 全変更を取り消す
$ git reset HEAD .
```
`git add`でステージに追加した変更を取り消す。指定した変更をステージから取り消すだけなので、ワークツリーには影響を与えない。


### git commit --amend
```
$ git commit --amend
```
直前のコミットをやり直す。直前のコミットを修正し、今のステージの状態を反映する。ただし、リモートリポジトリにプッシュした後にコミットをやり直すことはできない。


### git remote
```
$ git remote

# 対応するリモートリポジトリのURLを表示する
$ git remote -v
```
リモートリポジトリを表示する。

### git stash
```
$ git stash
```
作業を一時避難するコマンド。コミットまではしたくないが、別のブランチで作業をしたくなった時に使用することができる。変更分を`stash`に保存する。`git add`や`git commit`の前に行うと、`stash`に一時避難することができる。

#### git stash list
```
$ git stash list
```
避難した作業の一覧を表示することができる。

#### git stash apply
```
# 最新の避難した作業を復元する
$ git stash apply

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

# 特定の避難した作業を復元する
$ git stash apply <スタッシュ名>
```
避難した作業を復元するコマンド。`--index`オプションを付けることで、ステージにも反映することができる。

#### git stash drop
```
# 最新の避難した作業を削除する
$ git stash drop 

# 特定の避難した作業を削除する
$ git stash drop <スタッシュ名>

# 避難した全作業を削除する
$ git stash drop clear
```
避難した作業を削除する。

### git rebase
```
$ git rebase <ブランチ名>
```
履歴を整えた形で変更を統合する。GitHubにプッシュしたコミットをリベースしないように注意する。gitの履歴が壊れてしまうので、`git push -f`は絶対にしない。


## リモートリポジトリから取得する方法は2種類ある
### git pull
```
$ git pull

# 下記コマンドと同じ
$ git fetch origin master
$ git merge origin/master
```
リモートリポジトリから情報を取得して、マージまで行いたい時に使用する。ワークツリーに反映されるので、`git merge`は必要ない。


### git fetch
```
$ git fetch <リモート名>
$ git fetch origin
```
リモートリポジトリから情報を取得し、ローカルリポジトリに保存する。ワークツリーには反映されない。ワークツリーに反映させたい場合は、`git merge`で統合する。


## ブランチ
ブランチとは、コミットを指すポインタである。ブランチは分岐して作業ができ、複数機能の開発や複数人での開発を同時に行うことができる。

### git branch <ブランチ名>
```
$ git branch <ブランチ名>
```
上記コマンドはブランチを作成するだけで、ブランチの切り替えは行わない。


### git branch
```
$ git branch

# 全てのブランチを表示する
$ git branch -a
```
ブランチを表示するコマンド。リモートリポジトリのブランチも表示したい場合は、`-a`オプションを付けると表示できる。


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

# ブランチを新しく作成し、切り替える
$ git checkout -b <新ブランチ名>
```
ブランチを切り替えるコマンド。`-b`オプションは新規でブランチを作成し、切り替えることができる。


### git branch -m
```
$ git branch -m <新ブランチ名>
```
自分が作業しているブランチ名を変更することができる。


### git branch -d
```
$ git branch -d <ブランチ名>

# 強制削除する
$ git branch -D <ブランチ名>
```
ブランチを削除することができる。masterにマージされていない変更がある場合、削除されない。それでも削除したい場合は、`-D`オプションを付けると削除できる。


# 便利なgitコマンド
### git cherry-pick
```
$ git cherry-pick <コミットID>

# 別のブランチからコミットをコピーしたいが、コミットはしたくない場合
$ git cherry-pick -n <コミットID>
```
別のブランチから今いるブランチへ、必要なコミットだけをコピーし、コミットされるコマンド。`-n`オプションを使うことで、コミットされないようになる。


# マージ
マージとは、他の人、他のブランチの変更内容を取り込むこと。

### Fast Forward
分岐後、元ブランチが変更がない場合のマージ。

### Auto Merge
一般的なマージであり、枝分かれして開発していた場合、マージコミットという新しいコミットを作成する。

```
$ git merge <ブランチ名＞
```


# コンフリクト
同じファイルの同じ行に対して、異なる変更を行った時に発生する。コンフリクトが起きても、慌てず、冷静に対応すれば問題ない。

```
<<<<<<< HEAD
# 作業ブランチでの変更内容
<h1>コンフリクト</h1>
=======
# develop(マージしたブランチ)での変更内容
<h1>コンフリクト発生</h1>
>>>>>>> develop
```
ファイルの内容を書き換え、`>>`や`==`や`<<`を削除すると解消することができる。

```
<h1>コンフリクト</h1>
<h1>コンフリクト発生</h1>
```

# プルリクエスト
自分が変更したコードをリポジトリに取り込んでもらえるよう、他の人にレビュー依頼をする機能。


# Gitコマンドにエイリアスを付ける
### git config --global alias
```
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.br branch
$ git config --global alias.co checkout
```
日常で頻繁に使うコマンドはエイリアスを付けることで、入力を楽にすることができる。`--global`オプションを付けることで、PC全体の設定になる。


# バージョン管理したくないファイルがある場合
AWSで使用されるパスワードや機密情報が記述されているファイルや自動生成されるファイルなど、バージョン管理したくない場合がある。その時に、`.gitignore`ファイルを使用する。`.gitignore`に記述することでバージョン管理の対象から外れる。