git演習　これだけできればそこそこいけると思う！

#はじめに
復習がてら殴り書きしました。
最後の方までできれば指摘くらっても自分で修正していけるかと！
#実践
##gitの始め方
### 名前とアドレス登録
```sh
$ git config --global user.name "ユーザー名"
$ git config --global user.email メールアドレス
```
### リモートリポジトリとローカルリポジトリ紐づけ
主に2通り。

1. githubに作られているリモートリポジトリをクローン  
もうすでにリモート上にファイルがある場合はクローンでとりこも  

```sh
$ git clone URL
```
２. ローカルリポジトリとリモートリポジトリを紐づける。
　  ローカルのファイルから始めていく場合

```sh
#ローカルのフォルダ内にgitファイル生成
$ git init
#ローカルリポジトリとリモートリポジトリ紐づけ
$ git remote add origin URL
```

これでとりあえずローカルリポジトリとリモートリポジトリが繋がった状態。

### 一番最初にファイルを作ったらmasterでcommitしよ
gitファイルだけ作って真っ新な状態でブランチを切ろうとすると  

```sh
fatal: Not a valid object name: 'master'.
```

というエラーになる。
幹がないと枝はなりませんわな。
なので、ファイルを作ってまずは**master**でcommitしよ！
## 基本的な流れ

- ワークツリー  
編集したファイルをgitが検知してくれ自動的に編集したファイルだけを保管してくれてるところ  

↓↓↓ **add**  

- インデックス  
addしてワークツリーの中からコミットしたいファイルが入るところ  
タスクごとにコミットしたいので、コミットしたいファイルだけaddするように。

↓↓↓ **commit**

- リポジトリ


### git add
インデックスに追加  

```sh
$ git add . //編集した全てのファイルの場合
$ git add ファイル名
```
### git status
現在の状態を表示

```sh
$ git status

On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   test.rb      #addしたファイル(インデックス)

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test1.rb　　　　　　　　  #編集中のファイル(ワークツリー)
```
### git reset
インデックスに入れたファイルをワークツリーに戻す

```sh
$ git reset #インデックス内のファイルを全部ワークツリーへ戻す（addのときみたいに.はいらない）
$ git reset ファイル名
```
### git commit
```sh
#vim出てくるやつ
$ git commit
#メッセージ付き
$ git commit -m "メッセージ"
```
コミットしたログを見る

```sh
$ git log
#これハッシュ値も短くなる
$ git log --oneline
```
### ブランチ
```sh
#ブランチ一覧
$ git branch
#ブランチ作成
$ git branch test_branch
# ブランチ作成 + 切り替え
$ git switch -c ブランチ名
#ブランチ名変更
$ git branch -m 古いブランチ名 新しいブランチ名
#ブランチ削除
$ git branch -d ブランチ名
```
### git push
ローカルリポジトリでコミットした内容をリモートリポジトリに送信。 

```sh
$ git push origin HEAD
```

### ローカルリポジトリを最新にする。

```sh
#fetch + marge = pull
$ git pull origin HEAD
#コミット情報だけ最新
$ git fetch
#ファイル上書き
$ git merge origin/master
```
`pull`したあとに`marge`だけリセットする

```sh
$ git merge --abort
```
## やっちまった
### 直前のコミットを修正する
```sh
$ git commit --amend
#メッセージの修正だけならこれでいいし、
#ファイル修正したらaddしてからしたらその編集も乗る。
```
### すでにpushしたコミットを修正してもっかいpushしたい
そのままpushしてもリモートリポジトリとローカルリポジトリが違うからエラーになる。forceオプションを使って強制的にpushする。（結構危険）

```sh
$ git push -f origin HEAD
```
### commitをリセット
```sh
#編集したファイルはそのままでaddする前(ワークツリー)に戻す
$ git reset --mixed HEAD^
#編集したファイルはそのままでaddした後(インデックス)に戻す
$ git reset --soft HEAD^
#編集したファイルを編集前に戻す(なかったことにする)
#新規にファイル作ってた場合はファイルがなくなる
$ git reset --hard HEAD^
#ハッシュ値指定
$ git reset --soft 7a7b8a0f6f73c2951278c02eb20d820cbb1621e2~
#git log --onelineの短いハッシュ値の方でも使える！
```
`HEAD^`、`HEAD~1`は直前  
`HEAD~2`は直前の一つ前  
ハッシュ値を指定したい場合は`ハッシュ値~`最後の波線忘れないこと。  
ただし2つ目とか3つ目のやつを指定するとそれより新しいコミットは**全部リセット**される。
## cherry-pick
他のブランチにコミットをコピーする。

```sh
$ git switch -c ブランチ名
$ git cherry-pick コミットハッシュ値
```
ローカルリポジトリにコミット情報がないコミットはコピーできないので、`git fetch`を使って最新のコミット情報をリモートリポジトリからとってきてからコピーする。  
ローカルで自分が作ったブランチでコミットしたのを別ブランチ作ってcherry-pickしようとしたとき最初に作ったブランチと競合してしまうので`git commit --allow-empty`しろって出てくる。  
意味わからんってなったときは、`git cherry-pick --quit`をすればcherry-pickは一旦とまる。
## rebase
```sh
#git log --onelineの短いハッシュ値も使えるよ
$ git rebase -i コミットハッシュ値
```
指定したコミットより新しいコミットを編集するようになる。

```
481bad777ee0f9a0132e19eb61c42f1bd04d5707

34af8ad7b887eb96274c9e97f727e3e0e39bf391 ↑ここから上が修正対象

d535f26c5fecb718a3448b9eaeba232933e2b121 ←これをrebaseしたら
```
```sh
#これなら３つとも編集できるよ！
$ git rebase -i HEAD~3
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399745/cebc7d49-2fb6-0262-b0b7-d9e64e00b8e4.png)
なんかVScodeで直感的にできるようになっとる；
vimのときと並び方が逆やな。。。

```
1 pick 34af8ad create test7.rb
2 pick 481bad7 create test8.rb
```
vimではこんな感じで表示されるはず。  
### pick
何も編集しない状態。  
`p`という風に省略可。  
### fixup
`f`  
一つ古いコミットと統合する。  
**古い方のコミットメッセージが適用される。**
### squash
`s`  
fixupと同じように統合される。  
両方のコミットメッセージ参照され、vimでコミットメッセージの修正画面が表示される。
### drop
`d`
コミットを削除する。
一時的に作成したりcherry-pickしたコミットを削除したりする。
### コミットの順序入れ替え
VScodeなら直感的にドラッグで入れ替えればできてしまう。
vimの場合はコピペして入れ替えるだけ。
```
1 pick 34af8ad create test7.rb
2 pick 481bad7 create test8.rb

1 pick 481bad7 create test8.rb
2 pick 34af8ad create test7.rb
```
vimの操作は、ddで行切り取り、pでペースト
### reword
`r`
コミットメッセージ編集
# まとめ
インプット → 実践 → qiitaや自分用のmarkdownメモにまとめる。
この学習方法がぼくの中では最強なので、学習フェーズは急がず焦らず。
学習をやっつけ仕事にするのはヤバいので。。。
gitの一番の学習方法は自分でどうしようもなくぶっ壊して自分で元に戻すです。