Git resetとcheckoutの違い

git reset, git checkoutともに作業スペース、ステージ、ローカルレポジトリ内のファイル群を操作しますが、プロセスに少し違いがあります。

パス指定なしの場合

レポジトリHEAD の更新方法が大きく異なります。 reset の場合はブランチの方が移動するのに対し、 checkout の場合は HEAD のそのものが別ブランチに移動します。

具体例を挙げて説明しましょう。 master と develop の 2 つのブランチが異なるコミットを指し示していて、 develop の方をチェックアウトしているとします(HEAD は後者の方を向いた状態です)。 ここで git reset master を実行すると、 master ブランチの最新のコミットを develop ブランチも指し示すようになります。 ですが、代わりに git checkout master を実行しても、 develop ブランチは移動しません。HEAD が移動するのです。 その結果、HEAD は master の方を指し示すようになります。

どちらの場合でも HEAD がコミット A を指すようになるという意味では同じですが、 どのように それが行われるかはずいぶん違います。

resetの場合は HEAD が指し示すブランチの方が移動するのに対し、 checkoutの場合は HEAD そのものが移動するのです。

パス指定ありの場合

checkout はパスを指定して実行することも出来ます。その場合、 resetと同様、HEAD が動くことはありません。

実行されると指定したコミットの指定したファイルでインデックスの内容を置き換えます。 git reset [branch] file と同じ動きです。

しかし、 checkout の場合は、さらに作業 デ ィ レ ク ト リ の フ ァ イ ル も 置 き 換 え ま す 。 git reset --hard[branch] file を実行しても、まったく同じ結果になるでしょう(実際には reset ではこういうオプションの指定はできません)。作業ディレクトリを保護してはくれませんし、HEAD が動くこともありません。

また、 checkout にも git reset や git add のように --patch オプションがあります。これを使えば、変更点を部分ごとに巻き戻していけます。