488

どちらもプロジェクトを特定のコミットに戻すという意味で、私は常に と を同じものと考えてきましgit resetた。git checkoutただし、冗長になるため、まったく同じにすることはできないと思います。両者の実際の違いは何ですか?svn cosvnはコミットを元に戻すだけなので、少し混乱しています。

追加した

VonC と Charles は と の違いgit resetgit checkoutとてもよく説明してくれました。私の現在の理解では、git resetすべての変更を特定のコミットに戻しますが、git checkout多かれ少なかれブランチの準備をします。この理解を深めるには、次の 2 つの図が非常に役立ちます。

http://a.imageshack.us/img651/1559/86421927.png http://a.imageshack.us/img801/1986/resetr.png

追加 3

http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.htmlから、チェックアウトとリセットをエミュレートできますリベース。

ここに画像の説明を入力

git checkout bar 
git reset --hard newbar 
git branch -d newbar 

ここに画像の説明を入力

4

7 に答える 7

220
  • git reset具体的には、インデックスの更新、HEADの移動についてです。
  • git checkout作業ツリーを(インデックスまたは指定されたツリーに)更新することです。ブランチをチェックアウトした場合にのみHEADが更新されます(そうでない場合は、HEADが切り離されてしまいます)。
    (実際、Git 2.23 2019年第3四半期では、これはgit restore必ずしもそうとは限りませんgit checkout

比較すると、svnにはインデックスがないため、作業ツリーのみがsvn checkout特定のリビジョンを別のディレクトリにコピーします。
に近いものは次のようにgit checkoutなります。

  • svn update(同じブランチにいる場合、つまり同じSVN URLにいる場合)
  • svn switch(たとえば、同じブランチをチェックアウトするが、別のSVNリポジトリURLからチェックアウトする場合)

これら3つの作業ツリーの変更(svn checkout、、 )はすべてupdateswitchgitにコマンドが1つだけありますgit checkout
ただし、gitにはインデックス(リポジトリと作業ツリーの間の「ステージング領域」)の概念もあるため、もありますgit reset


Thinkeyeは、コメントの中で「 ResetDemystified」という記事に言及しています。

たとえば、異なるコミットを指す2つのブランチ' master'と' 'があり、現在' '(HEADがそれを指している)で実行すると、' '自体が同じコミットを指すようになります。'します。developdevelopgit reset masterdevelopmaster

一方、代わりに実行するgit checkout masterと、' develop'は移動せず、HEADそれ自体が移動します。HEAD''を指すようになりmasterます。

したがって、どちらの場合も、HEADコミットするポイントに移動しますAが、その方法は大きく異なります。resetは分岐HEAD点をに移動し、checkoutはHEADそれ自体を移動して別の分岐を指します。

http://git-scm.com/images/reset/reset-checkout.png

ただし、これらの点については次のとおりです。

LarsHはコメントに追加します:

ただし、この回答の最初の段落は誤解を招く可能性があります。「git checkout...ブランチをチェックアウトした場合にのみHEADを更新します(そうでない場合は、HEADが切り離されてしまいます)」。
正しくない:git checkoutブランチではないコミットをチェックアウトした場合でも、HEADを更新します(そうです、HEADが切り離されてしまいますが、それでも更新されます)。

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novoはコメントに同意します:

@LarsHは正しいです。
2番目の箇条書きには、ブランチをチェックアウトした場合にのみHEADが更新されるという誤解があります。
HEADは影のようにどこにいても行きます。
ブランチ以外の参照(タグなど)をチェックアウトするか、直接コミットすると、HEADが移動します。切り離されたヘッドは、HEADから切り離されたことを意味するのではなく、ヘッドがブランチrefから切り離されていることを意味します。これは、たとえば、から見ることができますgit log --pretty=format:"%d" -1

  • (HEAD ->アタッチされたヘッドの状態は、で始まります。
  • detachedは引き続き表示されますが(HEAD、ブランチ参照への矢印はありません。
于 2010-09-03T20:29:42.927 に答える
73

最も単純な形式ではreset、作業ツリーに触れずにインデックスをリセットし、インデックスに触れずに作業ツリーをcheckout変更します。

インデックスをリセットして一致させHEAD、作業ツリーをそのままにします。

git reset

概念的には、これはインデックスを作業ツリーにチェックアウトします。実際に何かを実行するには-f、ローカルの変更を強制的に上書きするために使用する必要があります。これは、「引数なし」形式が破壊的でないことを確認するための安全機能です。

git checkout

パラメータの追加を開始すると、いくつかの重複があるのは事実です。

checkout通常、ブランチ、タグ、またはコミットで使用されます。この場合、インデックスがリセットさHEADれ、指定されたコミットへのインデックスが作成され、作業ツリーへのインデックスのチェックアウトが実行されます。

また、提供--hardする場合は、作業ツリーを上書きするだけでなく、インデックスをリセットするようにreset依頼できます。reset

現在ブランチをチェックアウトしている場合は、代替ブランチまたはコミットを提供するときと提供するときで決定的な違いがresetあります。選択したコミットを指すように現在のブランチを変更しますが、現在のブランチはそのままにしますが、提供されたブランチをチェックアウトするか、代わりにコミットします。checkoutresetcheckout

他の形式のresetおよびcommitパスの提供を含みます。

パスを提供する場合、提供するresetことはできず、提供--hardresetれたパスのインデックスバージョンを提供されたコミットのバージョンに変更するだけです(またはコミットHEADを指定しない場合)。

にパスを指定すると、指定されたコミット(または)に一致するように指定されたパスのインデックスバージョンが更新されますが、指定されcheckoutたパスのインデックスバージョンは常に作業ツリーにチェックアウトされます。resetHEAD

于 2010-09-03T20:43:54.367 に答える
3

2 つのコマンド (リセットとチェックアウト) は完全に異なります。

checkout Xではありませんreset --hard X

X がブランチ名の場合 checkout X、現在のブランチは変更されませんが、変更されreset --hard Xません。

于 2015-09-11T16:01:15.550 に答える
0

あいまいさの説明は次のとおりです。

  • git checkout は HEAD を別のコミットに移動します (ブランチ名を使用して変更することもできます)が、 :
    1. どのブランチでも、そのブランチの先端 (「メイン」など) へのポインターは変更されません (そのため、頭が切り離された状態になる可能性があります)。

    2. また、ステージング領域と作業ディレクトリは変更されません (チェックアウト前と同様の状態で)。

例:

git checkout 3ad2bcf <--- checkout to another commit
git checkout another-branch <--- checkout to another commit using a branchname
  • git resetも HEADを移動しますが、ここでも2 つの違いがあります。

    1. 現在のブランチの先端にあるコミットを指すポインターも移動します。たとえば、現在のブランチへのポインターの名前が「main」で、git-reset を実行すると、メイン ポインターが別のコミットを指し、HEAD もそのコミットを指すようになります (基本的には、 HEADは、メイン ポインターを指すことによって間接的にそのコミットを指します。これはまだ接続された head(!)ですが、ここでは違いはありません)。

    2. Git-reset は、ステージング領域と作業ディレクトリを、リセットが実行される前と同じ状態にするとは限りません。ご存知のように、リセットには、ソフト、混合 (デフォルト)、およびハードの 3 つのタイプがあります。

      • ソフト リセットでは、ステージング領域と作業ディレクトリの両方がリセット前の状態のままになります (この点ではチェックアウトに似ていますが、違い 1 を忘れないでください)。
      • リセットのデフォルトのタイプである混合リセットでは、違い#1に加えて、ステージング領域の提案された次のコミット(基本的にgitで追加したもの)も、新しく指されたHEADに設定されます専念。ただし、作業ディレクトリでは、すべてのファイルに最新の編集内容が残っています (作業内容が失われないように、このタイプのリセットがデフォルトになっているのはそのためです)。
      • ハード リセットでは、相違点 #1 に加えて、HEAD、staging-area、および作業ディレクトリの 3 つのツリーすべてが、HEAD コミットによって新しく指定された場所に変更されます。

例:

git reset --soft 3ad2bcf
git reset da3b47
于 2021-10-02T05:40:13.847 に答える