機能だけで覚える基本的なGitコマンド　〜ほぼほぼ作業順〜　

#Gitコマンド(作業順覚書)
前提として、

- GitHubのアカウント作成済み
- sshKeyを登録済み
- git version 2.16.3

であること。

ちなみに、概念と共にコマンドを知る記事も書いてみたので、よろしければご覧ください。
[git概念と共に覚えていくgitコマンド
](https://qiita.com/Nedward/items/afeab9fe9f88e6956af5)


## Gitに最初にプロジェクトを上げるまで編

### git init
gitの管理下に置きたいファイルの中にいる状態で、このコマンドを使って、gitファイルを作る

```terminal
$ git init
```

### git add
　ファイルやディレクトリをインデックスに追加するために使うコマンド。　追加する時はファイル名やディレクトリ名を直接指定できる他に、*を使いワイルドカードで複数対象を指定することもできるが、大抵は、ステージングしたいものは全部だし、gitにあげたくないものは、git ignoreするので、大抵、全指定を意味するピリオド「.」を使う。


　 <font color="Red">**-p**</font>オプションを使うと同一ファイル内の変更を更に分割してコミットすることができる。細かくコミットメッセージを分けてやったことを記録しておくことは自身のやったことを後から追跡することにも役立ちますし、レビューしてくれる人への見やすさもグッとよくなります。使い方がちょっと特殊ですが、３つの選択肢だけ覚えておけば、そんなに難しくもなく使えます。
　 <font color="Red">**-p**</font>でaddすると、下記のような表示が出ます。いっぱいありますが、基本的に使うのは**s**と**y**と**n**です。
　**s**を押すことで、コードブロックを細分化してくれます。細分化していきコミットしたい部分まで細分化されたらyを押します。そうするとその細分化したところだけがstageに上がります。そして細分化した次のコードブロックに移動するので、そのコードブロックを入れたければ同じようにy、もしくは入れたくなければ、**n**を押します。nを押すことでstageに上がらなくなります。そうしてstageに上げるものとあげないものをyとnで選別しながら（n/n）になるまで繰り返します。そうして終わった時点でcommitし、pushするとyと選択肢た部分だけがリモートブランチに飛んでくれます。

```console
$ (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? s
$ (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y
$ (2/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? n
```

```console
$ git add .
$ git add パス名/ファイル名
$ git add *.拡張子
$ git add -p パス名/ファイル名
```

### git status
　リポジトリの状態を確認するために使うコマンド。現在のブランチの名称や、追加・変更されたファイルやディレクトリの一覧を表示。これで、ステージングされているファイルを確認できる。AWSの秘密鍵とかが書かれてるenvファイルとかリモートリポジトリにあげたらやばいのが入ってないかを確認する。

```terminal
$ git status
```

### git diff
　gitのコミット前のコードとの変更点を見ることができる。git diff 変更したファイル名を入力すれば、差分を見ることができる。

```terminal
$ git diff
```

### git commit
　変更したソースコードと、変更前のソースコードとの差分を表示する。-m''のオプションを使うと、そこに直接コミットメッセージが書けるが、説明が長くなりそうなら、何も打たずにエンターして、vimが立ちがあるので、そこに書いてコミットする。
--amendオプションをつければ、直前のコミットメッセージを修正することができる。

```terminal
$ git commit
$ git commit -m 'コミットメッセージ'
$ git commit --amend -m '修正したコミットメッセージ'
```

### git push
　ローカルリポジトリにあるファイルからリモートリポジトリへと移動する作業を行う。該当ブランチへ変更したファイルを流す。ブランチ名を指定してやれば、そこにプッシュされ、何も書かなければ、今いるブランチにプッシュされる。送り先のブランチは機能ごとに別れているので絶対に間違えない様にすること。ブランチについては、後述。

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

これで一先ず、１回目のgitまで行ける。そして、２回目以降のGitでの作業は、git addから始まり、git pushに終わる。これの繰り返しである。

## Gitブランチを変更する編
　開発をしている中で、機能ごとにブランチを分けて作業するのは、非常に大事。ブランチで分けることで、masterには綺麗な作り終えたプロダクトだけが残るようになるからである。

### git branch
　ブランチに対して各種操作を行うために使うコマンド。下記のように使う。現在使用しているブランチを示すのは、✳︎で示される。
カレントのブランチを削除する時は、別のブランチに移動して、対象のブランチを削除するようにする。

```terminal
$ git branch              ## ローカルブランチ一覧
$ git branch –d ブランチ名  ## ブランチの削除
$ git branch -r           ## リモートブランチ一覧
$ git checkout -b ローカルリモートブランチ名 origin/git側のリモートブランチ名 ##master以外の別のブランチをcloneする方法
$ git branch -v           ## 各ブランチの先頭コミットIDとメッセージを表示
$ git branch -vv          ## 追跡リモートブランチの名前表示
$ git branch -m 古いブランチ名 新しくつけたいブランチ名 ##ブランチのリネーム
```

### git switch
こちらcheckoutでブランチを作成したり切り替えを行っていたわけですが、restoreコマンドに続き、機能分化が行われたようです。これからはこちらのコマンドでブランチの作成及び、切り替えをした方がいいです。

```terminal
# ブランチの切り替え
$ git switch 切り替えたいブランチ名

# ブランチを新規作成して切り替え
$ git switch -c 新しいブランチ名
```

一番下にある元に戻すcheckoutのコマンドはgit restoreでやる方が良い。

### git checkout
元々はgit switchやgit restoreが持っていた機能をこのコマンド１つに集約されていたが、複合的なコマンドになりすぎていたため、能力が分化されることになった。　故に、現時点でcheckoutコマンドを使用する場面は、リモートのブランチでローカルには存在しないブランチを持ってくる時に限定されると推測される。

```terminal
リモートにあるブランチを確認し、欲しいリモートブランチを探す
$ git branch -a

下記コマンドを打てば、リモートブランチをローカルブランチとして引っ張ってこれる。また自動で作成したブランチに切り替わる
$ git checkout -b ローカルブランチ　origin/リモートブランチ
```

## Gitのリモートリポジトリから、ローカルにプロジェクトを持ってくる時編

### git clone
　既存のリモートリポジトリをローカルに落とすために使うコマンド。
例えば、GitHubに公開されているリポジトリを自分のPCへ落とすときに使う。

```terminal
$ git clone URL
```

### git pull
　リモートブランチの変更を取り込むために使うコマンド。リモートリポジトリにあるブランチ名を選択して、プロダクトをローカル落としてくる事ができる。pullはfetchとmergeの合わせ技であり、仕組みを理解せずに使っていると、コンフリクトした時などの対応が原因不明だけどgit pullしたらなんとかなった状態になるので、仕組みをしっかり理解する。

```terminal
$ git pull origin ブランチ名
```
これが出来れば、チーム開発においてとりあえずは、安心出来る。特にプッシュする際のブランチ確認は、気をつけること。

git pullに関しては、git fetchとgit mergeの混合技で、場面によって使い分けが必要です。詳しくはこちらの記事のgit pullとgit fetch.git mergeのセットの見出し部分をご覧ください。

[git概念と共に覚えていくgitコマンド
](https://qiita.com/Nedward/items/afeab9fe9f88e6956af5)

## ローカルブランチに必要な作業ブランチが欲しい時編
fetchすればremoteブランチを全部最新にしてくれます。その後に、欲しいリモートブランチ名を指定して、ローカルブランチを新しく指定してpullすることで最新の作業ブランチを引っ張ってくることができる。

使い所としては、例えば既存プロダクトにジョインした時のdevelopブランチが欲しい場合等に使います。リモートのdevelopブランチをローカルのdevelopブランチとして新しくブランチを作成してくれます。:を入れてブランチ名を書くことで新しくブランチを作ってくれるので　`swtich -c` は不要。

```terminal
$ git fetch
$ git pull origin リモートブランチ名:ローカルブランチ名

使用例:
$ git pull origin develop:develop
```

今後、チーム開発する時は作業ブランチの最新にする習慣が必要になってくると思いますので、関連記事は下記です。
[作業ブランチを最新に更新する方法](https://qiita.com/Nedward/items/7a5e20eb89fa0bf12dec)


## 差分を見たい時編
単純にリモートのファイルとローカルのファイルの差分を見たい時

```terminal
$ git diff
```

ブランチ上の差分を見たい時

```terminal
$ git fetch
$ git diff origin/ブランチ名 origin/ブランチ名
```


## Gitでやらかした時編

### git reset
　ローカルリポジトリのコミットを取り消すために使うコマンド。間違えてコミットしたり、修正漏れがあったときによく使う。gitのシステムは、working space、index、HEADの3種類の段階があります。

**但しhardオプションをつけたresetだけは慎重に！！！**

- working spaceは、ファイルが変更されているだけの状態
- indexは、addされている状態
- HEADは、作業ブランチ上の最新のコミット状態である。

いずれもまだローカルリポジトリ状の話であることだけは忘れないようにしたい。コマンドでは、この三つの状態をそれぞれオプションをつけて取り消していける。

- hardは、working space、index、HEADの全てを取消し
- mixedは、indexとHEADを取り消し
- softが、HEADだけを取り消し

つまり、hardはファイルの変更そのものまで消してしまい、mixedは、commitとaddコマンド両方の実行結果を打ち消し、softは、addコマンドだけの実行結果を打ち消す。

一番危ないのはhardオプション。working spaceの内容まで取り消すので、**せっかく書いた変更点を丸ごと吹っ飛ばします。** 差分管理をするgitがこのオプションでは、差分を無視して上書きを実行する点が脅威です。
コミットしたHEADも消されてしまうことも考えるとログにも残らないし、diffも無くなるので、実質、その変更点に至ってはバックする術が無くなりますので使用する際は注意が必要です。

--hard オプションをつけた後にcommitIDとなっているハッシュ値をつけるとそこまでプロダクト全体を巻き戻してくれる。開発中に何か別の場所が壊れた時にその壊れた箇所を発見する時に役立つ。こまめにpushしておくとよりこの恩恵を受けることができるようになるので区切りがついたらpushしておくようにしておく習慣をつけるとgoodです。

```terminal
$ git reset --hard
$ git reset --mixed
$ git reset --soft == git reset HEADと同義。git addを取り消すコマンドになる。
$ git reset --hard commitID
```

### git restore
このコマンドはgit checkoutが様々な機能を持ちすぎているために、その能力を分割するために作られたもの。git checkout ファイル名でリセット可能な能力はこのコマンドに引き継がれています。
間違えてステージにあげちゃった場合、git側から推奨されるコマンドとしてこのコマンドがあげられる。コミットしたものがある場合のgit statusを行うと、変更ファイルを表示するより先に

```terminal
$ git status
  (use "git restore --staged <file>..." to unstage)
```

というのが出てきます。これはgit reset --softと同等の効果を得られます。Gitが推奨しているコマンドがこっちなので、これからはこちらを利用するといいかもしれません。

```terminal
$ git restore --staged ファイル名
```

また、なんのオプションもつけないことによって、git checkoutと同等の効果を持ちます。つまり **編集したファイルを引数に取って実行すると、編集前のファイルへ元に戻してれくる機能** です。デバッグしまくった後とか便利ですね。

```terminal
$ git restore ファイル名
```

## 動作確認編
チーム開発している時に、他の人が作ったプルリクの内容を手元で動作確認したい時に使うコマンドです。
IDとしていることろは、プルリクエストを作成した時に上で作られるプルリクエストでグレーアウトしている#から始まる数字のことです。

###  git fetch orign pull/id/head:ブランチ名

```terminal
$ git fetch origin pull/ID/head:ブランチ名

ex) 
$ git fetch origin pull/114514/head:pr-114514
```

こちらはプルリクがmainにマージされた時に自分の作業ブランチを更新する時の手順です。
[作業ブランチを最新に更新する方法](https://qiita.com/Nedward/items/7a5e20eb89fa0bf12dec)

## ログを途切れさせない編
### git mv
ファイルリネームさせるgitコマンドです。
mvコマンドでリネームを行うと、別のファイルとして扱われるため、それまで記録し続けてきたログがその時点で途切れるので、ログをキープしながらリネームするためのコマンドになります。

```terminal
$ git mv リネームしたいファイルやディレクトリ リネーム名
```

## 作業途中からgit管理から外したくなった時の対応
　色々ファイルを触っていくうちに、途中で特定のファイルをセキュアにしたいので、git管理から外したくなることがあると思います。筆者はある程度のアプリのレイアウトを作った後に、後発でバックエンドを触った時、database.ymlに直接mysqlのパスワードを書いたので、git管理から外す必要がありました。

```terminal
$ git rm --cached ファイル名
```

これを行うと、ファイル名のトラックしていたキャッシュが削除されるので、git statusコマンドを打つと、

```terminal
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	deleted:    config/database.yml
```

こんな風にdeletedされた状態になります。これをプッシュしてあげると、そのファイルが追われなくなります。その後に、.gitignoreにコミットできないように記述してあげれば、OKです。

# github上に作った空のリモートリポジトリへプロダクトを最初にpushする手順
masterからmainになっただけの話なんですが、一応。

とりあえず、push前まで作業する。

```terminal
$ git status
$ git add .
$ git commit -m "First Commit"
$ git branch -M main
```

ローカルブランチのmainができたことを確認

```terminal
$ git branch
```
初pushします。
-uオプションをつけるとローカルリポジトリの現在のブランチの上流をorigin main に規定したことになり、次回からgit pushだけで上記のコマンドと同じことを実施できる。また、git pullだけでもgit pull origin mainと同じ意味になる。

```terminal
$ git push -u origin main
```

## 既存のディレクトリに対して初めてプッシュする時のエラー対処法
既存のディレクトリに対して、初めてプッシュを行う時のコマンドは

```terminal
$ git remote add origin git@github.com:XXX/XXXXX
$ git branch -M main
$ git push -u origin main
```

だが、git push -u origin main時にエラーを出す時がある。原因不明。
下記のような意味不明なエラーを出す。特に何もしていないのに、正真正銘、最初のpushなのに、何故か失敗する。

```terminal
$ git push -u origin main
error: src refspec main does not match any
error: failed to push some refs to 'github.com:XXX/XXXXXXX'
```

そんな時は下記で解決できる。要は、自分でmainブランチを作ってからmainにpushすればいい。

```terminal
$ git switch -c main
$ git add .
$ git commit -m 'First Commit'
$ git push origin main
```

## おまけ
gitで草を生やすには.gitconfigに設定として、ユーザー名とアカウントに登録してあるメールアドレスを書いとく必要があるのですよ。

```terminal
$ git config --global user.name "user_name"
$ git config --global user.email "e-mail"
```
ダブルクォーテーションを使って文字列扱いで引数をとります。これでコミットしたりissueを立てたりしたら草を生やせるようになります。

以上、gitのほぼほぼ手順通りの覚え書き。間違いがあれば、ご指摘お願いします。