Git勉強会 入門

# ゴール & 目的
- 業務でGitを使っているがそこまでコマンドを知らない人や、これからGitを使っていきたいから少し調べ始めた人向け。
- 今後業務に役立って欲しい。

# アジェンダ

- はじめに
- Gitとは
- 覚えて欲しいコマンド
- Git特徴
- Gitの開発フロー
- コミットルール
- できればやって欲しくないこと。
- Gitlab
- 終わりに

# はじめに
Gitは開発でなくてはならない存在になっている。
これらを理解することがエンジニアでは必須事項なので覚えて欲しい。
既に業務で使っているため、基礎の基礎は割愛してポイントを絞った勉強会になっています。
ただ、基礎の基礎で不明点があれば、是非とも質問して欲しいです！

# Gitとは
<img width="225" alt="Git-Logo-2Color.png" src="https://git-scm.com/images/logos/downloads/Git-Logo-2Color.png">

プログラムのソースコードのバージョン管理システムです。
Linuxカーネルの産みの親であるリーナス・トーバルズがGitを作りました。（神）

バージョン管理システムはCVSやSVNなど昔からあり、SVNが大変便利でした。
ただ、複数人対応する際にマージ祭りが多く大変でしたが、
ちょうどそれら問題を解決が得意なGitが広く使われるようになり、今の主流になりました。

# 覚えて欲しいコマンド
長い説明を色々語りたいところですが、単刀直入に以下のコマンドを覚えてくれれば問題ありません。

#### 1. 最新状態を取ってくる＆不要なブランチ情報を削除
```
git pull --prune
```
> ブランチを最新化するコマンドだが、pruneを追加することで、リモートブランチで削除されたブランチを削除することができる。
> ローカルに色々ごちゃごちゃ溜まっている人がいると思うので、実行していない人がいたら是非一回実行してみてください。スッキリします。

#### 2. 今までの変更を全て差し戻す
```
git checkout .
```
> コミット前限定で、修正をなかったことにしたい場合。
> 「.」をファイル指定することで、ファイル単位で差し戻すことが可能。

#### 3. git管理外のファイルを全て削除したい
```
git clean -dn #削除対象を表示する
git clean -df #削除を実施する
```
> 検証用でいらないくなったファイルやディレクトリを一括で削除したい場合便利
> 今は必要なさそう？と思いますが、必要な時がきます。

#### 4. ファイルをリネームしたい。
```
git mv hoge.txt fuga.txt
```
> 普通にmvでファイル名をリネームしたり移動したりすると、gitからは削除された扱いになり、変更履歴が消滅してしまう。
> git mvすることで、変更履歴を引き継いだ状態になるので、これは是非とも覚えて欲しいです。
> 似たようなコマンドでgit rmがありますがこれは特に使わなくてもOK。

#### 5. 直前のコミットや何らかの作業を無かった事にする（変更状態も削除。）
```
git reset --hard HEAD^
```
> push前限定で、コミットやマージ作業を無かったことにしたい場合。
> 「^」の個数分、何個前に戻るか決めれる。3つ戻りたい場合は「HEAD^^^」
> 何かやらかしたか！？と思ったらこれを使えばなかったことになります。

#### 6. 直前のコミットや何らかの作業を差し戻す。（変更状態は残る。）
```
git reset --soft HEAD^
```
> hardだとコミットした変更までも消えてしまうので、それが嫌ならsoftを使いましょう。
> hardとsoftの違いがいまいちわからない人はsoftを使った方が良いかもしれないです。

#### 7. 指定のブランチの最新状態を今のブランチに取り込む。(originを忘れないで)
```
git pull --prune
git merge origin/<branch>
```
または
```
git pull origin <branch>
```
> 上のコマンドと下のコマンドはいずれもマージの挙動が同じだが、マージの履歴の残り方が若干が違います。
> 「git pull origin <branch>」するとスッキリした履歴になるが、
> どこからマージしたのかちゃんと残したい場合、上のコマンドでやった方が精神衛生上良い。
> ##### 上のコマンドにある「origin/」について
> リモートブランチを指しているので、pull後にoriginを指定すると必ず最新版になる。もしoriginを付けなかった場合は、自分のローカルブランチの状態を取り込むことになるので、古い可能性が出てくる。


#### 8. ログをもう少しよく見たい
```
git log --graph --oneline
```
> ログ表示をグラフィカルにしたい場合に使うが、基本的にgitlabのgraphページやvscodeのgit historyの拡張でも十分だったりします。

#### 9. 途中まで変更した内容を一時的に退避したい
```
git stash
```
> 急な作業が入り、ブランチを切り替えたい場合があるが、コミットしたくない。困った。。という場合に使う。
> ##### 退避したものを復元
> ```
> git stash list
> git stash apply <number>
> ```
> または
>
> ```
> git stash pop　※適用と当時にstash情報が削除されます。
> ```
>
> ##### その他
> stashが難しい場合は、コミットしても良いと思います。
> その際に下記のオプションをつけると、前回コミットした内容を修正することができます。
>
> ```
> git commit --amend
> ```
> つまり、amendコマンドで何回コミットしても、コミットは一つのままです。

## やって欲しい設定
```
git config --global --add merge.ff false
git config --global --add pull.ff only
```
筆者はrebaseなどの歴史改変や、merge時のfast-forwardを使わない(使いこなせない)のもありますが、
まずGitを始める人は自分がどこからどこへマージしているかをキチンと把握できるまでは、この設定をした方が良いかと思います。
詳細は下記の記事を参照していただければと思います。

https://qiita.com/nog/items/c79469afbf3e632f10a1

# Git特徴
- リモートリポジトリ、ローカルリポジトリという概念がある。
- ブランチを切る、ブランチをマージなどが得意であり、複数人が同時に作業することを想定した設計
- Gitlab/Githubのようなサイトがある
    - これらは素のGitが裏で走っているが、それに追加機能としてGUIやissue、MRなどの認証機能をつけたものと解釈してOK。
- ***またGitですが、ありとあらゆるコマンドが用意されているため、考え付かないような操作をすることができる。***
    - **ここがポイント**で、なんでも出来る＝好き勝手すると崩壊する危険性を伴っています。

**つまりGitは使いやす過ぎる故、十人十色の運用方法があるため、運用が破綻する前にチーム内や部署でルールを決めていく必要がある。**

# Gitの開発フロー
如何様にも運用できてしまうGitはルールがないと本当に死んでしまいますので、過去の先人たちが考えまくりました。
そこで出た開発フローを軽めに紹介します。

**複数人で開発する際に特にこだわりがなければ、いずれかの開発フローに従ってみて、
その後、チームにあった方法に改良していくことをお勧めします。**

## Git-flow
<img width="650" alt="image.png" src="https://camo.qiitausercontent.com/bbb6ba70f058f0d10c8f7a769ae8fd089dc7684e/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f35333330392f30363134303132312d613062362d343237662d633134392d3638353863313439373338652e706e67">

ヴィンセントさんが考案したものです。こちらの記事が役に立ちます。

https://qiita.com/homhom44/items/9f13c646fa2619ae63d0

個人的にこれが一番しっくり来ています。
ブランチがそれぞれ意味を持たせて運用しているので、縦割りの関係でわかりやすいです。
必要なブランチが多いですが、それぞれ必要な理由がわかれば、簡単に受け入れることができると思います。

master：本番環境にあるソースコードで、テストがされているもの
develop：開発中のメインブランチ
hotfix/hoge：本番で不具合があったときに作成される一時的なブランチ
feature/fuga：新規機能やタスクをする際に作成するブランチ

補足：feature/のようにスラッシュ区切りでブランチ名を作成すると、gitとしてはフォルダのような区切りとして扱われます。

```
feature/
  fuga
  piyo
```

Git-flowですが、2つのブランチに対してマージする工程が少し面倒な箇所があります。
ですが、ちゃんとコマンドが用意されていたり、SourceTreeの機能になっていたりしているので、簡単にフォローできたりしますので、
気軽に試してみてください。

https://danielkummer.github.io/git-flow-cheatsheet/index.ja_JP.html

## gitlab-flow & github-flow
GitlabのMRや、GithubのPRを活用した開発フローもあります。
今はこちらの方が主流になっているかと思うので、こちらにも目を通していきます。

https://qiita.com/pandama09396862/items/9f013fa7b60f4d12d1d8

## コミットルール
コミットする際のルールも整えていく必要があります。
コミットの粒度や内容によって、Gitの履歴が大変見辛くなりますので、大変でしょうが覚えて欲しいです。

https://qiita.com/itosho/items/9565c6ad2ffc24c09364

これらを意識すると少しだけ恩恵もあったりします。
例えば、二行目を空けてコミットするなどをすると、
GitlabやGithubのコミット画面で詳細を見る「・・・」ボタンが表示されたりします。

## できればやって欲しくないこと。
※ここで述べていることは、現場によって大きく異なる部分です。
流派の違いもあるので、一例と思ってください。

- rebase、git pull origin masterなどの fast-forward関連。
    - git pullのみはOK
- force push

歴史改変するコマンドはメリットデメリットが多いです。
証跡を残して仕事する場合チームだと、おすすめしません。

### どうしてもrebaseがしたいのであれば、、、
- 一度もpushしていないローカルブランチなら、rebaseやsquashなどなんでもOK
- push後、MRを出す前にrebaseやsquashを行い、乱雑な履歴をクリーンアップする。
- MRを出した後はrebase禁止。


## Gitlab
- MRする際の小技としてissueを紐付けてクローズする方法が2つほど、あります。
    - MRの本文に、closes #123 とclosesの単語とクローズしたいissue番号をつける
    - コミットの文章にcloses #123をつける。
        - closes #123 #124 と複数書くことや
        - fixed #123 #124と書くこともできたりします。
            - https://www.codelab.jp/blog/?p=2289

## 終わりに
いかがだったでしょうか。
Gitの表面を説明したのみで、まだまだGitは深いです。
分からないことがあれば、いつでも聞いてください！
ご清聴ありがとうございました！！

## その他、 リンク
ここのブログが分かりやすかったので、興味があれば、色々みてみてください。

https://kray.jp/blog/git-why-explanation/
https://kray.jp/blog/git-pull-rebase/