LoginSignup
12
5
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

【Git】特定のコミットまで戻ってコードを確認したいだけのときは、git resetではなくgit switchを使おう

Posted at

はじめに

git reset --hard [コミットのハッシュ値]を実行すると、指定したコミット以降のコミット履歴が消去されてしまうので、
過去のコミット時のコードを一時的に見たいときは、コミット履歴に影響を与えないgit switch -d [コミットのハッシュ値]を使ったほうが良さそうということに気づきました。
git reset --hard [コミットのハッシュ値]を実行してコミット履歴を消去しても、一応復元できますが。)

筆者自身、詳しいことを知らずにgit reset --hard [コミットのハッシュ値]を使って焦ったことがあるので、両者の違いをまとめておきます。

サンプルの解説

以下のようなテキストファイルがあるとします。

sample.txt
first
second
third
fourth

ブランチについては、feature-1という作業ブランチにいるとします。

git branch
* feature-1
  main

コミットの履歴については、mainブランチで空のテキストファイルを作成したのち、最初のコミットをしています。
そして、feature-1ブランチを作成してそこに移動しています。

その後、add firstというコミットでテキストファイルにfirstを書いて、
add secondというコミットでテキストファイルにsecondを書いて、...
という流れになっています。

git log
commit 444444444444444 (HEAD -> feature-1)
Author: your name
Date:  Mon Jan 4 00:00:00 2024

    add fourth

commit 333333333333333
Author: your name
Date:  Mon Jan 3 00:00:00 2024

    add third

commit 222222222222222
Author: your name
Date:  Mon Jan 2 00:00:00 2024

    add second

commit 111111111111111
Author: your name
Date:  Mon Jan 1 00:00:00 2024

    add first

commit 000000000000000 (main)
Author: your name
Date: Sun Dec 31 00:00:00 2023

    first commit

(※実際には000000000000000などの部分はもっと長いハッシュ値になっています。以降も同様。)

git reset --hard をするとどうなるのか

はじめに、git reset --hard [コミットのハッシュ値]を実行するとどうなるのか見ていきましょう。

git reset --hart 222222222222を実行して、add secondコミットの状態にリセットを行うと、

ターミナル
HEAD is now at 2222222222 add second

と表示され、ファイルの中身は

sample.txt
first
second

になります。、add secondコミット時の状態になっていますね。

続いて、git branchでブランチを確認してみると、

git branch
* feature-1
  main

特に変化はないようです。

続いてgit logで履歴を見てみます。

git log
commit 222222222222222
Author: your name
Date:  Mon Jan 2 00:00:00 2024

    add second

commit 111111111111111
Author: your name
Date:  Mon Jan 1 00:00:00 2024

    add first

commit 000000000000000 (main)
Author: your name
Date: Sun Dec 31 00:00:00 2023

    first commit

見てのとおり、add second以降のコミットが消えてしまっています。

過去のコミットの状態にリセットしたいときはこの方法で良いと思います。
しかし、一時的に過去のコミットに戻ってコードを見たいだけの場合、git reset --hard [コミットのハッシュ値]を実行すると、最新のコミットに戻れなくなってしまいます

戻す方法について

git reset --hard [コミットのハッシュ値]を実行すると、最新のコミットに戻れなくなってしまう」と書きましたが、一応戻す方法はあるようです。

まず、git reflogを実行します。

git reflog
2222222 (HEAD -> feature-1) HEAD@{0}: reset: moving to 222222222222222
4444444 HEAD@{1}: commit: add fourth
3333333 HEAD@{2}: commit: add third
2222222 (HEAD -> feature-1) HEAD@{3}: commit: add second
1111111  HEAD@{4}: commit: add first
0000000 (main) HEAD@{5}: checkout: moving from main to feature-1
0000000 (main) HEAD@{6}: commit (initial): first commit

すると、このように操作履歴を見ることができます。

今回の場合、一行目の

git reflog
2222222 (HEAD -> feature-1) HEAD@{0}: reset: moving to 222222222222222

が、「git reset --hard [コミットのハッシュ値]でリセットを実行した操作に該当します。

リセットする前の状態、つまり二行目の

git reflog
4444444 HEAD@{1}: commit: add fourth

の状態に戻りたいので、
git reset --hard 4444444またはgit reset --hard HEAD@{1}を実行して、リセットする前の状態にリセットします。すると、

text.sample.txt
first
second
third
fourth

このように、ファイルの中身が最後のadd fourthコミットの状態に戻りました。

git logでログを見てみても、

git log
commit 444444444444444 (HEAD -> feature-1)
Author: your name
Date:  Mon Jan 4 00:00:00 2024

    add fourth

commit 333333333333333
Author: your name
Date:  Mon Jan 3 00:00:00 2024

    add third

commit 222222222222222
Author: your name
Date:  Mon Jan 2 00:00:00 2024

    add second

commit 111111111111111
Author: your name
Date:  Mon Jan 1 00:00:00 2024

    add first

commit 000000000000000 (main)
Author: your name
Date: Sun Dec 31 00:00:00 2023

    first commit

元に戻せているのが確認できます。

git switch -d を使うとどうなるのか

先ほどまでは、git reset --hard [コミットのハッシュ値]を使った場合を見てきました。

次にgit switch -d [コミットのハッシュ値]を使った場合を見ていきましょう。

add fourthまでコミットされた状態であることを確認して、

text.sample.txt
first
second
third
fourth
git log
commit 444444444444444 (HEAD -> feature-1)
Author: your name
Date:  Mon Jan 4 00:00:00 2024

    add fourth

commit 333333333333333
Author: your name
Date:  Mon Jan 3 00:00:00 2024

    add third

commit 222222222222222
Author: your name
Date:  Mon Jan 2 00:00:00 2024

    add second

commit 111111111111111
Author: your name
Date:  Mon Jan 1 00:00:00 2024

    add first

commit 000000000000000 (main)
Author: your name
Date: Sun Dec 31 00:00:00 2023

    first commit

git switch -d 222222222222222を実行してみると、

ターミナル
HEAD is now at 2222222 add second

と表示され、テキストファイルを見てみると、

sample.txt
first
second

add secondコミット時のファイルが表示されています。

git branchでブランチを見てみると、

git branch
* (HEAD detached at 2222222)
  feature-1
  main

現在(HEAD detached at 2222222)にいることがわかります。

ただしこれは、depatched HEADという状態であり、ブランチが作成されているわけではないので注意してください。
(この状態で作業をしても保存されません)

depatched HEADについては以下の記事がわかりやすいかと思います。

git logでコミットの履歴を見てみると、

git log
commit 222222222222222
Author: your name
Date:  Mon Jan 2 00:00:00 2024

    add second

commit 111111111111111
Author: your name
Date:  Mon Jan 1 00:00:00 2024

    add first

commit 000000000000000 (main)
Author: your name
Date: Sun Dec 31 00:00:00 2023

    first commit

指定したコミットとそれ以前のコミットが表示されています。

add thirdadd fourthコミットが消えているように見えますが、実際は消えておらず、feature-1ブランチに戻ると、きちんと全て表示されます。

git switch feature-1でもとのブランチに戻ってみると、

text.sample.txt
first
second
third
fourth

最後のadd fourthコミットの状態になっていることがわかります。
git logで履歴を見てみても、

git log
commit 444444444444444 (HEAD -> feature-1)
Author: your name
Date:  Mon Jan 4 00:00:00 2024

    add fourth

commit 333333333333333
Author: your name
Date:  Mon Jan 3 00:00:00 2024

    add third

commit 222222222222222
Author: your name
Date:  Mon Jan 2 00:00:00 2024

    add second

commit 111111111111111
Author: your name
Date:  Mon Jan 1 00:00:00 2024

    add first

commit 000000000000000 (main)
Author: your name
Date: Sun Dec 31 00:00:00 2023

    first commit

コミットの履歴が全て残っていることが確認できます。

ちなみにこの状態で、git branchでブランチ一覧を表示させると、

git branch
* feature-1
  main

先ほどまであった(HEAD detached at 2222222)が無くなっていることがわかります。

これは、(HEAD detached at 2222222)depatched HEADという状態であり、ブランチが実際に作成されているわけではないためです。そのため、他のブランチに移動してしまうと(HEAD detached at 2222222)は消えてしまいます。

depatched HEADを避けるには

depatched HEAD状態を避けた状態で過去のコミットに戻りたいときは、ブランチを作ってあげる必要があります。

git switch -c [作成するブランチの名前] [コミットのハッシュ値]
または
git switch -d [コミットのハッシュ値]を実行してdepatched HEADの状態でgit switch -c [作成するブランチの名前]
を実行すると、特定のコミットの状態のブランチを作った上で、そのブランチに移動できます。

試しに、feature-1ブランチにいる状態で

sample.txt
first
second
third
fourth

git switch -c add-second 222222222222222を実行すると、

sample.txt
first
second
git branch
* add-second
  feature-1
  main

add secondコミットの状態になっており、さらにadd-secondブランチが作成されていることがわかります。

switchの代わりにcheckoutも使える

ちなみにcheckoutコマンドを使っても、同じようなことができます。

git checkout 222222222222222を実行すると、

ターミナル
NOTE: switching to '222222222222222'.

You are in 'detached HEAD' state. 以下略

HEAD is now at 2222222 add second
sample.txt
first
second
git branch
* (HEAD detached at 2222222)
  feature-1
  main

となります。

おわりに

間違い等ございましたら、教えていただけますと幸いです。

参考文献

12
5
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
12
5