web-dev-qa-db-ja.com

「gitreset--hardhash」と「gitcheckouthash」に違いはありますか?

resetcheckoutの使用法はほとんどの場合異なりますが、これら2つの間にどのような違いがあるのか​​わかりません。

基本的なcheckoutが実行できることを実行するために--hardオプションを追加することを気にしない人がおそらく1人または誰もいないでしょう。

たぶん、あなたが歴史を見る方法に違いがありますか?

43
e-satis

この回答は、主に前の質問に対する私の回答から引用されています: 平易な英語でのgitリセット

2つは非常に異なります。インデックスと作業ツリーの状態は同じになりますが、結果の履歴と現在のブランチは同じではありません。

マスターブランチが現在チェックアウトされている状態で、履歴が次のようになっているとします。

- A - B - C (HEAD, master)

git reset --hard Bを実行します。あなたはこれを得るでしょう:

- A - B (HEAD, master)      # - C is still here, but there's no
                            # branch pointing to it anymore

--mixedまたは--softも使用すると、実際にその効果が得られます。唯一の違いは、作業ツリーとインデックスに何が起こるかです。 --hardの場合、作業ツリーとインデックスはBと一致します。

ここで、代わりにgit checkout Bを実行するとします。あなたはこれを得るでしょう:

- A - B (HEAD) - C (master)

切り離されたHEAD状態になりました。HEAD、作業ツリー、インデックスはすべてBに一致します。ハードリセットの場合と同じですが、マスターブランチはCに残されました。この時点で新しいコミットDを行うと、これが得られますが、これはおそらくあなたが望むものではありません。

- A - B - C (master)
       \
        D (HEAD)

したがって、チェックアウトを使用して、そのコミットをチェックアウトします。あなたはそれをいじって、あなたが好きなことをすることができます、しかしあなたはあなたの枝を置き去りにしました。ブランチも移動する場合は、リセットを使用します。

57
Cascabel

Gitで提供されているドキュメントが役に立たない場合は、Mark Lodatoによる A Visual Git Reference をご覧ください。

特に、git checkout <non-branch>git reset --hard <non-branch>(ホットリンク)を比較している場合:

git checkout master~3
(ソース: github.com

git reset --hard master~3

git reset --hard master~3の場合、リビジョンのDAGの一部を残すことに注意してください。一部のコミットは、どのブランチからも参照されません。それらは(デフォルトで)30日間reflog;によって保護されます。それらは最終的に剪定(削除)されます。

15
Jakub Narębski

git-reset hashは、指定されたハッシュへのブランチ参照を設定し、オプションでそれをチェックアウトします。with--hard

git-checkout hash作業ツリーを指定されたハッシュに設定します。ハッシュがブランチ名でない限り、ヘッドが切り離されてしまいます。

最終的に、gitは3つのことを扱います:

                   working tree (your code)
-------------------------------------------------------------------------
                     index/staging-area
-------------------------------------------------------------------------
      repository (bunch of commits, trees, branch names, etc)

git-checkoutデフォルトでは、インデックスと作業ツリーを更新するだけで、オプションでリポジトリ内の何かを更新できます(-bオプション)

git-resetデフォルトでは、リポジトリとインデックス、およびオプションで作業ツリーを更新するだけです(--hardオプション)

リポジトリは次のように考えることができます。

 HEAD -> master

 refs:
    master -> sha_of_commit_X
    dev -> sha_of_commit_Y

 objects: (addressed by sha1)

    sha_of_commit_X, sha_of_commit_Y, sha_of_commit_Z, sha_of_commit_A ....

git-resetブランチ参照が指すものを操作します。

履歴が次のようになっているとします。

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic2][topic3]

ブランチは、コミットすると自動的に進む名前にすぎないことに注意してください。

したがって、次のブランチがあります。

 master -> Q
 dev -> Q
 topic1 -> G
 topic2 -> W
 topic3 -> W

そしてあなたの現在のブランチはtopic2、つまり、HEADはtopic2を指します。

HEAD -> topic2

次に、git reset Xは名前をリセットしますtopic2Xを指す;つまり、ブランチtopic2でコミットPを実行すると、次のようになります。

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic3]
                           \
                            P [topic2]
6
hasen