【Git】【初心者】「git pull」ってのを魔法の言葉だと思っていたよ、私は。

# この記事で分かること
- git fetch, merge, pull の使い方・挙動の概要
- ユースケース
- 付録
  - git 周りでよく聞くブランチ名
  - アップストリームブランチの指定方法（他記事リンク）
  - 筆者の失敗談「ソースの最新化ってgit pullしてれば良いんじゃないの⁉」

# 初めに
こんにちは、新人エンジニアをやっている者です。
先日、業務中に自分だけ開発環境が動かないというトラブルが起こり、それが **「ソースの最新化」ができていなかっただけ** という初歩的なミスがトリガーになっていたために方々にお手数をおかけしてしまいました…
あくまで自分の不徳の致すところではあるのですが、新人の方は陥りそうな落とし穴かとも思ったので、自戒の念をこめて記事に残そうと思います。

# 前提
- **「git って何？」** といった本当に基礎的なことは本記事では扱いません。
- ローカルにリモートリポジトリのソースをクローンする手順も取り扱いません、ご了承ください。


# fetch, merge, pull の仕様・使い方
今回挙げる3種類のコマンドはいずれも**リモートリポジトリの状態をローカルに反映させる**ために扱うものになります。大人数での開発をしている方は手元のソースを定期的に最新化したいなんてこともあるのではないでしょうか…！
早速、それぞれの違いについてみていきましょう！


### git fetch
使用例
```bash
$ git fetch
```
- リモートの最新情報をローカルに持ってきます。この```fetch```コマンドではあくまで**持ってくる**だけというイメージです。
    - 正確にはリモートのmainブランチから、リモートとローカルの間にある「origin/main」というブランチに最新情報を持ってきています。ローカルのソースに反映させるには次で紹介する```merge```というコマンドが別途必要になります。
    - (origin,main等のブランチに関しては記事末尾で付録として簡単にまとめます)

### git merge
使用例
```bash
$ git merge main  // mainブランチの情報を反映
```
- 引数（mergeの後ろ）で指定したブランチの情報を**今いる作業中のブランチに反映**させます。
- fetchで持ってきた情報を**反映させる**イメージです。


### git pull
使用例
```bash
$ git pull origin main
```
- 今いる作業中のブランチにリモートリポジトリの情報を反映させます。
  - 引数を指定せず、```git pull```だけで実行した場合、作業中のブランチと関連付けられているブランチ（アップストリームブランチ）の情報を取得し、反映されます。
    - アップストリームブランチについては```$ git branch -vv```コマンドで確認できます。
    - 設定方法については付録に掲載した別記事をご参照ください🙇
- 内部的には ```git fetch``` と ```git merge``` を同時に行っています。



# ユースケース（使用例）
ここではローカルのソース最新化というケースを想定して手順を紹介します。
あくまで情報を取得するルートが異なるだけで、最終的な結果は同じになりそうです。

### 共用のリモートリポジトリの最新情報をローカルに反映させたい
###### 状況設定
- 共同開発用のリモートリポジトリがある
- ローカルでは自分だけの作業ブランチを作成し、普段はそこで作業をしている

###### ソースの最新化方法①
1. ```$ git switch (ブランチ名)```などを使い、最新化したい作業ブランチに移動
1. 手元で変更がある場合、```$ git stash```でその変更を一時退避（後で戻します）
1. ```$ git fetch``` でリモートリポジトリの情報を取得
1. ```$ git merge origin main``` で今いる作業中のブランチに持ってきた情報を反映
1. ```$ git stash pop``` で退避していた手元の変更を再度反映
1. （ここでコンフリクトが起こる場合アリ…その場合はVSCodeのマージエディターなどで解消…）
1. 完了！

:::note warn
###### git stash の話
```$ git stash```をするかどうかは正直好みの問題かとも思っています（結局戻すときにコンフリクトは起こるし…）。筆者は修正が何かの間違いで上書きされるのを予防するという意味で毎回やっています。
:::

###### ソースの最新化方法②
1. 最新化したい作業ブランチに移動
1. ```$ git pull``` でローカルのmainブランチを最新化
1. ```$ git merge main``` で今いる作業中のブランチにmainブランチの情報を反映
1. 完了！

# 終わりに
今回はgit fetch, merge, pullをテーマにリモートリポジトリの情報を取得する手順について取り上げました。
大人数での大規模開発に欠かせないGit。とにかく奥が深いですね…今後も勉強していこうと思います。

ありがとうございました！

 
# 付録
### ・ git のよく聞くブランチ
| ブランチ種類 | 説明 |
|:-:|:-:|
| origin | githubでソースが置いてある場所（≒ローカルリポジトリ）を指す名前 |
| main | 旧```master```ブランチのこと。あくまでデフォルトでつけられたブランチの名前ことで、ローカルにもリモートにもある。  |
| origin/main | ローカル側にあり、リモートのmainブランチを追跡しているブランチ  |

### ・ アップストリームブランチの設定方法
参考記事 https://www.delftstack.com/ja/howto/git/set-upstream-in-git/



--- こっから下は雑談 ---





# おまけ失敗談「ソースの最新化ってgit pullしてれば良いんじゃないの⁉」
記事を書くきっかけにもなった失敗談です。

一日前まで動いていたローカルでの開発環境が急に起動しなくなってしまいました。
「ソースは定期的に最新化しているし、起動に影響あるような変なアプリも入れてないし…」と若輩エンジニアの私は狼狽してしまいました。
先輩に「開発環境起動しなくなっちゃいました…またなんか俺やっちゃいましたかね…」とペアプロを申し込んだところそれらしき原因は見当たらず…「VPNはちゃんと接続してる？」「もしかしたらeclipseダウンロードしなおしか…？」などだいぶお時間を頂きました。そんな中、以下のような会話に。

```
先輩「ブランチっていつ切りました？」
筆者「一か月以上前ですかね…」
先輩「（ローカルの）ソースは新しくしてる感じですよね？」
筆者「してます！git pullのやつですよね！」
先輩「そう～ちょっと見てみましょうか」
（一緒に手元のソースを見る）
先輩「あ、これ出来てないですね。」
筆者「！？」
```
結論、環境が起動しない原因は直近で起動に関するアップデートが入ったにもかかわらず、それを知らんぷりしてひと月以上前のソースを使っていたことが原因でした。
というのも、私がやっていたソースの最新化とは、
1. ```git stash```で変更一時退避して～…
1. ```git switch main``` でメインブランチに移動して…
1. ```git pull```で最新化！
1. ```git stash pop```で変更復帰！
1. 終わり！（コマンド叩くのエンジニアっぽくてかっこいい～！）
のことでした。皆さんはお気づきかと思うのですが、2の操作で引数を指定しない場合、ローカルのmainブランチが最新化されるだけで、自分がいる作業ブランチは古い状態のままになってしまいます。

なまじpullというものがfetch + mergeであるということを知っていた私は「fetch? merge? ンなもんpull使えば一発よ！」と各コマンドの意味や使い方を調べずに魔法として使っていました…

結果、ソースを最新化したところ一発で解決。先輩はその後も優しく丁寧にフォローしていただけましたが、とてもご迷惑をおかけしてしまった…という話です。

とにかく言われたことを鵜呑みにするのではなく、自分の知として身に付けるために調べてみることですね…深く反省します。
一番よく使う言語（？）にもかかわらず、まだまだGitについては知らないことばかり。精進いたします。



# 参考記事
- [git fetchとブランチ取り込み系コマンドを解説](https://qiita.com/matsumon-development/items/d3231acccc08c8d74c21)
- [Git - originとmasterとは何か(初心者向け)](https://qiita.com/seri1234/items/e651b3e108a695a92809)
- [【初心者向け】git fetch、git merge、git pullの違いについて](https://qiita.com/wann/items/688bc17460a457104d7d)