gitでやらかしたときによく使うrevertやreflogやrebaseについて

gitを現場で利用したてのとき、コンフリクトが起きたりした際や、気づいたら変なマージリクエストが作られてしまった際、どうすれば良いかあたふたしていたのは僕だけでしょうか?(僕だけかもしれない)

そんなときに、焦りながらやるとどんどんコミットログが汚れていき、かなり悲惨な目にあうこともあります。

今回はgitでやらかしたときによく使うrevertやらreflogやらrebaseについて解説します。

前提事項

下記で紹介する操作は、ある程度リスクもある作業です。

不慣れな方は、必ずローカルブランチでお試しください。

また、これらの操作後はマージリクエストに不備がないことを確認し、操作が適切なのかもチームメンバーにも確認してもらいながら実施することをオススメします。

revertを使ってマージコミットを取り消す

リリース後不具合が発生してしまった場合、マージコミットそのものをrevertしてmergeそのものを取り消すことができます。

この場合、revertコミットを更にrevertすつことで簡単にもとに戻すこともできます。(revertをrevertする、なんてい言ったりもします)

githubやgitlabのGUIから直接revertもできますが、下記のようにコマンドラインで実行することも可能です。

// revertしたいコミットIDを確認したい場合
$ git log

// コミットIDを指定してrevertする
$ git revert #{コミットID}

ちなみに似たものでresetもありますが、この場合はログが残りません。明らかな不具合等の場合や後々元に戻すことも考慮するとrevertを使うことが多い印象です。

最終手段のreflog

git reset --hard HEAD^などで取り消しすぎてしまった場合、基本的にはログが残らないので戻すことはできませんが、reflogを使えば過去のコミットを基本的にすべて見ることが可能です。

// 過去のコミットがみれる
$ git reflog
e59be1e (HEAD -> main, origin/main) HEAD@{0}: Branch: renamed refs/heads/main to refs/heads/main
e59be1e (HEAD -> main, origin/main) HEAD@{2}: commit: add: api/hello.js追加
011039b HEAD@{3}: commit: add: データフェッチ追加

// 下記のように指定することでもとに戻すことも可能
$ git reset --hard HEAD@{3}

rebaseを使ってコンフリクトを解消する

ブランチを最新化せずに開発をしてしまったり、コンフリクト発生時にたまにやります。

例えば、開発者Aさんと開発者Bさんが同時に開発をしており、Aさんが先に開発完了してmainブランチにmergeしたとします。

そして、このときBさんも触っているファイルが更新されていた場合、Bさんがmainブランチにmergeするタイミングでコンフリクトが発覚します。

この場合、mainブランチを最新化した後、開発ブランチをrebaseすることでローカル上でコンフリクトを解消することができます。

ただし、この方法は最終的にコンフリクト修正後にforce pushする必要があるため開発ブランチを触っているひとが複数人いる場合は注意が必要です。

// mainブランチを最新化
$ git checkout main
$ git pull origin main

// 開発ブランチでrebaseする
$ git checkout development
$ git rebase main

// コンフリクトを解消する

おまけ

以下は緊急度は低いですがコミットを改竄修正ときに便利なのでご参考まで。

こっそりコミットを取り消す

ローカル開発していて不要なコミットがある場合にたまに使います。revertと違いログが残らないので後で戻したい場合は使用しないようにご注意を。(最悪reflogで戻せますが)

// 直前のコミットを取り消す
$ git reset --hard HEAD^

// 2つ前のコミットを取り消す
git reset --hard HEAD^^

コミットメッセージを修正する

コミットメッセージをタイポしてしまった場合などに修正する方法です。ただしリモートにもすでにある場合はforce pushすることになるのでご注意

// メッセージタイポした
$ git commit -m "initial commmit"

// amendをつけることでメッセージのみ修正ができる
$ git commit --amend -m "initial commit"

そもそもgitそのものがよくわからん

下記のサイトがイラストと一緒に非常にわかりやすく解説しているのでおすすめです。

今回取り上げたrevertとかもここ読んでみてほしいです。

まとめ

  • 慣れないうちはチームメンバーにも確認してもらいながら実施すること
  • 特定のコミットを取り消し、かつログを残したいときはrevertする
  • ログから戻すことができないなどのとき、最終手段としてreflogをつかう
  • コミットを取り消してログも残したくない場合はresetする
  • コンフリクトを解消する一つの策としてrebaseがある
  • コミットメッセージだけを変更したい場合はcommit --amend -m “XXX”を使う

それでは、ご安全に!