Gitのブランチがdetached fromになってしまった時の失敗した対応方法

- 環境
    - CentOS Linux release 7.6.1810 (Core)
    - git version 1.8.3.1
    - xfc4-terminal 0.8.7.4

# 事象 : 現在のブランチに`detached from`と表示される
```bash
# 何だ？
$ git branch
* (detached from origin/feature/branchA)
  feature/develop

# 何だ何だ？
$ git branch --contains=HEAD
* (detached from origin/feature/branchA)

# 今のブランチはどこへいった？
$ find .git/refs/heads/
.git/refs/heads/
.git/refs/heads/feature
.git/refs/heads/feature/develop
```

## しかも1回コミットしちゃった

```bash
# コミットした時よく見るとdetached HEADとかいってたのに
$ git commit -m "問題コミットのコメント"
[detached HEAD e4ab2e5] 問題コミットのコメント
 8 files changed, 258 insertions(+)
 create mode 100644 project/src/main/java/jp/co/Hsitory.java
 create mode 100644 project/src/main/java/jp/co/logic/HsitoryLogic.java
 create mode 100644 project/src/main/java/jp/co/logic/impl/HsitoryLogicImpl.java

# プッシュしてエラーになったのに
$ git push
fatal: You are not currently on a branch.
To push the history leading to the current (detached HEAD)
state now, use

    git push origin HEAD:<name-of-remote-branch>

# 更にプッシュしてエラーだったのに・・・
$ git push --set-upstream origin feature/branchA
error: src refspec feature/branchA does not match any.
error: failed to push some refs to 'https://github.com/user/repo.git'

# なんかログに出てたからつい放置してしまった(コミットしたんだから出るさ)
$ git log
commit e4ab2e5
Author: ponsuke <ponsuke@mail.com>
Date:   Wed Jul 10 18:13:31 2019 +0900

    問題コミットのコメント

commit 3407420
Merge: 05bc343 d532a4b
Author: ponta <50603053+ponta@users.noreply.github.com>
Date:   Wed Jul 10 11:20:17 2019 +0900

    Merge pull request #5 from feature/branchB

    Feature/branchB

# そしてこのハッシュ変だ！
$ git name-rev e4ab2e5
e4ab2e5 undefined
```

# 原因 : HEADがブランチではなくコミットを指しているから
[detached HEAD から脱出する方法を git の内部構造から探る - Qiita](https://qiita.com/Kuniwak/items/4e5d55d6888e5f6411fe)

```bash
# HEADの流れを見てみる
$ cat .git/logs/HEAD
# 省略
d532a4b e0fdb37 ponsuke <ponsuke@mail.com> 1562661447 +0900   checkout: moving from branchB to feature/develop
e0fdb37 e0fdb37 ponsuke <ponsuke@mail.com> 1562662611 +0900   checkout: moving from feature/develop to feature/branchA
e0fdb37 e0fdb37 ponsuke <ponsuke@mail.com> 1562721493 +0900   checkout: moving from feature/branchA to feature/develop
e0fdb37 3407420 ponsuke <ponsuke@mail.com> 1562726844 +0900   checkout: moving from feature/develop to origin/feature/branchA
3407420 e4ab2e5 ponsuke <ponsuke@mail.com> 1562750011 +0900   commit: 問題コミットのコメント

# branchAの流れを見てみると・・・何か・・・ユーザ名をタイポったようだ・・・
$ cat .git/logs/refs/remotes/origin/feature/branchA
0000000 e0fdb37 ponsuke <ponsuke@mail.com> 1562662653 +0900   update by push
e0fdb37 3407420 onsuke <onsuke@82e9656b4223.(none)> 1562726194 +0900    fetch: fast-forward
```

## 失敗した対応 : もとのブランチまで戻そうとして、コミットした変更内容まで戻してしまった。
```bash
# これまでの操作を確認する
$ git reflog
e4ab2e5 HEAD@{0}: commit: 問題コミットのコメント
3407420 HEAD@{1}: checkout: moving from feature/develop to origin/feature/branchA
e0fdb37 HEAD@{2}: checkout: moving from feature/branchA to feature/develop
e0fdb37 HEAD@{3}: checkout: moving from feature/develop to feature/branchA
e0fdb37 HEAD@{4}: checkout: moving from branchB to feature/develop
# 省略

# コミットした変更内容は消さないように戻したかった
$ git reset --hard HEAD@{0}
HEAD is now at e4ab2e5 問題コミットのコメント

# まだ、detachedだなぁ
$ git branch
* (detached from origin/feature/branchA)
  feature/develop

# そっか、コミット後に戻ったからまだ変なんだ、と思った
$ git status
# HEAD detached from origin/feature/branchA
nothing to commit, working directory clean

# コミットしちゃっているからdiffも出ないし
$ git diff HEAD
$

# もういっこ戻そう！
$ git reset --hard HEAD@{1}
HEAD is now at 3407420 Merge pull request #5 from feature/branchB

# ん？
$ git status
# HEAD detached at origin/feature/branchA
nothing to commit, working directory clean

# コミットした変更内容まで戻してしまった！
$ git diff HEAD
$

# あ～～～もう変更内容はない〜
$ git log
commit 3407420
Merge: 05bc343 d532a4b
Author: ponta <50603053+ponta@users.noreply.github.com>
Date:   Wed Jul 10 11:20:17 2019 +0900

    Merge pull request #5 from feature/branchB

    Feature/branchB
```

この後、もう一度実装し直してコミット&プッシュしたらもとのブランチ(origin/feature/branchA)に無事変更が入りました。

### 次回への反省 : 落ち着こう
1. プッシュ時を振り返って
    2. `fatal: You are not currently on a branch.`(現在ブランチ上にいません)って言われているんだから考えよ、やり方も教えてくれてるんだからメッセージ読もう

> `git push origin HEAD:master`
> 現在の分岐を、originリポジトリ内のリモート参照に一致するmasterにプッシュします。この形式は、ローカル名を考慮せずに現在のブランチをプッシュする場合に便利です。
> [Git - git-push Documentation](https://git-scm.com/docs/git-push)

1. 戻し作業の前を振り返って
    2. 間違ってコミットした変更対象のファイルをどっかに退避してからもとのブランチまで戻して、退避したファイルを戻す
    2. まず、もとのブランチをチェックアウトして、間違えたコミットをチェリーピックしてもできたかも
3. コミットまで戻しちゃった時を振り返って
    4. [git reset --hardは取り消せるらしい](https://qiita.com/ritukiii/items/74ee3274c3f218511a0c#番外編-git-reset---hardを取り消したい)