"git checkout <filename>"和"git checkout -- <filename>"之间的区别是什么?

141

1
请参阅 Git checkout双破折号的含义 - user456814
4个回答

267

特殊的“选项”--意味着“将此点之后的每个参数视为文件名,无论其外观如何”。这不是Git特有的,而是一般Unix命令行约定。通常情况下,您使用它来说明参数是文件名而不是选项,例如:

rm -f      # does nothing
rm -- -f   # deletes a file named "-f"

git checkout1也可以使用--,表示后面的参数不是可选的 "treeish" 参数,该参数用于指定您想要的提交。

因此,在这种情况下,始终使用--安全的,但当您要恢复的文件名称以-开头或与分支的名称相同时,您就需要使用它。以下是一些分支/文件消歧的示例:

git checkout README     # would normally discard uncommitted changes
                        # to the _file_ "README"

git checkout master     # would normally switch the working copy to
                        # the _branch_ "master"

git checkout -- master  # discard uncommitted changes to the _file_ "master"

并且选项/文件消歧:

git checkout -p -- README  # interactively discard uncommitted changes
                           # to the file "README"

git checkout -- -p README  # unconditionally discard all uncommitted
                           # changes to the files "-p" and "README"

如果你有一个以-开头的分支,我不确定该怎么做。也许最好一开始就不要这样做。


1在这个模式下,“checkout”还可以做其他几件事情。我不明白为什么git选择将“放弃未提交的更改”作为“checkout”子命令的一种模式实现,而不是像大多数其他版本控制系统那样实现“恢复”或者像我认为在git自己的术语中更合理的"reset"。


14
git checkout <name> 会切换到分支 <name>。git checkout -- <name> 会将文件 <name> 切换为暂存区中的版本。 - dunni
3
谢谢,不幸的是git文档没有很好地解释这个问题。 - Carlton
1
关于“Unix惯例”:确实,--作为选项和参数之间的分隔符被广泛实现。它适用于任何使用POSIX getopt(3)处理其命令行选项的程序/实用程序(请参见man 3 getopt),使用getopt(1)的shell脚本以及一些自己实现它的程序,但不能保证在所有情况下都能正常工作。 - arielf
1
哈!我曾经读过一个关于如何丢弃工作更改的例子,当时忘记了在其他命令行程序中看到这种约定,认为 -- 意味着“否定更改”,就像 C/C++ 一样 - 从那以后我一直这么想。我的思维被震撼了! - underscore_d
像我这样的人:不要被“master”这个名称所困惑,它指的是文件名为master而不是分支。 - HarsH
@HarsH,你觉得回答的哪一部分让你感到困惑了?我想澄清一下。 - zwol

11

--后面的任何内容都被视为文件名(而不是程序参数)。这一点非常重要,比如当你有以破折号开头的文件名时。


这是最好的答案。它简短明了。 - F.Tamy

0
git checkout -- filename

将使用索引(暂存区)中的文件版本替换您在工作目录中拥有的版本。

git checkout filename

将尝试检出与同名的分支,如果不存在,则执行与 git checkout -- <filename> 相同的操作。


0

git checkout <filename>git checkout -- <filename> 的区别在于如何处理未合并的更改。

git checkout <filename> 会放弃当前分支中的更改,并用指定分支或提交版本中的文件替换它。如果文件中有未合并的更改,则此命令将失败并显示错误消息。

git checkout -- <filename> 会放弃文件中的所有更改,包括任何未合并的更改。当您想要完全放弃本地更改并重新开始使用指定分支或提交版本的版本时,这非常有用。

总之,git checkout <filename> 用于切换到文件的特定版本,同时保留已合并到当前分支的更改,而 git checkout -- <filename> 则放弃文件中的所有更改,包括未合并的更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接