【目的別】Github手順書【初心者向け】

# 当記事の目的
### 以下の悩みを解決

- GitHubのコマンドが書いてあるページはたくさんあるけど、現状に合わせてどう組み合わせて使ったらいいか分からない
- はじめてGitHub触るけどぶっちゃけ何から手を付けたらいいか分からない

### 前提条件
- 構成管理システムの概念的な話は一切触れません
- GitHubのコマンドをインストール済みで、Linux上でGitHubにアクセスすることを想定
- fetchとは何か、mergeとは何か、ローカルリポジトリとは？originとは？みたいな話は別のまとめを見てください。気が向いたら参考ページ張ります
- 筆者がGitHubに慣れていくにつれ加筆されていきます

Windows環境の人は、インストールについてはそれなりに手間なので、[【Windows】Gitの環境構築](https://prog-8.com/blogs/git-preparation-windows)を参考にしてください。Linux環境の人はデフォルトでインストールされていることがほとんどですが、なければ`sudo apt-get install git`してください。

インデックスを見ながら、自分に合った目的をお探しください

# GitHubコマンド手順

## case1 : 開発チームに入ったぞ！早速ローカルのフォルダにリモートのソースコードをクローンしてこよう！

### 手順
- 自分のリポジトリにアクセス
![画像](http://drive.google.com/uc?export=view&id=1J71o3EvGH5hT1gSjJwzXUiBSJLIqNgRr)

- Clone or downloadをクリックし、表示されたURLを控える（`https://github.com/自分のリポジトリ.git`とする）
- ローカルリポジトリを作成したいフォルダに移動
- `$ git clone https://github.com/自分のリポジトリ.git -b branch_name local_folder_name`
    - branch_nameは、リモートのどのブランチをクローンするか指定
    - local_folder_nameは、作成するローカルリポジトリの名称（デフォルトは`リモートURL-ブランチ名`）
- ユーザID、パスワード入力を求められるため、GitHubにログインする際のユーザ名とパスワードを入力する

### 詰まりそうな点
- 社内でエンタープライズのGitを利用している場合や、セキュリティ意識の高い方で2段階認証設定をしている場合は、GitHubホームページ上でアクセストークンを発行して、PWの代わりに使う必要がある。[参考：Githubの2段階認証を実施してgitコマンドが使えないときにやったこと](https://qiita.com/n_morioka/items/650d2950f527d594a00f)

## case2 : ブランチを分けてカスタマイズをするぞ！まずはブランチを分けよう！

### 手順
- gitクローンされた、ローカルリポジトリ下にいることを確認
- `$ git branch`でブランチの状態を確認

```console
shun@shun-VirtualBox:~/xxx/yyy$ git branch
* original_branch_name
```

- `$ git checkout -b new_branch_name original_branch_name`で新ブランチ作成
    - new_branch_nameは、作成する新しいブランチの名称 
    - original_branch_nameは、基にするローカルのブランチ名称
    - リモートからチェックアウトする場合は`$ git checkout -b branch_name remote/origin/branch_name`
        - remote/origin/branch_nameがリモート、branch_nameがローカル
- `$ git branch`でブランチの状態を確認

```console
shun@shun-VirtualBox:~/xxx/yyy$ git branch
  original_branch_name
* new_branch_name
```

## case3 : カスタマイズが終わったから、分岐したローカルブランチに対してコミットしよう！
- gitクローンされた、ローカルリポジトリ下にいることを確認
- `$ git status`でチェックアウトしてからの変更情報を確認
    - `deleted:  moved_file.py`は、消去されたファイル（実際にはファイル移動）
    - `modified:  changed_file.py`は、変更が加えられたファイル
    - `deleted:  deleted_file.py`は、消去されたファイル
    - `new_file.py`は、新規で作成されたファイル
    - `new_folder/moved_file.py`は、新規で作成されたファイル（実際にはファイル移動）

```console
shun@shun-VirtualBox:~/xxx/yyy$ git status
ブランチ new_branch_name
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
	deleted:    moved_file.py
	deleted:    deleted_file.py
	modified:   changed_file.py


追跡されていないファイル:
  (use "git add <file>..." to include in what will be committed)

	new_folder/moved_file.py
	new_file.py

no changes added to commit (use "git add" and/or "git commit -a")
```

- この状態を想定して、まずはaddしていく
    - `$ git add moved_file.py`
    - `$ git add deleted_file.py`
    - `$ git add changed_file.py`
    - `$ git add new_folder/moved_file.py`
    - `$ git add new_file.py`
- `$ git status`でaddした後の状態を確認
    - それぞれがrenamed, modified, deleted, new fileとしてコミット予定の発射台に乗っていることを確認する

```console
shun@shun-VirtualBox:~/xxx/yyy$ git status
ブランチ new_branch_name

コミット予定の変更点:
  (use "git reset HEAD <file>..." to unstage)

	renamed:    moved_file.py -> new_folder/moved_file.py
	modified:   changed_file.py
	deleted:    deleted_file.py
	new file:   new_file.py

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)


追跡されていないファイル:
  (use "git add <file>..." to include in what will be committed)

no changes added to commit (use "git add" and/or "git commit -a")
```

- `$ git commit -m 'message'`でコミットを実行
    - messageは任意のコミットメッセージを入力


### 詰まりそうな点
- 間違えてaddして、取り消したい場合は`$ git reset HEAD added_file`を実行。`$ git reset HEAD`までは固定。renameの場合は、変更前のファイルと変更後のファイルに対して両方resetする必要がある
- 一括でadd取り消したい場合は`$ git reset HEAD`
- commit時にメッセージは必須で、-m以降を入力しないとvimが開いてしまう

## case4 : ローカルのブランチにコミットしたぞ！リモートブランチにも反映しよう！
### 手順
- `$ git push origin new_branch_name`
    - originは固定値
    - new_branch_nameはリモートに反映させたいブランチ名称
    - new_branch_nameがリモートにない場合は、新規に作られる

### 詰まりそうな点
- リモートに同一名称のブランチがない場合は、new_branch_nameが新規作成される

## case5 : 1つ1つaddするのめんどくさいから一括でaddしたい！
### 手順
- `$ git add -u`
    - トラッキング（バージョン管理）されているファイルについて、すべてaddされる
    - つまり、「削除されたファイル」、「変更されたファイル」はaddされ、「新規作成されたファイル」はaddされない

- `$ git add -A`
    - トラッキング（バージョン管理）されていないファイルも含めて、すべてaddされる
    - つまり、「削除されたファイル」、「変更されたファイル」、「新規作成されたファイル」がaddされる

- `$ git add .`
    - カレントディレクトリ以下に対して、`$git add -A`を実行する

## case6 : プルリクも承認されたし、不要ブランチを削除するぞ！

### 手順

まずはローカルのブランチから削除していく

- `% git branch`
    - まずは現在のブランチの状態を確認
    - developにマージが完了しており、updateDevelopを削除したいとする

```console
shun@shun-VirtualBox:~/workspace/global$ git branch
  develop
* updateDevelop
```

- `$ git checkout develop`
    - このままでは削除できないので、developブランチに移動する

マージが完了している場合

- `$ git branch --delete updateDevelop`
    - 不要ブランチを削除する

マージが完了していないが削除したい場合

- `$ git branch -D updateDevelop`
    - 不要ブランチを`マージをせずに`削除する
    - ※これまで反映したcommitは削除されるので注意

次にリモートブランチを削除する

- `% git branch --remote`
    - まずは現在のリモートのブランチの状態を確認
    - ローカルでは削除したupdateDevelopが残っている

 
```console
shun@shun-VirtualBox:~/workspace/global$ git branch --remote
  origin/HEAD -> origin/master
  origin/develop
  origin/updateDevelop
```

- `$ git push --delete origin updateDevelop`
    - 不要ブランチを削除する

もしくは以下のコマンドでも可能

- `$ git push origin :updateDevelop`

最終的なブランチの状態を確認する

- `$ git branch --all`

```console
shun@shun-VirtualBox:~/workspace/global$ git branch --all* develop
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/develop
```

## case7 : リモートブランチに反映された内容をローカルの同名ブランチにも反映させたい！

### 手順

現在のブランチの構成は以下の状態とし、リモートのdevelopに反映されたコミットをローカルdevelopにも反映させたいとします

```console
shun@shun-VirtualBox:~/workspace/global$ git branch -a
  master
　develop* 
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/develop
```

一発で反映させたい場合は、以下のコマンド

- `$ git pull origin develop`
    - origin（追跡ブランチ）に、リモートのdevelopを反映させる（フェッチ）
    - また、originからローカルのdevelopブランチに統合する（マージ）

上記の手順を別コマンドで行うと以下のようになる

- `$ git fetch origin develop`
    - origin（追跡ブランチ）に、リモートのdevelopを反映させる
- `$ git merge FETCH_HEAD`
    - originのFETCH_HEADからローカルのdevelopブランチに統合する

## case8 : やばい！間違えてリモートブランチにコミットしてしまったから戻したい！

### 手順

前のコミットに戻るのではなく、前のコミットに対する打消しコミットをします。ここで使うメインコマンドは、`revert`,`reset`です。

- `$ git fetch`
    - リモートのブランチの状態（間違えてプッシュした状態）をローカル追跡ブランチに反映させる

ローカルに、間違えてコミットしてしまったリモートのブランチと同一のブランチを作ります。同一名称の作業用ブランチを消している場合は、新規にリモートからチェックアウトしますが、同一名称の作業用ブランチを消していない場合は、リモートブランチをプルします。
※ただしローカルブランチにコミット以降触っていない場合は何もしない

- `$　git checkout -b work_branch origin/work_branch`
    - 同一名称のブランチをローカルから削除した場合

- `$ git pull origin work_branch`
    - 同一名称のブランチがローカルにある場合

- `$ git log`
    - 直前に行ったコミットIDを取得するために、ログを確認する


以下の`revert`もしくは`reset`のどちらかを実行する。

- `$ git revert <コミットID> --no-edit`
    - ローカルブランチに対して、先ほど行ったコミットIDを<commit>に指定し、revertコマンドを実施する
    - --no-editをつけない場合は、エディタが開き、打消しコミットのコミットメッセージを入力する

- `$ git reset --hard <コミットID>`
    - もしくはこちらで戻ることも可能
    - revertは打消しコミットをすることで前のコミットIDに戻ったように見えるが、resetは全てなかったことにしてくれる

- `$ git push origin work_branch`
    - ローカルブランチのコミットをrevert/resetした状態を、リモートにも反映させる

## case9 : 特定のファイルについて、commitのバージョン、ADDを取り消したい！

### 手順
コミット自体をさかのぼりたい場合は以下のコマンドを実行。
- `$ git reset --hard <コミットID>`
    - コミットの番号に戻る
- `$ git checkout <コミットID> <ファイルパス>`
    - コミットID時点のファイルを取り出す

ADDしただけで、コミットしていない場合は以下のコマンドを実行。
- `$ git reset HEAD .`
    - すべてのADDを取り消す場合
- `$ git reset HEAD XXXXXX`
    - ファイルXXXXXXのADDを取り消す場合

## case10 : Untracked filesを削除したい！

`$ git status`の結果、新規作成ファイルやフォルダが増えていて「Untracked files」と表示された場合、addして新規ファイルとしてtrackするか、不要のため削除するか考えることになる。今回は、削除する場合の手順について記載する。

### 手順
- `$ git clean -n`
    - cleanコマンドを実施した場合に、削除されるuntracked filesの一覧が表示される
    - ディレクトリも対象の場合は`$ git clean -nd`

- `$ git clean -f`
    - untracked filesが削除される
    - ディレクトリも対象の場合は`$ git clean -fd`


続く