Gitを知りたいすべてのエンジニアに捧ぐ。。。

# はじめに
エンジニアには欠かせないもの。たくさん必要なものがある中の一つに「Git」があるかと思います。駆け出しエンジニアには「何それ？」といった人は多いと思います。現役エンジニアでも、Gitについては知っていても使い方でこんな使い方も出来るんだ！ということもあるほど奥が深いです。
Gitを制するものはエンジニアを制するということで、最低限、基本知識は身に付けましょう！！
(※最後の方にGitの用語一覧も用意しているので、活用してみてください！)

## Gitとは？
まずGitとは、分散型バージョン管理システムのことです。
もう少し分かりやすく言うと、ファイルのバージョン管理を簡単に行えるツールです。
使い方の例としては、コードを編集した際に何か不具合が発生したので、元のバージョンへ戻す。といったことが出来ます。

### 特徴
- 古いバージョンに簡単に戻すことが出来る。

- ファイルを一元管理することができる

- 編集した履歴を複数人で共有できる

- 複数人で修正した部分を一つに統合できる

## Gitプラットフォームについて
Gitを効率よく使うためには、ほとんどの場合プラットフォームを利用します。
そこで、有名なものを上げると、3つあります。

### [GitHub](https://github.co.jp/)
ハブ(Hub)とは、「拠点・中心・集まり」と言う意味で、Gitの仕組みを利用し、世界中の人々が自分のプログラムコードやデザインデータなどを保存、公開できるようにしたWebサービスの名称です。

### [GitLab](https://about.gitlab.com/)
オープンソースのGitリポジトリ管理ソフトウェアです。2014年に創業。最新の資金調達も含めて、4500万ドル以上の資金調達を成功させるなど、Gitリポジトリ管理の分野においてはGitHubに次ぐ「ナンバーツー」の存在です。


### [BitBucket](https://bitbucket.org/)
タスク管理のJIRA、社内Wikiなどでよく用いられるConfluenceなどのベンダーでもあるAtlassianが提供しているGitプラットフォームです。日本ではマイナーではありますが、アメリカなどでは非常に多くの企業がBitBucketを用いています。

## 特徴
大体は似たり寄ったりなのですが、個人的には今勢いがあるGitLabがおすすめですかね〜。
簡単にCI/CDを使えたり、プライベートリポジトリが無料で利用できたりと、優れている部分が多くあるので！
(※とは言っても、使い慣れているのはGitHubなので使いがちなのですが、、笑)

#### 共通
- フォーク(Fork)
    - 一つのプロジェクトが複数に分派していくのを食器のフォークの先端に例えが名称の所以です。
    - 誰かのリポジトリをほかの人がコピーすることが出来る機能。
- プルリクエスト(Pull Request)・マージリクエスト(Merge Request)
    - 自分が行った変更をオリジナルのものに反映したい時に使います。
    - ここで、レビューをしてもらったりします。
- マージ(Merge)
    - 特定のブランチに指定したブランチの内容を統合させる機能。
    - 主に、メインブランチにプルリクエストで修正したトピックブランチの内容をマージします。
- イシュー(Issues)
    - プロジェクトやソースコードの課題を管理するための機能。
    - リポジトリ単位に管理されている。

- ウィキ(Wiki)
    - ビルド時の手順や注意事項、調査結果や引き継ぎなど、チームメンバーと共有したい情報を記載する。
    - 基本は自由に記載する。

#### GitHub特有
- アクション(Actions)
    - GitHub上で動作するサーバレス実行環境。
    - 複数のActionを組み合わせ、実行する順番を定義することで独自のワークフローを構築できます。
- プロジェクト(Projects)
    - アジャイル開発や、プロジェクトマネジメントという視点で、カンバン式のタスク管理が出来る機能。

#### GitLab特有
- CI/CD
    - GitHubは外部のCIサービスと、CIのベースとするDockerのコンテナレジストリサービスと連携して行うが、GitLabはいずれも無料で標準搭載している。

## メリット
- ソースコードのコラボレーション開発・コードレビュー機能
- WebUIで様々ながことが行える高いユーザビリティ
- チケット管理機能などの開発に関わる重要な付随機能や、そういった機能・サードパティサービスとの連携機能


## 基本的なコマンド使い方一覧
まず、ここに載っているものは頭に入れておくと開発がスムーズに進みます！！

#### version

```ruby

$ git --version # バージョンの確認
```

#### init

```ruby

$ git init # ディレクトリにリポジトリを作成
$ git init --bare # ベアリポジトリの作成
$ git init --shared # グループ書き込み権限の有効
```

#### config

```ruby

$ git config --list # 設定の確認
$ git config キー名 # 設定の確認
$ git config キー名 設定値 # ローカルリポジトリに登録・更新
$ git config --global キー名 設定値 # すべてのローカルリポジトリに登録・更新
$ git config --unset # キー名削除
$ git config -l # 使用されるリポジトリの設定を表示
$ git config --global user.name ユーザー名 # ユーザ名の設定
$ git config --global user.email メールアドレス # メールアドレスの設定
$ git config --global color.ui auto # 出力結果を色付け
```

#### add

```ruby

$ git add ファイル名
$ git add *.html.erb # 「〇〇.html.erb」をステージングに上げる
$ git add -A # すべての変更を含むワークツリーの内容をインデックスに追加
$ git add -u # 以前コミットしたことがあるファイルだけインデックスに追加
$ git add . # すべてのファイルをステージングに上げる
$ git add -p ファイル名 # 任意のブロックに分割し、ブロック毎に処理(下図参照)
```

##### -pオプションの選択肢一覧

| 選択肢 | 内容 |
|:-:|:-:|
| y  | 通常通りaddする  |
| n  | スキップする  |
| q  | 終了する  |
| a  | これ以降すべてaddする  |
| d  | これ以降すべてスキップする  |
| g  | 指定したブロックへ移動する  |
| /  | 正規表現でのブロック検索する  |
| j  | 未確定なブロックに移動する  |
| J  | 次のブロックへ移動する  |
| k  | 未確定な前のブロックへ移動する  |
| K  | 前のブロックへ移動する  |
| s  | ブロックを分割する  |
| e  | 手動で現在のブロックを修正する  |
| ?  | ヘルプを表示する  |

#### commit

```ruby

$ git commit # インデックスに追加されたファイルをコミット
$ git commit -m “コミットメッセージ” # コミットと同時にメッセージを指定
$ git commit -a # 変更されたファイル(新規を除く)をインデックスに追加・コミット
$ git commit --amend -m "コミットメッセージ" # 直前のコミットメッセージを修正
```


#### push

```ruby

$ git push リモートリポジトリパス ブランチ名 # リモートリポジトリに変更を書き込む
$ git push リモートリポジトリ名 --tags # リモートリポジトリにすべてのタグをアップロード
$ git push リモートリポジトリ名 タグ名 # リモートリポジトリに指定したタグをアップロード
$ git push リモートリポジトリ名 :ブランチ名(タグ名) # 指定したブランチ,もしくはタグをリモートリポジトリから削除
$ git push -f # ローカルブランチの内容で強制的に上書き
$ git push -n # 実行せずに実行する内容だけを表示
```

#### merge

```ruby

$ git merge ブランチ名 # 現在のブランチをほかのブランチとマージする
```

#### status

```ruby

$ git status # 前回のコミットと比較したファイルの変更点を表示
$ git status -s # 短い書式で表示
$ git status -sb # 現在のブランチ情報を表示
```

#### checkout

```ruby

$ git checkout ファイル名 # HEADと同じ状態に戻す
$ git checkout . # 全ファイル、HEADと同じ状態に戻す
$ git checkout コミットID ファイル名 # # 指定したコミットIDと同じ状態に戻す
$ git checkout ブランチ名 # ブランチ移動
$ git checkout -b ブランチ名 # 新たにブランチを作成して移動する
$ git checkout --ours ファイル名 # マージでコンフリクトした際、上方を指定してファイル内容を採用する.
$ git checkout --theirs ファイル名 # マージでコンフリクトした際、下方を指定してファイル内容を採用する.
```

#### log

```ruby

$ git log # コミットログを参照
$ git log --oneline # コミットログの先頭７桁のコミットIDを表示
$ git log --decorate # コミットログのHEADの位置を明示
$ git log --graph # コミットログを縦グラフで表示
$ git log --grep [filter] # 指定した文字がコミットログに含まれるコミットを表示
```

#### diff

```ruby

$ git diff # インデックスとワーキングツリーの差異を表示
$ git diff --cached # HEADとインデックスの差分を表示
$ git diff コミットID1 コミットID2 # コミット間の差異を表示
```

#### show

```ruby

$ git show # 最新のコミット内容を表示
$ git show タグ名 # タグを指定してコミット内容を表示
```

#### tag

```ruby

$ git tag # タグの一覧を表示
$ git tag -n[number]@ # タグとそのメッセージ[行数指定]の一覧を表示
$ git tag -l フィルター # タグをフィルターをかけて表示
$ git tag タグ名 # 現在のコミットIDにタグを関連付け
$ git tag タグ名 コミットID # コミットIDを指定してタグを関連付け
$ git tag -a タグ名 # 現在のコミットIDにメッセージ付きのタグを関連付け
$ git tag -d タグ名 # 指定したタグを削除
```

#### rm

```ruby

$ git rm ファイル名 # ワークツリーとインデックスからファイルを削除
$ git rm --cached ファイル名 # インデックスのファイルを削除
```

#### mv

```ruby

$ git mv 旧ファイル名 新ファイル名 # ファイル名を変更
```

#### stash

```ruby

$ git stash # 現在の状態を保存
$ git stash save “メッセージ” # メッセージ付きで現在の状態を保存
$ git stash list # 保存した状態の一覧を表示
$ git stash pop # 最新の保存状態を復元
$ git stash pop stash@{numbar} # 番号を指定して保存状態を復元
$ git stash apply # 保存状態をリストに残したまま最新の保存状態を復元
$ git stash apply stash@{number} # 保存状態をリストに残したまま指定した番号の保存状態を復元
$ git stash drop stash@{[number]} # 指定した番号の保存状態を削除
$ git stash clear # 保存状態をすべて削除
```

#### clone

```ruby

$ git clone git@github.com:ユーザー名/リポジトリ名.git # リポジトリをコピー
```

#### reflog

```ruby

$ git reflog # 過去にHEADが指していたコミット一覧を表示
$ git reflog ブランチ名 # ブランチを指定して過去にHEADが指していたコミット一覧を表示
```

#### cherry-pick

```ruby

$ git cherry-pick コミットID # 別のブランチのコミットを現在のブランチにコピー
```

#### branch

```ruby

$ git branch &[new branch] # 現在のブランチの確認&新しいブランチを作成
$ git branch -a # すべてのブランチを確認
$ git branch -r # リモートブランチを確認
$ git branch -d ブランチ名 # ブランチを削除
$ git branch -m 旧ブランチ名 新ブランチ名 # ブランチ名を変更
$ git branch --set-upstream [my branch] [other branch] # 他のユーザーのブランチと自分のブランチを関連付ける
```

#### revert

```ruby

$ git revert コミットID # コミットIDのコミットを取り消す
```

#### pull

```ruby

$ git pull リモートリポジトリパス ブランチ名 # リモートリポジトリの変更を取り込む
```

#### fetch

```ruby

$ git fetch リモートリポジトリ名 # リモートリポジトリの最新情報を追加
$ git fetch --prune # リモートリポジトリの削除情報をローカルに更新
```

#### rebase

```ruby

$ git rebase -i コミットID # コミットIDの古い順にコミットが表示され、コミットの取り消しやコミットメッセージなどの編集が出来る
$ git rebase --abort # 直前のgit rebaseの編集を中止
$ git rebase --continue # git rebaseの変更を適応
```

#### remote

```ruby

$ git remote # リモートリポジトリの一覧表示
$ git remote add ユーザー名 リモートリポジトリパス # リモートリポジトリの追加
$ git remote rename リモートリポジトリ名 新リポジトリ名 # リモートリポジトリの名前変更
$ git remote show リモートリポジトリ名 # リモートリポジトリの情報参照
$ git remote prune リモートリポジトリ名 # リモートリポジトリで排除されたブランチをローカルからも削除
```

#### reset

```ruby

$ git reset # 全ファイルをステージングから取り除き、ファイルの変更は残す
$ git reset ファイル名 # 指定したファイルをステージングから取り除き、ファイルの変更は残す
$ git reset --hard # 全ファイルをステージングから取り除き、ファイルの変更した箇所も削除
$ git reset HEAD^ # 直前のコミットの取り消し
```


## こんな時どうする？(トラブルシューティング)
「こんな時どうしたらいいの〜〜〜〜〜」と言った場面に対応できる作業手順をいくつか記載しているので、困った際の参考にしてみてください！

### ブランチを作りたい時

```ruby

$ git checkout develop
↓
$ git checkout -b 作成するブランチ名
↓
$ git push -u origin 作成したブランチ名
```

### プルリクエスト作成したい時

1.以下のコマンドを実行する。

```ruby

$ git add .

$ git commit -m "コミットメッセージ"

$ git push origin ブランチ名
```

2.GitHub(GitLab等)に移動し、右上の緑色のCompare & pull requestボタンをクリック。

3.プルリクエスト内容を記入する。

4.どのブランチからどのブランチにpull requestするかを確認する。

-例-
developブランチからsampleブランチへのpull request

sample ... develop

5.「Create pull request」ボタンを押して、Pull Requestを作成。

### 最新情報を特定のブランチに反映させたい時

1.add 〜 pushまで終わらせた状態で以下のコマンドを実行する。

```ruby

git checkout メインブランチ名

git pull origin メインブランチ名

git checkout 開発用ブランチ

git merge origin メインブランチ名
```

2.もし、コンフリクトが発生した場合は、以下を実行する。

```ruby

# コンフリクト内容を解消した上で、、
$ git add .

$ git commit -m "コミットメッセージ"

$ git push origin 開発用ブランチ

$ git merge origin メインブランチ名
```

### ローカルをリモートに合わせたい時(強制的に)

```ruby

# リモートの最新を取ってくる
$ git fetch origin

# ローカルのmainを、リモート追跡のmainに強制的に合わせる
$ git reset --hard origin/メインブランチ名
```

### 間違えたコミットを取り消したい時

```ruby

# 直前のcommitの取り消し
$ git reset --hard HEAD^

# n個前のcommitの取り消し
$ git reset ---hard HEAD~n
```

### 間違えたリセットを取り消したい時

```ruby

# ログを出す
$ git reflog

# 任意のところでリセットする
$ git reset --hard HEAD@{number}
```

### コミット履歴を綺麗にしたい時

```ruby

# 必要な部分までのcommitを解除
$ git reset HEAD~n

# 必要な部分の修正を退避させておく
$ git stash

# 余計なコミットを削除
$ git reset HEAD~n --hard

# 退避しておいた修正部分を戻す
$ git stash pop 
```

# 終わりに
ここに書いていないコマンドや、トラブルシューティングはありますが、この記事を見れば割と色んなことに対応できる知識が身につくと思います。
Gitとはエンジニアという職業上、切っても切り離せないサービスなので、いつでも見返せるようにストックしておいてください！

## Git用語一覧
- リポジトリ(repository)
    - ファイルやディレクトリを入れて保存しておく倉庫のようなもの。
- リモートリポジトリ(remote repository)
    - 特定のサーバー上に設置して複数人で共有するためのリポジトリ。
- ローカルリポジトリ(local repository)
    - ユーザーごとに配置される手元のマシン(自身のPC環境)で編集できるリポジトリ。
- コミット(commit)
    - ファイルやディレクトリの編集作業をローカルリポジトリに記録するための操作のこと。
- ワークツリー(work tree)
    - ユーザーが編集している作業中のディレクトリのこと。
- インデックス(index)
    - 作業場所であるワークツリーと、保存場所であるローカルリポジトリの中間領域
- クローン(clone)
    - リモートリポジトリをまるごと自分のローカル環境（ローカルリポジトリ）に保存する機能。
- プッシュ(push)
    - ローカルリポジトリにあるファイルをリモートリポジトリに送信して保存する機能。
- ブランチ(branch)
    - ファイルの編集履歴を分岐させて記録していく機能。並行して同時に行われる作業を正確に管理出来る。
- マスターブランチ
    - メインのブランチのこと。変更等はこのブランチに統合される。
- トピックブランチ
    - マスターブランチから切り取られたブランチ。ここで、編集や修正等を行い、完了するとマスターブランチに統合される。
- マージ（merge）
    - トピックブランチをマスターブランチに統合すること。
- プル（pull）
    - 共有されているリモートリポジトリに保存されているファイルの内、ローカルリポジトリに無いファイルや他のユーザーが更新したファイルのみをダウンロードする機能。
- フェッチ（fetch）
    - リモートリポジトリからファイルの最新情報を取得してくる操作。(ローカルのファイルは更新されない)
- リモートリポジトリパス
    - 通常は「origin」としている。

## 参考

[【初心者向け】Gitとは何なのか。基本用語やその仕組みをまとめています。](https://tcd-theme.com/2019/12/what-is-git.html?gclid=Cj0KCQjwjPaCBhDkARIsAISZN7QYDwzHljAD1jyE5ePybputNISAhyqfMUWzb3qwCUam54z1hHNfeEcaAhbYEALw_wcB)

[GitとGitプラットフォームについてと、GitHubかGitLabかBitBucketの3大Gitプラットフォーム紹介](https://siderlabs.com/blog/ja/3-major-git-platforms/)

[GitHubとは何かわかりやすく解説！機能やメリットも簡単に紹介](https://www.sejuku.net/blog/7901)

[GitLabとは？GitHub買収で10倍のインポート数。使い方を解説](https://tech-camp.in/note/technology/44434/)

[GitHubの新機能「GitHub Actions」でワークフローを自動化しよう](https://codezine.jp/article/detail/11450)

[VSCodeでのGitの基本操作まとめ](https://qiita.com/y-tsutsu/items/2ba96b16b220fb5913be)

[git add -p 使ってますか？](https://qiita.com/cotton_desu/items/bf08ac57d59b37dd5188)

[コミットは作業ログではない](https://qiita.com/suzuki-hoge/items/cc91877ce69527ced692)