今日は現場でちょっとヒヤッとした出来事があったので、
プログラマーになるまでの記録として残しておきます。
結論から言うと、
メインブランチにプッシュしかけました。
プッシュしかけたと言えば聞こえはいいのですが、実際めっちゃVScodeのソース管理の部分のプッシュボタン押しまくってました。なんかプッシュできないな....?
仕方ない、コマンドで行くかgit push origin branch(ブランチ名は仮名)ってしようとした時に気づいてしまったんです!!!!!
め... め.... メインブランチじゃないですか?!?!?!
今いるブランチ😱
一瞬で血の気が引きました。
嘘だろ?!
私コミットしちゃったぞ?!?!?!!
いつもなら作業中ここで暖かく見守って変更が全員終わるのを待ってくれていたカラフルなディレクトリたちももういない....
もうここにあるのは押せなくなってしまったグレーに染まったコミットボタンだけ....
まっっ先に思ったのは、使えないなコミットボタン!!!
もっと頑張れ!!
そう、私はもうコミットボタンさえ責め立ててしまうくらい余裕がなかった.
しかし、私は冷静さを取り戻した。
まだコミットしただけじゃないかーーー
先輩がロックか何かをかけていてくれたおかげでまだ大事故は起こっていない。
そう言えばメインブランチじゃないけどよく他のブランチに間違えてプッシュしまくってたぞ?🤔
今回もその要領でいけばこもっと履歴を取り戻せるはず!
そう思い、まずはできることをしました
─── そう、私のコミット履歴を取り戻す旅はここから始まりました
ってことで前置きが長くなったのですが、わかりやすく
main に誤コミットしたときの戻し方を説明していきたいと思います。
なぜそうするかまで含めて順番に説明します!
まず状況を確認する
作業を始める前に、いま何が起きているか見ます。
まずは冷静に落ち着いて。身の回りの安全を確保してから落ち着いて作業しましょう。
パニックになってしまって再度誤って変なところにコミットしないようにです。
git branch --show-current # 今いるブランチ
git status # 未コミットの変更があるか
git log --oneline -5 # 最近のコミット履歴
前回の状態(例)
On branch main
Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.
これは....
見間違いなんかじゃない....
やっぱりメインブランチにコミットしてます。
- ローカルの main に、自分だけのコミットが1つある
- リモートの origin/main にも、別の新しいコミットが1つある
という意味です。
git log --oneline -3
3bd804a ブラウザのタブ名を変更 ← 自分が誤って main に入れたコミット
1c28374 Merge pull request #364 ...
「間違えて main にコミットした」 と分かったら、次に進みます。
大原則:消す前に退避する
いきなり消すと、あとで「やっぱりその変更使いたい」となったとき困ります!!ガチで!!!本当にね!!フリじゃないよ?!
消すのなんか正直最後でもいい、いやむしろ消し忘れてもいい。
書いてあったコードを消してしまうより何千倍もましだ。
ただし!
mainを戻すのを忘れるのはマズいです。退避だけして reset しないと、main にはまだ誤コミットが残ったままです。
だから順番は
- 変更を別ブランチにコピーして退避
- main だけ元に戻す
- (必要なら)最新の main の上に作業を載せ直す
手順1:退避用ブランチを作る
git branch feature/tab-title 3bd804a #←さっき間違えたコミットの番号
これは何をしている....?って普段以上に怯えてると思う。でももう大丈夫だから。
大丈夫、怖くない。落ち着いて聞いてほしい。
| 部分 | 意味 |
|---|---|
| git branch | ブランチを作る |
| feature/tab-title | 新しいブランチ名 |
| 3bd804a | そのコミットを指す(誤コミットのID) |
main はそのままで、同じ内容のブランチがもう1本できるイメージ。
main → 3bd804a(誤コミット)→ 1c28374 → ...
feature/tab-title → 3bd804a(同じ内容を保持)
コミットIDの調べ方
git log --oneline -5
一番上の行の 3bd804a のような英数字がコミットIDです。
先頭の 7文字くらい で十分使えます。
手順2:main をリモートと同じに戻す
git checkout main # main にいることを確認(大事!)
git fetch origin # リモートの最新情報を取得
git reset --hard origin/main
これは何をしている?
| 部分 | 意味 |
|---|---|
| git reset | ブランチの先端(HEAD)を動かす |
| --hard | コミットも作業フォルダのファイルも 指定した状態に戻す |
| origin/main | リモートの main の最新(GitHub上の main) |
結果
main → 78b34c6(origin/main と同じ)
feature/browser-tab-title → 3bd804a(退避済み)
main から誤コミットが消え、リモートと揃う のがゴールです。
--hard に注意
- 未保存の変更も消える ので、戻す前に git status で確認
- 今回は「コミット済みを戻す」だけだったので --hard で問題なし
手順3:戻せたか確認する
git status
git log --oneline -3
成功するとこうなります
On branch main
Your branch is up to date with 'origin/main'.
78b34c6 引用リポスト移行タスクを追加修正
1c28374 Merge pull request #364 ...
- up to date with 'origin/main' → main がリモートと同じ
- 誤コミット 3bd804a が main の履歴から消えている
ここまでで main は救済完了 です。お疲れさま!!!
手順4:退避した変更を、ちゃんとしたブランチでやり直す
main はきれいになったけど、作業内容自体はまだ使いたいですよね。!
私はここでcherry-pickを使いました。
git checkout main
git pull origin main
git checkout -b feature/rename-tab-title
git cherry-pick feature/tab-title
cherry-pick は、特定のコミットだけを今のブランチに持ってくる操作です。
コミットIDが 3bd804a → d01e941 のように変わっても正常です。
「同じ変更を、最新の main の上に載せ直した」という意味だからです。
状況別:自分で使い分ける
パターンA:コミットしたけど push していない(今回)
git branch 退避ブランチ名 <コミットID>
git checkout main
git fetch origin
git reset --hard origin/main
パターンB:まだコミットしていない(ファイルだけ変更)
git restore . # 変更を全部捨てる
# または
git stash # 一時退避(あとで戻せる)
git checkout -b feature/xxx # 別ブランチで stash pop
パターンC:すでに push してしまった😱
reset --hard だけでは不十分で、リモートを書き換える必要があります。
基本は先輩に相談が安全です。
事前チェックリスト(次回用)
main で作業して「あれ?」となったら:
# 1. 今どこにいる?
git branch --show-current
# 2. push した?
git status # "ahead of origin/main" ならまだ push してない
# 3. 戻したいコミットはどれ?
git log --oneline -5
# 4. 退避
git branch backup/作業名 <コミットID>
# 5. main を戻す
git checkout main
git fetch origin
git reset --hard origin/main
# 6. 確認
git status
git log --oneline -3
# 7. 作業をやり直す(PR用)
git checkout -b feature/やりたいこと
git cherry-pick backup/作業名
今回は先輩がメインブランチにプッシュできないようにしてくれてたので助かりました!!!
つまり何が言いたいかはお分かりですね??
新入社員が入ってきた職場の皆様!!メインブランチにプッシュできないように設定してください!!今すぐに!!急いで!!
やり方は私にはわかりませんが、先輩方ぜひ頑張ってください!!!

