git logでコミット履歴を活用しながら、gitの枝分かれミスを解決する方法

# 前提

* 以下の三つのブランチがある
    * main
    * develop
    * feature

* 本来、developからfeatureを分岐させて作業しなければならなかったが、Aさん（自分）が誤ってmainから分岐させた状態で作業をしてpushしてしまった。その上、featureブランチでBさんがコードを追記した。

* 本来のあるべき姿
```
------------- main 
   \_________ develop
        \____ feature
```

* 現状
```
------------- main 
   \_________ develop
   \__________ feature
```

* どのように本来のdevelopブランチから派生させた状態、且つ、AさんとBさんがfeatureで作業した分も反映したブランチにするか、その手順を記す。
* `git log`のコミット履歴を見ながら作業することで、現在どのような状態なのかを把握しながら行う、という点を主軸に記していく。




# 手順
* `git log`で履歴を閲覧(以下、SHA値を省略)すると、現時点では、ローカルリポジトリ（緑色）のコミット履歴とローカルに同期したリモートリポジトリ（赤色）のコミット履歴が同じであることを確認できる。（マークダウンでは色まで表現できず悪しからず）

```terminal
(HEAD -> feature, origin/feature)
```

* `git branch`でfeatureにいること確認
```terminal
* feature
  main
```

* `git fetch`でBさんコミット分の情報の差異を取り込む。
    * ただし、fetchはリモートリポジトリの情報を参照できるようになっただけであり、ローカルリポジトリのブランチに反映させるにはpull(またはfetch+merge)が必要。git addやgit commitなどとの関係性については他に分かりやすく解説してくれている別記事の参照を推奨。
```terminal
 * [new branch]      develop         -> origin/develop
```

* `git log`を見ると、以下のようになる。Bさんコミット分が加わったことにより、ローカルリポジトリのコミット履歴と差異があることを確認できる。
    * これは、Bさんがコミットした部分と差異が発生しているため＝最新のコミット番号とズレが生じていることを表している
```terminal
 (HEAD -> feature)

```

* `git pull origin feature`を行い、Bさんコミット分をローカルリポジトリのfeatureに取り込む
```terminal
 * branch            feature -> FETCH_HEAD
 * Updating 5cd6952..a3c4723
Fast-forward
```

* `git log`を見ると、以下のようになる。Bさんコミット分も加わり、ローカルリポジトリのfeatureの状態も最新になったことが確認できる。
```terminal
 (HEAD -> feature, origin/feature)
```

* `git checkout -b develop origin/develop`により、origin（リモート）にあるdevelopブランチをベースに、ローカルのdevelopブランチを新規作成する。
```terminal
branch 'develop' set up to track 'origin/develop'.
Switched to a new branch 'develop'
```

* `git branch`で今いるブランチがdevelopであることを確認できる。
```terminal
* develop
  feature
  main
```

* `git log`で確認。originから最新のものを取ってきているので、ローカルリポジトリのコミット履歴とリモートリポジトリのコミット履歴が同一（最新）であることを確認できる。
```terminal
 (HEAD -> develop, origin/develop)
```

* `git checkout feature`でfeatureブランチに切り替える。
```terminal
Switched to branch 'feature'
Your branch is up to date with 'origin/feature'.
```

* `git merge develop`でマージを行う（featureにdevelopとの差分をマージする）
```terminal
Merge made by the....
```

* `git log`で確認すると、マージを行ったことで、ローカルリポジトリのコミット履歴とリモートリポジトリのコミット差異があることを確認できる。
    * これは、マージを行ったことで、ローカルリポジトリのfeatureにはdevelopとの差異分が統合されているが、リモートリポジトリのコミット履歴には統合されておらず、差異が発生しているため。
```terminal
 (HEAD -> feature)
```

* `git push origin feature`を行うと、以下のようにpushが始まり、リモートリポジトリにfeatureブランチの履歴が送信される。
```terminal
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
```

* `git log`で確認。ローカルリポジトリもリモートリポジトリもコミット履歴が同一（最新）であることを確認できるので、これで完了。
```terminal
 (HEAD -> feature, origin/feature)
```


# 備忘録
* ブランチ：履歴の流れを分岐して保存していくための機能
* git log：今までのコミット履歴を確認することのできるコマンド
* HEAD：今自分が作業している場所を示すポインタ
    * git logの`(HEAD -> ブランチ名)`は現在のコミット履歴を参照しているブランチがどこかを表している
    * 以下のように、複数のブランチがある場合は、現在のブランチがmainで、残りの２つのブランチ、 origin/developと defaultも同じコミットを指していることを示す
    * 例）
```terminal
commit 66483ae81ca288f9cffdeb2859606bec5ec0363b (HEAD -> main, origin/develop, default)
```

* origin/ブランチ名：ローカルにプルしたリモートブランチのこと。 このブランチの正式な名称は、`git branch -a`で確認することができ、remote/origin/ブランチ名　となっている。指定する際は、remote/を省略できる。

* git fetch：他人の更新内容を取得したい場合に実行するコマンド。リモートリリポジトリの状態が最新になった場合は、`git fetch`を行うことでローカルリポジトリの「リモートリポジトリ名/ブランチ名」の履歴も更新される。