git checkout コマンドで使われる -- の意味


Git を使い始めたというみなさん, git checkout -- <file> というコマンドで使われる -- の意味ってなんなんだろうかと疑問になったことはありませんか.

例えば example というディレクトリを git init で Git レポジトリにして README.md というファイルを作成し, それを git add README.md で Index に追加し最初のコミットをしたとします:

mkdir example
cd example
git init
touch README.md
git add README.md
git commit -m "Initial commit"

そして README.md を次のように変更したとします:

echo "This is the first line." > README.md

git status を打つと次のようなメッセージが表示されます:

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   README.md

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

すると, 次の行に -- が書かれています:

  (use "git checkout -- <file>..." to discard changes in working directory)

この意味は working directory 内の変更を破棄するんだったら, git checkout -- <file> を使ってねということです.

なので先ほど変更した README.md の変更を破棄するんだったら次のように打ち込んでくれということです:

git checkout -- README.md

このコマンドを打つと README.md から先ほど追加した This is the first line. という行が削除されることになります.

それはいいのですが, どうして -- を指定する必要があるのでしょうか?

ということで今回の内容の趣旨にようよくたどり着くことができました.

一体どうしてなんでしょうね?

答えはずばりブランチの名前と重なってしまうのを防ぐためです.

正確にはブランチだけではないのですが, 今回は便宜的にそういうことにされていただきます.

つまりは現在のブランチの名前は master ですが, もし何を思ったか僕が README.md というブランチを作成した場合:

git branch README.md

もし次のように打つと:

git checkout README.md

README.md というファイルの変更を破棄するのではなく, README.md というブランチをチェックアウトすることになってしまいます.

そもそも README.md という名前でブランチを作る人はちょっとどうかと思いますが…

でも次のようにすると:

git checkout -- README.md

README.md というブランチをチェックアウトするのではなく, ちゃんと README.md というファイルの変更を破棄してくれます.

README.md はブランチ名ではなく, ファイル名だということを Git に正確に使えるために, 曖昧さをなくすために -- を指定するということだったんです.

確かに README.md というブランチが存在しなければ, 次のように打っても:

git checkout README.md

README.md というファイルの変更が破棄されることになりますが, 変更を破棄するたびに “このファイル名と同じ名前のブランチは存在しなかったかな” と考えるのは僅かですがコストがかかるので, そういう煩わしさを少しでも減らすということでファイルの変更を git checkout で破棄するときは常に -- を指定してそのあとにファイル名を続けるといいかと思います.

ということでした.

最後までお読みくださいましてありがとうございました.