「git reset --hard HEAD~1」と「git reset --soft HEAD~1」の違いは何ですか? 質問する

「git reset --hard HEAD~1」と「git reset --soft HEAD~1」の違いは何ですか? 質問する

Git でコミットを取り消そうとしました。使用するのは危険ですかgit reset --hard HEAD~1?

のさまざまなオプションの違いは何ですかgit reset?

注: HEADは現在/最新のコミットですが、HEAD~1はHEADの直前のコミットです

ベストアンサー1

git resetには、ソフト、ミックス、ハード、マージ、キープの 5 つの「モード」があります。通常、これらのモードが使用されるため、最初の 3 つから説明します。その後に、ちょっとしたおまけがありますので、お楽しみに。


次のような履歴を持つリポジトリがあると仮定します。

7e05a95  (HEAD -> main) Update a
e62add5  Update b
ca9ae0a  Update a
9b6060d  Add c
eebe372  Add b
947586a  Add a

最新のコミット ( 7e05a95) には次の変更が含まれています:

diff --git a/a b/a
index b66ba06..28b68e2 100644
--- a/a
+++ b/a
@@ -1 +1 @@
-new content
+new new content

git resetでは、さまざまなモードで実行すると何が起こるでしょうか? 調べてみましょう!

柔らかい

を使用すると、git reset --soft HEAD~1現在のブランチから最後のコミットが削除されますが、ファイルの変更はそのまま残ります。作業ツリーまた、変更はインデックスに残るため、 を続けて実行すると、git commit前に「削除」したコミットとまったく同じ変更を含むコミットが作成されます。

これは実際にはどのように見えるでしょうか? 次のようになります:

> git reset --soft HEAD^ # Assuming HEAD points at 7e05a95
> git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   a

ご覧のとおり、ファイルの変更はaインデックス上にあり、再度コミットする準備ができています。

混合

これはデフォルトのモードで、soft と非常によく似ています。 でコミットを「削除」すると、git reset HEAD~1作業ツリー内の変更は保持されますが、インデックスには保持されません。そのため、コミットを「やり直す」場合は、コミットする前に変更を追加する必要があります ( git add)。

実際には、結果は次のようになります。

> git reset --mixed HEAD^ # Assuming HEAD points at 7e05a95
> git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   a

no changes added to commit (use "git add" and/or "git commit -a")

ファイルの変更はaまだ残っていますが、インデックスには表示されません。

難しい

git reset --hard HEAD~1使用するとコミットされていない変更と追跡されていないファイルをすべて失う最後のコミットで導入された変更に加えて、変更は作業ツリーに残らないため、コマンドを実行するとgit statusリポジトリに変更がないことがわかります。

これについては慎重に扱ってください。 によって追跡されていないgit(コミットされていない、または少なくともインデックスに追加されていない) 未コミットの変更を誤って削除した場合、 を使用してそれらを元に戻す方法はありませんgit

実際の例は次のようになります。

> git reset --hard HEAD^ # Assuming HEAD points at 7e05a95
> git status
On branch main
nothing to commit, working tree clean

ご覧のとおり、変更は残っていません。ファイルにコミットされていない変更もあったとすると、bそれらも失われます。

> echo 'some uncommitted changes' > b
> git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   b

no changes added to commit (use "git add" and/or "git commit -a")

> git reset --hard HEAD^ # Assuming HEAD points at 7e05a95
> git status
On branch main
nothing to commit, working tree clean

ボーナス

保つ

git reset --keep HEAD~1興味深い便利な機能です。現在 HEADおよび指定されたコミット。これらのファイルの 1 つ以上にコミットされていない変更がある場合は、リセットを中止します。基本的には、 のより安全なバージョンとして機能しますhard

コミットされていない変更がいくつかある、以前の例をもう一度見てみましょうb

> echo 'some uncommitted changes' > b
> git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   b

no changes added to commit (use "git add" and/or "git commit -a")

> git reset --keep HEAD^ # Assuming HEAD points at 7e05a95
> git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   b

no changes added to commit (use "git add" and/or "git commit -a")

ファイルの変更は削除されましたaが、ファイル内のコミットされていない変更は保持されていますb

繰り返しになりますが、「ハード」は削除します全て「keep」はリセットコミットからの変更のみを削除します。


これらのモードのそれぞれについては、git リセットのドキュメント

注記
コミットを削除すると、git resetコミットは実際には失われません。コミットまたはその子を指す参照がなくなるだけです。git resetたとえば、 などのコマンドを使用して、 で「削除」されたコミットの SHA-1 キーを見つけることで、コミットを復元できますgit reflog

おすすめ記事