Git 2.23引入了一个新的命令Git开关——在阅读了文档之后,它看起来和Git checkout <branchname>几乎一样,有人能解释一下区别或用例吗?
引入了两个新命令“git switch”和“git restore” 分裂“检出分支以推进其历史”和 “检查出索引的路径和/或一个树状的工作 从单个“git签出”中推进当前历史记录 命令。
Git 2.23引入了一个新的命令Git开关——在阅读了文档之后,它看起来和Git checkout <branchname>几乎一样,有人能解释一下区别或用例吗?
引入了两个新命令“git switch”和“git restore” 分裂“检出分支以推进其历史”和 “检查出索引的路径和/或一个树状的工作 从单个“git签出”中推进当前历史记录 命令。
当前回答
tl;dr:当使用checkout with——force时,你可以在合并过程中切换分支。你不能用switch。
细节:
其他答案已经涵盖了将签出分为切换和恢复的动机,以及存在语法使用差异的事实。(例如,你可以在提交或远程跟踪分支(如origin/main)中直接使用签出,但在switch中,你还必须显式指定——detach选项。)然而,我也发现了至少一个显著的功能差异。
Git开关-f的文档如下:
即使索引或工作树与HEAD不同,也要继续。索引和工作树都被恢复以匹配交换目标。如果指定了——recursive -submodules,子模块内容也会恢复到与切换目标匹配。这用于丢弃局部更改。
类似地,git checkout -f是这样记录的(强调最后一句):
在切换分支时,即使索引或工作树与HEAD不同,即使存在未跟踪的文件,也要继续执行。这用于丢弃本地更改和任何碍事的未跟踪文件或目录。 当从索引中检出路径时,不要在未合并的条目上失败;相反,未合并的条目将被忽略。
最后一句似乎适用于签出的另一种含义,即还原命令的等效。然而,当你试图在合并过程中切换分支时,git checkout -f将会成功,即使你当时有未解决的冲突。如果你正在合并(即使没有冲突),Git开关-f根本不起作用,因为你会得到这样的错误消息:
致命:合并时不能切换分支
注意:这个差异是使用Git 2.37.1版本测试的
其他回答
switch命令确实做了与签出相同的事情,但只针对那些切换分支的使用。特别是,与签出不同,它不能恢复工作树文件-而是使用与switch一起引入的restore命令来完成。
详细解释
正如您在2.23.0发布说明中提到的,引入switch和restore命令是为了将checkout命令分割为两个独立的部分:
“签出分支以改进其历史” “检查出索引和/或树状的路径,以推进当前历史”
换句话说,签出做了两件不同的事情,这个版本将这些不同的事情分开到它自己的集中命令中。
检出的双重目的可以在文档中的摘要描述中看到:
git-checkout -切换分支或恢复工作树文件
添加了switch命令的commit在其提交消息中解释了新命令的基本原理:
“git checkout”做太多事情是许多人困惑的来源 用户(有时甚至是老用户)。为了补救, 命令将拆分为两个新的命令:switch和restore。良好的 旧的“git checkout”命令仍然在这里,直到所有(或大部分) 用户)对此感到厌倦。
由此可以明显看出,引入新命令是为了减少混淆,因为有两个集中的命令,而不是一个多用途命令。
请注意,截至2021年12月,新命令仍被列为实验性(switch, restore):
这个命令是实验性的。行为可能会改变。
命令比较
我还没有在任何地方找到这些命令的完整比较。通过阅读文档,我认为这应该是一个相当完整的比较:
previous command | new command |
---|---|
git checkout <branch> |
git switch <branch> |
git checkout |
N/A (use 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 (use git switch <start-point> then 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),一些先前的用法可以转换为新命令,而其他用法则需要进行额外的调整。值得注意的变化包括:
The -b/-B options for creating a new branch before switching are renamed to -c/-C. They also have long option variants (--create/--force-create), whereas previously they only had the single letter option versions. --detach (or -d) is now always required when switching to a detached head, where it was previously optional for commits but required for branches. The source tree for restoring is now given by the -s (or --source) option, rather than being an inline argument. Switching using --force now fails if there are unmerged entries, rather than ignoring them. --force has also been renamed to --discard-changes, with --force being kept as an alias.
tl;dr:当使用checkout with——force时,你可以在合并过程中切换分支。你不能用switch。
细节:
其他答案已经涵盖了将签出分为切换和恢复的动机,以及存在语法使用差异的事实。(例如,你可以在提交或远程跟踪分支(如origin/main)中直接使用签出,但在switch中,你还必须显式指定——detach选项。)然而,我也发现了至少一个显著的功能差异。
Git开关-f的文档如下:
即使索引或工作树与HEAD不同,也要继续。索引和工作树都被恢复以匹配交换目标。如果指定了——recursive -submodules,子模块内容也会恢复到与切换目标匹配。这用于丢弃局部更改。
类似地,git checkout -f是这样记录的(强调最后一句):
在切换分支时,即使索引或工作树与HEAD不同,即使存在未跟踪的文件,也要继续执行。这用于丢弃本地更改和任何碍事的未跟踪文件或目录。 当从索引中检出路径时,不要在未合并的条目上失败;相反,未合并的条目将被忽略。
最后一句似乎适用于签出的另一种含义,即还原命令的等效。然而,当你试图在合并过程中切换分支时,git checkout -f将会成功,即使你当时有未解决的冲突。如果你正在合并(即使没有冲突),Git开关-f根本不起作用,因为你会得到这样的错误消息:
致命:合并时不能切换分支
注意:这个差异是使用Git 2.37.1版本测试的
以下是git手册 - 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.
switch有一些限制:目前你可以从任何提交切换到<分支名称>,但是不可能从<分支名称>切换到一个状态为分离HEAD的特定提交。所以你需要使用git签出5efb(其中5efb是任意提交哈希引用的一个例子)
好吧,根据你链接到的文档,它的唯一目的是拆分和澄清git签出的两种不同用法:
Git开关现在可以用来改变分支,就像Git checkout <branchname>那样 Git恢复可以用于将文件重置为某些修订,如Git checkout——<path_to_file>所做的那样
人们对使用git checkout的不同方式感到困惑,正如你可以从Stackoverflow上关于git checkout的许多问题中看到的那样。Git开发人员似乎已经考虑到了这一点。