Git 2.23 引入了一个新命令git switch
——阅读文档后,它似乎与git checkout <branchname>
基本相同。有人可以解释一下区别或使用情况吗?
引入了两个新命令“git switch”和“git restore”,将“检出要推进其历史记录的分支”和“从索引和/或树状结构中检出路径以在推进当前历史记录上工作”从单个“git checkout”命令中拆分出来。
Git 2.23 引入了一个新命令git switch
——阅读文档后,它似乎与git checkout <branchname>
基本相同。有人可以解释一下区别或使用情况吗?
引入了两个新命令“git switch”和“git restore”,将“检出要推进其历史记录的分支”和“从索引和/或树状结构中检出路径以在推进当前历史记录上工作”从单个“git checkout”命令中拆分出来。
根据您提供的文档,它的唯一目的是分离和澄清两种不同使用方式的git checkout
:
git switch
现在可以用来更改分支,就像git checkout<branchname>
一样git restore
可以用来将文件重置为某个版本,就像git checkout --<path_to_file>
一样人们对于这些不同的git checkout
使用方式感到困惑,正如您在Stackoverflow上看到的关于git checkout
的许多问题所示。Git开发人员似乎已经考虑到了这一点。
git checkout
切换分支?git checkout
获取某个文件的特定版本?git checkout
撤销对一个文件的更改?git checkout
说实话,我在思考能否用 git checkout
的各种标志完成正常的 git 工作流程。 - Captain Mangit checkout
在技术上已经不再需要用于任何事情了吗?还是它仍然用于某些特定的事情,比如检出一个不是分支头的提交(进入“分离头”模式)? - PieterNuyts-b
标志的内部工作方式如何,它仍然会创建一个分支。 - Captain Mangit checkout -b <分支名称>
的人,您可以使用 git switch -c <分支名称>
来实现相同的效果。 - Defaultgit checkout
是一个瑞士军刀般的工具,因为它有几个不相关的用途。
如果您修改了一个文件但尚未暂存更改,则 git checkout <filename>
将撤消这些修改... 这是一种取消文件更改的快速简便方法。您仍然停留在同一分支。
git checkout <branchname>
(如您所指出的)则切换分支。
这是两个完全不同的目的,如果文件名和分支名相似,可能会导致混淆。
将其作为两个命令使用更清晰易懂。
git checkout <name>
会优先选择分支而不是文件。 - Kartik Sonejigit checkout <filename>
常常可以正常工作,但是更好的方法是使用git checkout -- <filename>
,因为--
明确地告诉git
解析器已经传递给git checkout
的选项已经结束,而且一个文件或目录路径列表已经开始了。这可能很重要,例如,如果您的文件名以破折号开头,比如-myfile
。在这种情况下,执行git checkout -- -myfile
应该可以正常工作,如果没有前面的--
,-myfile
看起来就像是传递给git checkout
的一个乱七八糟的选项。 - Gabriel Staplesswitch
命令确实与checkout
命令执行相同的操作,但仅适用于切换分支的情况。特别是,与checkout
不同的是,它不能恢复工作树文件,而是使用与switch
同时引入的restore
命令来完成。
正如您在引用的2.23.0版本发布说明中所指出的,switch
和restore
命令被引入以将checkout
命令拆分为两个独立的部分:
换句话说,checkout
执行两个不同的操作,而此版本将每个操作拆分为自己专注的命令。
可以从文档中的摘要描述中看出checkout
的这种双重目的:
添加了git-checkout - 切换分支或恢复工作树文件
switch
命令的提交在其提交消息中解释了新命令的原因:
从这个说明可以清楚地看出,引入新命令是为了通过拥有两个专注的命令而减少混淆,而不是一个多功能命令。“git checkout”做太多事情会让许多用户感到困惑(甚至有时候会让老手们感到困惑)。为了解决这个问题,该命令将被拆分为两个新命令:switch和restore。好老的“git checkout”命令仍然存在,并且将一直存在,直到所有用户(或大多数用户)对其感到厌倦。
switch
,restore
):
此命令是实验性的。行为可能会发生变化。
以前的命令 | 新的命令 |
---|---|
git checkout <branch> |
git switch <branch> |
git checkout |
N/A(使用git status ) |
git checkout -b <new_branch> [<start_point>] |
git switch -c <new-branch> [<start-point>] |
git checkout -B <new_branch> [<start_point>] |
git switch -C <new-branch> [<start-point>] |
git checkout --orphan <new_branch> |
git switch --orphan <new-branch> |
git checkout --orphan <new_branch> <start_point> |
N/A(先使用git switch <start-point> ,然后使用git switch --orphan <new-branch> ) |
git checkout [--detach] <commit> |
git switch --detach <commit> |
git checkout --detach [<branch>] |
git switch --detach [<branch>] |
git checkout [--] <pathspec>… |
git restore [--] <pathspec>… |
git checkout --pathspec-from-file=<file> |
git restore --pathspec-from-file=<file> |
git checkout <tree-ish> [--] <pathspec>… |
git restore -s <tree> [--] <pathspec>… |
git checkout <tree-ish> --pathspec-from-file=<file> |
git restore -s <tree> --pathspec-from-file=<file> |
git checkout -p [<tree-ish>] [--] [<pathspec>…] |
git restore -p [-s <tree>] [--] [<pathspec>…] |
checkout
)替换为新命令名称(switch
,restore
)来转换,而其他一些则需要额外的调整。值得注意的变化包括:
-b
/-B
已更名为-c
/-C
。它们还有长选项变体(--create
/--force-create
),而以前它们只有单字母选项版本。--detach
(或-d
),而以前对于提交来说是可选的,但对于分支来说是必需的。-s
(或--source
)选项给出,而不是作为内联参数。--force
(或-f
)进行切换现在如果存在未合并的条目将会失败,而不是忽略它们。--force
也已更名为--discard-changes
,而--force
仍然保留作为别名。switch
有一些限制:目前您可以从任何提交切换到 <分支名称>
,但无法从带有 detached HEAD 状态的 <分支名称>
切换到特定的提交。因此,您需要使用 git checkout 5efb
(其中5efb是任意提交的哈希引用示例)。
switch
的创建目的是用于切换分支,当你这样做时,你确实希望处于该分支的 HEAD。checkout
是一种更通用的操作,可以将您的工作副本与历史记录中的任何给定状态(=提交)保持一致。由于任何分支名称都是该分支的 HEAD 提交的别名,因此检出分支在技术上与检出任何其他提交没有区别。 - Mike-d
参数,您可以执行以下操作:git switch -d 6c13
。 - Mendi Barel简而言之: 当使用checkout
命令时,加上--force
选项,你可以在合并过程中切换分支。 但是如果使用switch
命令,就不能这样做。
细节:
其他回答已经解释了将checkout
分成switch
和restore
的原因,以及存在语法用法差异的事实。(例如,您可以直接使用checkout
与提交或远程跟踪分支(如origin/main
),但是对于switch
,您还必须显式指定--detach
选项。)然而,我至少发现了一个重要的功能区别。
git switch -f
被文档描述如下:
即使索引或工作树与
HEAD
不同也要进行更改。 索引和工作树都将恢复为匹配的转换目标。 如果指定了--recurse-submodules
,则子模块内容也将恢复为匹配的转换目标。 这用于丢弃本地更改。
同样,git checkout -f
被文档描述如下(重点在最后一句):
当切换分支时,即使索引或工作树与
HEAD
不同,甚至有未跟踪的文件阻碍时,也要继续进行。 这用于丢弃本地更改以及任何妨碍途中未跟踪的文件或目录。从索引检出路径时,不要在未合并的条目上失败; 相反,未合并的条目将被忽略。
这似乎适用于checkout
的另一种含义,即restore
命令等效版本。 但是,在尝试在当前处于合并过程中的情况下切换分支时,git checkout -f
将成功,即使您此时存在未解决的冲突。 而如果您当前正在合并(即使没有冲突),git switch -f
根本无法工作,因为您将收到以下错误消息:
fatal: cannot switch branch while merging
注意:此差异是使用Git版本2.37.1进行测试的。
restore
命令中没有 --force
选项,这表明它可能是为了分支切换场景而存在的,而不是文件恢复场景。 - M. Justincheckout -f
等同于git reset --hard; git switch <branch>
(在switch
中不带有-f
)?或者我忽略了一些副作用? - Mikeswitch -f
不像 checkout -f
那样尝试重置。 - TTTgit checkout --orphan
和git switch --orphan
之间的行为有所不同。$ git checkout --orphan new-branch
$ git status
On branch new-branch
No commits yet
Changes to be committed:
.....
将切换到 new-branch
分支并保留已跟踪的文件。
而使用 switch
将删除所有已跟踪的文件,创建一个全新的分支。
$ git switch --orphan new-branch
$ git status
Switched to a new branch 'new-branch'
switch
可能比checkout
更安全。checkout
时,您可能会意外地将正在进行中的工作文件“还原”为其原始状态(然后它就消失了)就像在这种情况下一样。像输入add
而不是checkout
这样的单个错误可能导致更改丢失(我经常更改分支并创建提交,因此犯了这个错误)。switch
命令可以防止这种更改丢失。man git-switch
。
Synopsis
git switch [<options>] [--no-guess] <branch> git switch [<options>] --detach [<start-point>] git switch [<options>] (-c|-C) <new-branch> [<start-point>] git switch [<options>] --orphan <new-branch>
Description
Switch to a specified branch. The working tree and the index are updated to match the branch. All new commits will be added to the tip of this branch.
Optionally a new branch could be created with either
-c
,-C
, automatically from a remote branch of same name (see--guess
), or detach the working tree from any branch with--detach
, along with switching.Switching branches does not require a clean index and working tree (i.e. no differences compared to
HEAD
). The operation is aborted however if the operation leads to loss of local changes, unless told otherwise with--discard-changes
or--merge
.THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
git switch
~= git checkout -b [branch]
。
git checkout [branch]
会让你进入分离头指针状态。
-b
标志创建一个新分支。如果目标不是分支名称,则 git checkout [branch]
仅会给您一个分离的 HEAD。如果它是一个分支名称,它将检出它,与 git switch
相同。 - M. Justin
git checkout
?在使用时我并未看到弃用警告。但是随着git switch
和git restore
的推出,我现在已经看不到使用checkout
的必要性了。然而,如果它没有被弃用,Git 团队只是使事情变得更加混乱,而不是更简单。是否有人知道git checkout
的计划?如果它仍然有用途,请问有人能够添加或编辑答案以详细说明其用途吗? - Mike Williamsongit checkout <commit>
。 - Bastian Venthurcheckout
只会因为它的少数情况而继续存在。这将延长混淆的时间。但我想我们只能互相帮助来解决这个问题 :) - Mike Williamsongit switch --detach <commit>
。 - benftwc