「git reset」と「git checkout」の違いは何ですか?


440

私はいつも考えてきたgit resetgit checkoutの両方の特定のコミットにプロジェクトのバックを持っているという意味で、同じよう。ただし、冗長になるため、完全に同じにすることはできません。2つの実際の違いは何ですか?svn svn coはコミットを元に戻すだけでよいので、少し混乱しています。

追加された

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 

ここに画像の説明を入力してください



再:「それは間違っているか、過度に単純化されていますか?」はい、最初の図は、チェックアウトとリセットの違いに関して誤解を招くものです。(-- filesバリアントに関しては問題ないかもしれませんが、わかりません。)この図は、主な違いがインデックスとWDのどちらに影響するかを示しているように見えます。それに関する私の答えを見てください。2番目と3番目の図は、実際の違いを確認するのに非常に役立ちます。4番目と5番目の図は、これらのコマンドの機能を理解しているかどうかを確認するのに役立ちますが、実際の目的には役立ちません。
LarsH

「Git Tools Reset Demystified」の「Check it out」セクションを見つけて、最も役立つ要約を提供しました。
Josiah Yoder

1
prosseek:最初の図が誤解を招くものであると@LarsHに同意した場合、それを削除してもらえますか?
Josiah Yoder

チェックアウトとリセットはリベースの2番目の部分をエミュレートするだけでありthink-like-a-git.net、データの損失を防ぐために追加の手順(リンクされた記事で提供)が必要であることに注意してください。
カウリネーター

回答:


198
  • 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 checkoutupdateswitch)のgitに一つだけのコマンドがありますgit checkout
しかし、gitにはインデックス(リポジトリと作業ツリーの間の「ステージング領域」)の概念もあるので、も持っていgit resetます。


Thinkeyeコメントの中で記事「リセットされた謎解き」について言及しています

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

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

したがって、どちらの場合もHEAD、コミットを指すように移動しますAが、その方法は大きく異なります。reset分岐HEAD点に移動し、チェックアウトは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が移動します。デタッチされたヘッドは、HEADからデタッチされたことを意味するのではなく、ヘッドがブランチ参照からデタッチされたことを意味しますgit log --pretty=format:"%d" -1

  • 取り付けられたヘッド状態が始まります(HEAD ->
  • detachedは引き続き表示されますが(HEAD、ブランチ参照への矢印はありません。

7
これgit resetは、ブランチの「ラベル」を変更し、オプションで副作用としてインデックスまたは作業ツリーを更新することについてだと思います。git checkout作業ツリーを更新し、現在「選択された」ブランチ(HEAD)を切り替えることです。
Mikko Rantalainen 2013

2
@MikkoRantalainenいいえ。git resetについては100%HEADです。分離されたHEADモード(stackoverflow.com/a/3965714/6309)、つまりブランチ(!)がない場所でも機能します。git checkoutは、分離されたHEADモードでも機能します。または、分離されたHEADモードでSHA1をチェックアウトするために使用できます。この場合も、ブランチは含まれません。
VonC、2013

3
検索エンジンによってここに送信されたすべての失われた魂についてさらに読むと、それは価値があると思います:git-scm.com/blog/2011/07/11/reset.html
Thinkeye

2
@Thinkeyeの良いリファレンス。私はそれを関連する抜粋とともに回答の中に含めて、より多くの可視性を実現しました。
VonC、2014

2
Reset Demystifiedからの説明はすばらしい。ただし、この回答の最初の段落は誤解を招く可能性があります。「git checkout ... は、ブランチをチェックアウトした場合にのみHEADを更新します(そうでない場合、分離したHEADになります)。trueではない... ブランチではないコミットをチェックアウトしても、 git checkout はHEADを更新します(そうです、結局、分離されたHEADになりますが、それでも更新されます)。多分私はあなたが「更新」の意味を誤解していますか?git checkout a839e8fコミットするようにHEADを更新しますa839e8f
LarsH 2018

67

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

インデックスをmatchにリセットしHEAD、作業ツリーをそのままにします。

git reset

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

git checkout

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

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

また、あなたが提供する場合--hardresetご依頼することができreset、インデックスをリセットするだけでなく、作業ツリーを上書きします。

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

その他の形式resetおよびcommit供給経路が含まれます。

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

あなたはへのパスを指定した場合checkoutと同様に、resetそれは供給コミット(または一致に供給されたパスのインデックスバージョンに更新されますHEAD)を、それは常に作業ツリー内に供給されたパスのインデックスバージョンをチェックアウトします。


2
「チェックアウト」がインデックスを変更しないと言うのは間違いです。ブランチから別のブランチに移動するために使用されると、インデックスが変更されます。
wiki1000

最も単純な形式では、リセットは作業ツリーに触れずにインデックスをリセットし、チェックアウトは索引に触れずに作業ツリーを変更します。:それはどのように混乱するのですか:|
Aditya Gupta

41

変更を元に戻す場合の1つの簡単な使用例:
1.変更されたファイルのステージングを元に戻す場合は、リセットを使用します。
2.ステージングされていないファイルへの変更を破棄する場合は、チェックアウトを使用します。


1
完璧な答え。ありがとうございました。
user358591 2018

11

一言で言えば重要な違いは、あるreset 移動現在の分岐参照しながら、checkoutしない(それはヘッドを移動します)。

Pro Gitの本で「Demystifiedのリセット」で説明されているように、

最初resetに行うことは、HEADが指すものを移動することです。これはHEAD自体変更することと同じではありません(これは何をするかcheckoutです)。HEADが指してreset いるブランチ移動します。つまり、HEADがmasterブランチに設定されている場合(つまり、現在masterブランチにいる場合)は、git reset 9e5e6a4masterポイントすることで実行が開始され 9e5e6a4ます。【強調追加】

同じ記事からの非常に役立つテキストと図の抜粋については、VonCの回答も参照してください。ここでは重複しません。

もちろん、使用されるパラメーターに応じて、インデックスと作業ツリーにどのような影響がcheckoutあり、どのような影響を与えるreset可能性があるかについて、より多くの詳細があります。2つのコマンドには多くの類似点と相違点があります。しかし、私が見ているように、最も重要な違いは、彼らが現在の枝の先端を動かすかどうかです。


2
私の以前の答えに加えて、良いフィードバック。+1
VonC 2018

2

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

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

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


2
しかし、Xがファイルまたはフォルダーである場合、それらは同じです。
テッドビガム2017

1

簡単なニーモニック:

git reset HEAD           :             index = HEAD
git checkout             : file_tree = index
git reset --hard HEAD    : file_tree = index = HEAD
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.