【失敗談】GitHubのコミット履歴を復元させることになった時の話し

## そもそも、なぜコミット履歴を復元することになったのか


#### 禁断のコマンド「git push -f」

作業の詳細はここでは割愛しますが、当時Git-flowを導入しようと作業を進めていました。 その作業の途中で「git push」を行なったところ、下記のようなエラーが出ました。

```
% git push
〜〜省略〜〜
〜〜省略〜〜
error: failed to push some refs to 'https://github.com/〜〜省略〜〜.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

# 翻訳
ヒント：リモートにあなたが行った作業が含まれているため、更新は拒否されました
ヒント：ローカルにはありません。 これは通常、別のリポジトリがプッシュすることによって発生します
ヒント：同じ参照に。 最初にリモートの変更を統合することをお勧めします
ヒント:(例：'git pull ...'）もう一度押す前に。
ヒント：詳細については、「gitpush--help」の「早送りに関する注意」を参照してください。
```


エラー内容の一文に、「同じ参照に。 最初にリモートの変更を統合することをお勧めします」といった内容が出ていたため、その言葉を都合のいいように自分で解釈してlocalの開発ブランチをリモートにプッシュしてしまおうと「-f」のオプションを使用して強制プッシュを実行。

```
% git push -f
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
〜〜省略〜〜
〜〜省略〜〜
〜〜省略〜〜
 + 4XXXXX6...aXXXXX8 master -> master (forced update)
```

すると、開発用ブランチからpushしたはずが、<font color="red">master -> master (forced update)　「マスターの強制更新」</font>という内容のメッセージが出力。
何が起きているのか、GitHubでブランチを確認。
すると、開発ブランチだけではなく、マスターブランチも<font color="red">直近１週間分のコミット履歴が全て消えてしまっている</font>ことに気づきました。
これはまずいと、「git log」でlocalのコミット履歴を確認するも、全てのブランチで１週間分のコミット履歴が消えていることが分かりました。　過去にどこをどう修正したのか、なぜ修正したのか、という履歴を確認出来なくなってしまい、「あぁー、やってしまった」となったのが、コミット履歴を復元するに至った経緯です。


## 状況把握

ここで一旦、落ち着いてまず状況を把握することに。
整理すると次のことが分かりました。

:::note info
GitHubの「Issues」に「#No」で紐付けていたコミット履歴はブラウザ上で確認することが出来る
:::

:::note info
Time Machineで外付けHDDに直近のバックアップ データが残っている
:::


## 復元方法の調査及びアクション

現状把握できている状況から、復元の方法がないか記事を検索。
GitHub公式のリファレンスで検索したところ、サポートチームへ連絡すれば、90日前までのデータを復元できる可能性があることが分かりました。
少し考えて、こんな経験をすることもなかなか無いと思い、有識者からアドバイス頂きながら自分で解決することは出来ないか？と考え、某メンタリングサービスを活用することに。


## 結局どうやって解決したか

#### 1. データの復元

まず、直近のバックアップ データを元にlocal環境を復元。


#### 2. Issuesに残っていたコミット履歴を確認

次に唯一、コミット履歴を確認することが出来た、GitHubの「Issues」に残っていたコミットのハッシュ値を元に「git show」コマンドを実行して、どのような結果が出るか確認。

```
% git show ＜コミットのハッシュ値＞
commitの詳細情報
〜〜〜省略〜〜〜〜  # 消えていたコミットの詳細が表示された！
〜〜〜省略〜〜〜〜
```

すると、消えていたコミットの詳細情報が残っていることが分かりました。


#### 3. コミットのハッシュ値を元にブランチの切り替え

Issuesに残っていた最新のコミットのハッシュ値を指定してブランチの切り替えを実行することに

```
% git checkout ＜コミットのハッシュ値＞
Note: switching to '＜コミットのハッシュ値＞'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at ＜コミットのハッシュ値＞ ＜コミット名＞
```



#### 4. コミット履歴の確認

「git log」コマンでコミット履歴を確認したところ、消えていた過去のコミット履歴が復元されていることが確認出来ました。

```
% git log    # またはオプションで「--oneline」
〜〜省略〜〜　  # 消えていたコミット履歴の一覧が表示された！
〜〜省略〜〜
〜〜省略〜〜
```


#### 5. 復元させたいブランチへマージ

まずは、開発ブランチへマージ

```
% git checkout develop
% git branch　			         # 一応、今のブランチを確認
% git merge ＜コミットのハッシュ値＞	 # 履歴が確認出来たコミット
% git push --set-upstream origin develop
```

GitHubの開発ブランチ(develop)でコミット履歴を確認したところ、元通り復元されていることが確認出来ました。　これで、復元したかったコミット履歴は無事復元することが出来ました。


## 反省

GitHubはチーム開発で使用する重要なツールで、何かミスをすると自分だけではなく、チームのメンバーに大変な迷惑をかけてしまうということ。　将来自分がエンジニアになった際に同じことをやってしまっていたらと思うと、個人開発とは言え良く分からないまま進めてしまった自分の行動の甘さに深く反省しました。


## 今後に向けて

初めての操作や商用に直結する操作、メンバーで共有している環境の変更など、上げれば切りがないかもしれませんが、要所要所で、どんな影響があるのか分からない時は、一度手を止めて確認してから影響があっても取り戻せる体制を整えて実行する。　または有識者へ相談するなどして、被害を最小限に抑えながら今後のポートフォリオ制作を進めていきたいと思います。


## 最後に

同じ失敗を繰り返さないための自分への戒めとして、あえて失敗談を掲載しました。　ここまで、お読み頂きありがとうございました。:bow: