環境
Ubuntu 20.4
Git 2.25
はじめに
git resetの3つのオプションの違いについて書いてみました。
- --soft
- --mixed
- --hard
--mixed
ステージングエリアだけをクリアし、ワーキングディレクトリはクリアしません。git addした後、「このまま、commitしないで、やっぱり取り止めよう」となった場合に使います。
--hard
ワーキングディレクトリが、過去のコミット履歴の状態に戻ります。ステージングエリアに上がっているファイルがあればクリアされます。
--soft
コミットの取り消しだけが行なわれます。ステージングエリアとワーキングディレクトリの内容は、クリアされず現状のまま残ります。
--mixedの動き
test1.txtとtest2.txtの2つのファイルを修正した後、ステージングエリアに上げます。
$git add .
$git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: test1.txt
new file: test2.txt
2つファイル共、ステージングエリアから降ろされました。ステージングエリアから降りても、ワーキングディレクトリがクリアされることはありません。現状のワーキングディレクトリの内容でそのまま残ります。
$git reset --mixed
$git status
Untracked files:
(use "git add <file>..." to include in what will be committed)
test1.txt
test2.txt
複数のファイルがステージングエリアに上がっている場合、ファイルを指定してステージングエリアから降ろすことができます。test1.txtとtest2.txtがステージングエリアに上がっていて、test1.txtだけを、ステージングエリアから降ろしました。test2.txtだけが、ステージングエリアに残っている状態です。
$git add .
$git reset test1.txt
$git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: test2.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
test1.txt
test2.txtもステージングエリアから降ろすと、ステージングエリアに上がっているファイルはゼロになりました。
$git reset test2.txt
$git status
Untracked files:
(use "git add <file>..." to include in what will be committed)
test1.txt
test2.txt
次の2つのコマンドの動きは同じです。--mixedは省略することができます。
$git reset
$git reset --mixed
次の3つのコマンドの動きはすべて同じです。
$git reset
$git reset .
$git reset ./
--hardの動き
コミットをした後、ファイルを修正して、次のコマンドを実行すると、直前にコミットをした状態に戻ります。つまり、ワーキングディレクトリの内容がクリアされます。git addでステージングエリアに上げている状態であれば、ステージングエリアの内容もクリアされます。
$git add .
$git reset --hard
$git status
nothing to commit, working tree clean
HEADより一つ下の履歴に戻す場合です。下記の2つのコマンドは同じです。HEAD^の代わりに、履歴IDを指定して、複数の履歴を横断して、過去の履歴に戻すことができます。
$git reset --hard HEAD^
$git reset --hard 4c0a5a0
HEADは省略して書くことができます。つぎの2つのコマンドは同じです。
$git reset --hard
$git reset --hard HEAD
コミットされたファイルが複数存在する場合、特定のファイルを指定して、コミットを取り消すといったことはできません。次のコマンドは全てエラーになります。test1.txtとtest2.txtの2つのファイルがコミットされている状態で、test1.txtだけを復活させて、test2.txtはコミットされた状態のままにしておくといったことはできません。
$git reset --hard . # エラー
$git reset --hard ./ # エラー
$git reset --hard test1.txt # エラー
--softの動き
test1.txt、test2.txtの2つのファイルを修正して、ステージングエリアにあげます。
$git add .
$git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test1.txt
modified: test2.txt
次のコマンドで、HEADよりも1個前の履歴を復活させました。しかし、ワーキングディレクトリが復元されることはありません。現状のワーキングディレクトリの内容のままです。ステージングエリアに上がっている2つのファイルも、引き続き、ステージングエリアに上がっている状態のままです。
$git set --soft HEAD^
$git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test1.txt
modified: test2.txt
履歴IDを直接指定して、復元させることもできます。
$git reset --soft HEAD^
$git reset --soft caddd1
HEADよりも3個過去の履歴に戻す場合です。2つのコマンドはどちらも同じです。
$git reset --soft HEAD^^^
$git reset --soft HEAD~3