概要
この記事で扱うこと
- Gitの基本的なコマンドである
git reset
やgit revert
の扱い方 -
git reset
、git revert
のイメージ
この記事を読むべき人
- Git初心者
- 「addとかcommitとかはわかるけど実践で使ってみたらなんかよくわからん!」という方
「Gitって?」「リモートリポジトリって何?」といった基本の「き」的な内容は取り扱いません🙇
初めに
WHIのアドベントカレンダ―本日分を担当させていただきます!
git add
, git commit
, git push
など、リモートリポジトリへ反映する方法はなんとなく知っていても、それを取り消す方法って意外にまとまってないですよね…
自分も新卒エンジニアという身なので、改めてGitの使い方をおさらいしようと思います!
git reset, revert の基本的な使い方
というわけで、まずは基本的な使い方からまとめていきます。
git reset
$ git reset --soft HEAD^ //直近のcommit等を取り消す
-
直前の操作を取り消します。(commitやpushなど)
-
第1引数ではどのレベルで巻き戻すかを指定します。
-
--soft
: 直前の操作のみを取り消し、編集をステージング(git add
)した状態に戻す -
--mixed
: 直前の操作とステージングを取り消し、編集したばかりの状態に戻す -
--hard
: 直前の操作・編集を丸ごとなかったことにする(※使用注意!)
-
-
第2引数ではどのコミットまで戻すかを指定します。
git revert
$ git revert コミットID
-
指定したのコミットを打ち消すコミットを作成します。例えば「Aという文字を書き加える」というコミットを対象にrevertを実行すると、「Aという文字を削除する」というコミットが作成されます。
-
引数では打消しのコミットの対象を指定します。
- コミットIDの指定 : 上述の
git reset
の参照方法と同じ
- コミットIDの指定 : 上述の
-
コミット時と同様、コマンドを実行するとコミットメッセージの編集画面に遷移します。任意のメッセージを入力し、
:wq
で保存&quitしてください。 -
「逆向きの変更は作りたいが、一度にコミットまでしたくない」という場合は
git revert -n コミットID
のように[-n]コマンドが使えます。
何が違う?
両者の基本的な使用法はおさらいしました。ですが、どのような差があり、どう使い分ければいいのでしょうか?
結論からいうと、両者の差はコミット履歴が残るかどうかという点だけです。
ここでは両者のイメージをまとめておきます。
git reset
resetはコミットそのものをなかったことにし、今いる地点を正とします。
過去を改変したことによってその先の未来がなくなってしまうイメージです。その手のアニメだとあるあるですね!
コミット履歴まで消えてしまうため、ユースケースとしては
- 「本当に間違ってコミットしてしまった」
- 「コミット後に誤りに気付いたが軽度なので誰かに見られる前に直しちゃいたい」
などが考えられそうです。
コミット履歴欄に余計なものが残らないので、ごちゃつかずに済みますね!
起こりうるエラーと解決法
ただし、歴史の改変は往々にして世界線の不整合を生み出してしまいます…
resetをしたのちにgit push
をしようとするとエラーが表示されてしまうのです。
上図では、要所要所でリモートリポジトリに変更を反映している状態で、ローカルでcommit3をresetし、その先の変更を反映しようとしています。
ですが、リモートリポジトリからすると「2の次に3があって、その次に4」という歴史を経ているので、急にcommit4'(ダッシュ)が来ても「歴史が違うのでプッシュされても困る!(どちらの歴史が正しいかわからない!)」となってしまうのです。
この状態を解決する方法は以下2つがあげられます。
1. git fetch
などでローカルの状態をリモートリポジトリに合わせる
1. git push origin head -f
(強制プッシュ)を行うことで、リモートリポジトリの状態をローカルに合わせる
いずれもリモートと手元のソースをそろえるという手間がかかります。強制プッシュを行ってしまえばエラーなくpushが可能ですが、共同で編集しているブランチであれば、メンバーの方に一声かけるのが賢明でしょう。
git revert
revertは逆向きのコミットを生成するので、あくまで時系列としては先に進んでいます。
resetが「コミットなんて無い!0に戻す! (1 ⇒ 0)」なのに対し、
revertは「コミットが+1されたので、-1のコミットを足して0に戻します~ ( 1 + (-1) = 0 ) 」というイメージです。
過去改変を行うわけではないので、reset後のpush時に起こるようなエラーは起こりえません。
また、修正したことが明示的になるので、「この人は意図的に修正を入れたんだな・コミットを取り消そうとしたんだな」ということが他の人からもわかります。
ただし、あくまで 「逆向きのコミットを生成する」 コマンドなので、コミット履歴が残ってしまう点は注意が必要です。
まとめ
お疲れ様でした!
今回はGitにおける取り消し手段の代名詞であるgit reset
とgit revert
についてまとめました。
開発初心者の方が一番最初につまずくのがgit周りなんじゃないでしょうか…(少なくとも私は😿)
私も日々経験を積んで、エンジニアとして大成できるよう精進いたします。ご精読ありがとうございました!