5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

怖くない切り戻し git-revert / git-reset

Last updated at Posted at 2021-02-04

はじめに

master ブランチに最新版がマージされたあと、問題が見つかってリリース前に戻したいときがたまにあります。しかし git-revert/git-reset は普段使うことがないので、少し身構えてしまいますね。今回はこれらのコマンドを簡単なサンプルを見ながら動きを確認していきます。

git-revert/git-resetとは

どちらも変更点を打ち消すためのGitコマンドになります。
どのような違いがあるのか見てみましょう。
一応、公式のドキュメントに書いてある説明です。

  • revert: いくつかの既存のコミットを元に戻す
  • reset: 現在のHEADを指定された状態にリセットする
    だそう。

難しいのでざっくり以下の認識でOKです。
スクリーンショット 2021-02-03 19.07.23.png
どういうことか触りながらサンプルを見ながら説明します。

まずはおさらい git-rebase / git-merge

git-rebase

分岐先のコミットを古いものから順に舐めていき、分岐元へと順次取り込んでいく。

スクリーンショット 2021-02-03 19.11.01.png

git-merge

分岐先の差分を分岐元に合体する。

スクリーンショット 2021-02-03 19.12.14.png
(squashしているとかno-ffとかの細かい話は割愛)

ハンズオン

では、次に git-revert/git-reset のサンプルを見ながら手を動かしながら見てみましょう。

git-reset

以下のコードをコピペして実行してください。実行すると下図のような状態になります。

# msaterブランチを作成
mkdir gitHandsOn && cd gitHandsOn
git init
echo "A" >> work.txt
git add . && git commit -m "Commit A"

# featureブランチに切り替えてコミットAからコミットDを作成
git checkout -b feature
echo "B" >> work.txt
git add . && git commit -m "Commit B"
echo "C" >> work.txt
git add . && git commit -m "Commit C"
echo "D" >> work.txt
git add . && git commit -m "Commit D"

# git-rebase
git checkout master && git rebase - && git log --oneline

スクリーンショット 2021-02-03 19.15.23.png

次にgit-resetしてみましょう。
まずはさきほどのコミットDを打ち消してみます。

git checkout master
# コミットログを表示
git log --oneline
---------------------------------------------------------------
8254890 (HEAD -> master, feature) Commit D
5a5afaf Commit C
09d38a1 Commit B
383454e Commit A
---------------------------------------------------------------
# コミットDを打ち消してみましょう
# まずは以下のようにコミットDのコミットログを指定して、git-resetを叩いてください
git reset --hard 8254890
git log --oneline

いかがですか、消えましたか?

消えませんね。

どういうことか。

git-resetは指定されたコミットにHEADを移動させるコマンドなので、コミットDを指定してもコミットDは打ち消されません。

では改めてコミットDを打ち消してみましょう。

git checkout master
# コミットログを表示
git log --oneline
---------------------------------------------------------------
8254890 (HEAD -> master, feature) Commit D
5a5afaf Commit C
09d38a1 Commit B
383454e Commit A
---------------------------------------------------------------
# コミットDを打ち消してみましょう
# 改めて以下のようにコミットDのコミットログを指定して、git-resetを叩いてください
git reset --hard 5a5afaf
git log --oneline
---------------------------------------------------------------
5a5afaf (HEAD -> master) Commit C
09d38a1 Commit B
383454e Commit A
---------------------------------------------------------------

コミットDが無事に打ち消されました。

スクリーンショット 2021-02-03 19.19.21.png

演習1

最初にコピペしたコードを使って以下の状態にしてください。
※ 答えは一番最後に載せておきます。

スクリーンショット 2021-02-04 23.11.50.png

hard と soft の違いについて

hard はコミットを打ち消すとともにローカルの内容も移動後のHEADの時点に戻します。
soft オプションを使用すると、コミットは打ち消されるが、ローカルの内容はそのまま保持されます。これは、修正内容を維持しつつコミットだけを削除したい場合に適しています。

演習2

最初にコピペしたコードを使って以下の状態にしてください。
※ 答えは一番最後に載せておきます。

スクリーンショット 2021-02-04 23.14.48.png

git-revert

以下のコードをコピペして実行してください。実行すると下図のような状態になります。

# msaterブランチを作成
mkdir gitHandsOn && cd gitHandsOn
git init
echo "A" >> work.txt
git add . && git commit -m "Commit A"

# featureブランチに切り替えてコミットAからコミットDを作成
git checkout -b feature
echo "B" >> work.txt
git add . && git commit -m "Commit B"
echo "C" >> work.txt
git add . && git commit -m "Commit C"
echo "D" >> work.txt
git add . && git commit -m "Commit D"

# git-merge
# mergeの際にコミットコメントが必要なのでそのまま保存をしてください
git checkout master && git merge --no-ff - && git log --oneline

スクリーンショット 2021-02-04 23.16.36.png
マージコミットを打ち消してみましょう。

git checkout master
# コミットログを表示
git log --oneline
---------------------------------------------------------------
5b96ca7 (HEAD -> master) Merge branch 'feature'
2757f8e Commit A
914017f (feature) Commit D
711f950 Commit C
b66b20c Commit B
---------------------------------------------------------------
# マージコミットを指定してrevertを実行しくてださい
git revert 5b96ca7

いかがですか、消えましたか?

消えませんね。

どういうことか。

マージコミットを打ち消したいときは mainline というオプションを付与してあげる必要があります。

そしてマージコミットを打ち消す場合には mainline に 1 を指定してあげます。

小話 - mainline

mainline とは Git の parent-number のことです。git-merge とは2つのブランチを合体させることですが、どのブランチのコミットを合体させたかを以下のコマンドで調べることができます。

$ git show マージコミットのID
commit 5b96ca711b150aa66108fead2442699f8203ad9d (HEAD -> master)
Merge: 2757f8e 914017f
Author: takiguchi-yu

 Merge branch 'feature'

ここでいうと
2757f8e が mainline=1 で
914017f が mainline=2 ということになります。

では改めてマージコミットを打ち消してみましょう。

git checkout master
# コミットログを表示
git log --oneline
---------------------------------------------------------------
5b96ca7 (HEAD -> master) Merge branch 'feature'
2757f8e Commit A
914017f (feature) Commit D
711f950 Commit C
b66b20c Commit B
---------------------------------------------------------------
# マージコミットを指定してrevertを実行しくてださい
git revert --mainline 1 5b96ca7
git log --oneline
---------------------------------------------------------------
ce3046a (HEAD -> master) Revert "Merge branch 'feature'"
5b96ca7 Merge branch 'feature'
2757f8e Commit A
914017f (feature) Commit D
711f950 Commit C
b66b20c Commit B
---------------------------------------------------------------

無事できました。revert は reset と違ってコミットが残ります。
コミットログが残せる=一旦、チーム内でレビューを通せる、などのメリットがありますね。

スクリーンショット 2021-02-04 23.22.42.png

演習3

最初にコピペしたコードを使って以下の状態にしてください。
※ 答えは一番最後に載せておきます。

スクリーンショット 2021-02-04 23.24.10.png

さいごに

結構業務だと対策前進してしまうことも多いのですが、こうしたコマンドを知っておくことで気軽に?切り戻しができますね!

演習の解答サンプル

演習1

git checkout master
git log --oneline
---------------------------------------------------------------
8254890 (HEAD -> master, feature) Commit D
5a5afaf Commit C
09d38a1 Commit B
383454e Commit A
---------------------------------------------------------------

# git-reset はHEADの移動させるコマンドなので、コミットAを指定してあげれば良い
git reset --hard 383454e
git log --oneline
---------------------------------------------------------------
383454e (HEAD -> master) Commit A
---------------------------------------------------------------

演習2

git checkout master
git log --oneline
---------------------------------------------------------------
8254890 (HEAD -> master, feature) Commit D
5a5afaf Commit C
09d38a1 Commit B
383454e Commit A
---------------------------------------------------------------

# softでresetすれば良い
git reset --soft 383454e
git log --oneline
---------------------------------------------------------------
383454e (HEAD -> master) Commit A
---------------------------------------------------------------

演習3

git checkout master
git log --oneline
---------------------------------------------------------------
5b96ca7 (HEAD -> master) Merge branch 'feature'
2757f8e Commit A
914017f (feature) Commit D
711f950 Commit C
b66b20c Commit B
---------------------------------------------------------------

# この場合は普通にコミットDのコミットIDを指定してあげれば良いですね
git revert 914017f
git log --oneline
---------------------------------------------------------------
ad37cf4 (HEAD -> master) Revert "Commit D"
76572dd Merge branch 'feature'
8b4e87e Commit A
3912023 (feature) Commit D
7454740 Commit C
99f5f37 Commit B
---------------------------------------------------------------
5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?