Github 基本事項まとめ

### この記事について
- インターンなどを通してGithubについて学んだことを整理した備忘録である。
- 以下が含まれる。
    - Githubとは？
    - Githubを用いるメリット
    - Githubを利用する際に聞く用語とその簡単な説明
    - sshによるGithubとの接続方法
    - リモートリポジトリ(後述)にファイルをアップする方法
    - リモートリポジトリからファイルをダウンロードする方法


## Githubの概要と用語の説明
 ### [Githubとは](#Githubとは)
- バージョン管理ツール Git のWebアプリ版
- バージョン管理とは：コードの変更履歴を記録し管理するもの。
- 「あの時のコード修正を取り消して元に戻したいなあ」といったときに過去のコードに瞬時に戻すことができるツール

### なぜGithubか、メリット
- コードの変更履歴を保存できる。セーブポイント(コミット)単位で**バージョンの巻き戻し**ができる。
- **機能や修正内容ごとに作業スペースを分けられる。** ブランチを作成することで実現できる。
- 複数人の開発がしやすくなる。
- **機能や修正内容ごとにタスクを割り振る**のに適している。分担しやすい。（ブランチ）
- **作業内容をWebブラウザ上で簡単に確認**したり、コメントをつけたりできる。（プルリクエスト）
- **意図しない作業内容の上書きを防止**できる。（マージ, コンフリクト）
- 個人作業用のスペースと共有スペースがあるため、それぞれが**独立して開発**を進められる。（ローカル/リモートリポジトリ）
- 自動でテストやビルドができる(GitHub Actions)
- ソースコードを簡単に公開できる

 #### 各種用語の説明
| 用語| 説明 |
| ---- | ---- |
| リポジトリ |ファイルやディレクトリの状態を記録する場所(貯蔵庫)|
|ローカルリポジトリ|自分のPCにあるリポジトリ|
|リモートリポジトリ|サーバーにあるリポジトリ|
 |インデックス(git addで作成される)|コミットの対象となるファイルを置いておく場所、無駄なファイル交換を防ぐ|
 |クローン(git clone)|リモートの内容をローカルへ(ダウンロード)|
 |コミット(git commit)	|インデックスから、ファイルをローカルリポジトリに保存する
 プッシュ(git push)	|ローカルリポジトリをリモートリポジトリに送信すること
 プル(git pull)	|リモートリポジトリの変更をローカルリポジトリに反映させる。フェッチ+マージ
 フェッチ(git fetch)|リモートから最新情報をローカルへ
 マージ(git merge)|ローカルの「origin/master」ブランチ → ローカルの「master」ブランチ。
 マージ|現在のブランチ(HEADの指している場所)へ、他のブランチの更新を取り込む処理。ブランチの統合
 コンフリクト|マージ対象の２ファイルで同じ箇所が変更されており、自動でマージができないこと。複数人が同じ箇所を変更した場合に、どの記述を優先したらいいか分からない状態
 ブランチ|作業履歴を枝分かれさせて記録する
 プルリクエスト（Pull Request）| 「こういう変更内容を適用させてください！」というような申請をだして、コードレビューが可能
 GitHub Actions|テストやビルドなどを自動で行ってくれるツール
 リモート追跡ブランチ|リポジトリをクローンした際にローカルリポジトリ上に作成される、リモートリポジトリの状態を表すためのブランチ

 
## 初期設定編：接続

Githubでは、レポジトリに接続 -> (ブランチの作成、接続) -> ローカルにファイルを追加 -> コミット -> pushの流れでファイル共有を行います。

そのため今回の例では、まずGithubとssh接続を行います。

そもそもGithubではhttp,https,git,sshの4種類のプロトコルを使ってリポジトリに接続ができます。

- http：通信が暗号化されていないのであえて使う意味は無い
- https：暗号化がされ、GitHubの推奨プロトコル

またhttpやhttpsの方が高速で、クローンも高速に行うことが出来ます。
しかしSSHには、仕組みが比較的分かりやすく、なおかつ一般的なアクセスには困らないというちょうど良さがあります。

また、ssh接続は広く利用されるので今後の役にも立ちます。 ぜひ手順をふんわり掴みましょう。

 ### ssh接続とは
- ネットワークを経由してマシンを遠隔操作する仕組み
- 通信が暗号化されているのが特徴的
- 暗号化に公開鍵と秘密鍵が必要(手元で生成)
- 接続先に鍵を登録して認証してもらう

### ssh接続の手順
**(手順１)公開鍵、秘密鍵の生成**

鍵を入れるディレクトリへ移動 
`cd ~/.ssh`

.sshは隠しディレクトリと呼ばれるもので、普段は表示されないようになっています。
ディレクトリ名の前に "." がついているものは隠しディレクトリです。
表示したい場合は、`ls -a`とすることで表示されます。

次に、鍵の生成を行います。
`ssh-keygen -t rsa -f <file_name>`
<file_name>は任意のファイル名を指定してください。指定しなければデフォルトでid_rsaとid_rsa.pubの二つの鍵が生成されます。
何か聞かれたら3回エンターを押せば鍵の生成は完了です。

**(手順２)公開鍵をGithubにアップ**

( https://github.com/settings/ ) で公開鍵の設定が出来ます。（GitHubに登録していることが前提条件です）
画面右上の「Add SSH key」のボタンを押し、「title」に公開鍵名、「key」に公開鍵の中身を入れます。
`vi id_rsa.pub`
などして公開鍵をコピペしてください。

**(手順3)公開鍵をデフォルト以外の名前で作った時は以下を行なってください。それ以外は手順4へ**

.ssh/configを作成してその中に以下を書き込んでください。
```code: config
 Host github github.com
   HostName github.com
   IdentityFile ~/.ssh/<自分の鍵のファイル名>
   User git
```

**(手順4)接続の確認**
`ssh -T git@github.com`
を実行し、
Hi (account名)! You've successfully authenticated, but GitHub does not provide shell access.
と返ってきたらOK!

## Github push編：add, commit, push ~基本操作とよくあるミス、原因その対処法~

1. リポジトリの取得
`git clone <リンク>`

2. 自分のローカル環境にあるブランチを確認
`git branch`
or
`git branch -a` (リモートのブランチ環境とローカルのブランチ環境が確定する)

3. ブランチを作る(or 切る)
`git branch <ブランチ名>`

4. ブランチに移動する
`git checkout <ブランチ名>`

5. 変更したファイルの一覧を確認
`git status`

6. 変更したファイルのソースコードを確認
`git diff [-w]` -wオプションで空白を無視できる

7. コミットしたいファイルを選択
`git add <ファイル名>`

     すべてのaddの取り消しを行いたいとき
`git reset HEAD` 

    特定のファイルのaddを取り消したいとき
`git reset HEAD file_name`


8. 変更点に問題がなければコミット
`git commit -m "コメント内容"`

9. コミットログの確認
`git log [-n]` -n で履歴の数を限定できる

ここまではローカルのリポジトリにのみ影響する

10. githubへpush
`git push origin <ブランチ名>`


### よくあるミス
 **間違えてadd (or rm) した**

`git reset HEAD`
`git reset HEAD <ファイル名>`

 **commitメッセージを打ち間違えた**

`git commit --amend` で
1. vimを開き i を押して挿入モードにする。
2. メッセージを修正する。
3. escを押してモードを戻す。
4. :wqで内容を保存する。

 **commit内容を間違えた**

 直前のコミットを取り消せる
`git reset –soft HEAD^`

特定のcommitを打ち消す
`git revert <commitメッセージのid>` idは`git log`で確認できる


　**間違えてpushした**
- よくない方法
ログを抹消してなかったことにする。
    - 自分のローカルmasterがリモートにあるmasterより古いものだったら、その古いところまで逆戻りさせることになる → 他の人の作業内容も吹っ飛ぶ
```code: sh 
git reset --hard
git push origin master -f
```
- 正しい対処1
gitのコミットの差分状から作業内容を復帰させて、作業ブランチ上で、pushする。
```code:sh
 git checkout master
 git pull
 git checkout -b 取消用のブランチ名
 # 自分の作業内容を元に戻す
  
 git push origin 取消用のブランチ名
 
 # github上でmergeする
```
- 正しい対処2
念のため、ローカルのmasterをpullで最新に → 作業ブランチでも最新の状態をmergeで反映 → 本来自分がpushすべきだった作業ブランチへpush
```code:sh
 git log
 
 自分の間違えたコミットのIDを見つける
 git revert 間違えたコミットのID
 
 git pull
 git checkout 本来のpushすべき作業ブランチ
 git merge master
 git add .
 git commit -m "コミットメッセージ"
 git push origin 本来のpushすべき作業ブランチ
```


## Github pull編：fetch, pull, merge ~よくあるミスと原因その対処法~

`git fetch`
リモートリポジトリにある内容をリモート追跡ブランチ(ローカル)に持ってくる(ローカルの更新はしない)

`git diff <ローカルブランチ> origin/<ローカルブランチ>`
origin/<ローカルブランチ> はリモート追跡ブランチのこと。このコマンドでリモート〜ローカル間の差分の確認ができる。

`git merge <リモート追跡ブランチ>`
リモート追跡ブランチの内容をマージを実行して取り込む

`git pull`
最新の更新内容を取得して、一番最新の内容をマージしてくれる(つまり、fetch + merge)

### よくある問題
 - ローカルで未コミットの変更をリモートに反映させずローカルでだけ保持したい
 	- リモートの変更で上書きせず、ローカルでの変更を保持したい場合
    	1. 事前に、ローカルでだけ保持したい変更以外の変更をすべてコミットする
    	
    	1. ローカルでだけ保持したい変更を退避させる 
    	 `git stash save "どんな内容のstashか"`

        1. この状態で `git pull` する
        
        1. `git stash list` で退避したものリストを確認する。
        実行すると`「stash@{番号}」(これがstash名): On 「ブランチ名」: 「メッセージ」`のように表示される

        1. `git stash apply <復旧したいstash名>`で復旧させる。
        この時、競合が起きるstashの方を採用したいなら、
`git checkout --theirs <ファイル名>` 逆なら`git checkout --ours <ファイル名>`
        1. `git stash drop <stash名>` で退避を削除




**参考文献**

> GitHubとは何か？gitとの違いやメリットについてもわかりやすく解説！：https://webpia.jp/github/#index_id1

> GitHubとは？初心者向けにメリットや知識、機能を解説：https://techmania.jp/blog/github0001/

> 【Git】コンフリクトとは？どうやって解消するのか？【初心者向け】：https://www.engilaboo.com/git-conflict/

> 【初心者向け】git fetch、git merge、git pullの違いについて：https://qiita.com/wann/items/688bc17460a457104d7d

> git mergeでブランチをマージしよう!いろんな疑問を徹底解説：https://www.sejuku.net/blog/71003

> 【Git】インデックスとは？【図解でわかり易く解説】：https://tetoblog.org/2021/06/git-index/#i-2

> 【Git・GitHub】用語のまとめ：https://zenn.dev/miya_akari/articles/13c718afa783fe

> Git 基本の用語集：https://qiita.com/toshi_um/items/72c9d929a600323b2e77

>変更を一時的に退避しよう!git stashを使いこなす5つのステップ：https://www.sejuku.net/blog/71428#index_id2

>git stash でコンフリクトしたとき : https://shirokurohitsuji.studio/2021/12/15/git-stash-conflict/

>git pull実行時にローカルで未コミットの変更を保持する方法 : https://dev.classmethod.jp/articles/git-pull-local-change-keep/

> 【Git入門】git pullの使い方！pullで最新ソースを取得しよう : https://codelikes.com/git-pull/