简体中文 ▾ 主题 ▾ 最新版本 ▾ git-checkout 上次更新于 2.47.1

名称

git-checkout - 切换分支或恢复工作树文件

概要

git checkout [-q] [-f] [-m] [<branch>]
git checkout [-q] [-f] [-m] --detach [<branch>]
git checkout [-q] [-f] [-m] [--detach] <commit>
git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>]
git checkout [-f] <tree-ish> [--] <pathspec>…​
git checkout [-f] <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul]
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>…​
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul]
git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>…​]

描述

更新工作树中的文件,以匹配索引或指定树中的版本。 如果没有给出路径说明符,git checkout 也会更新 HEAD 将指定分支设置为当前分支。

git checkout [<branch>]

为了准备在 <branch> 上工作,切换到它,更新索引和工作树中的文件,并将 HEAD 指向该分支。保留对工作树中文件的本地修改,以便可以将它们提交到 <branch>

如果未找到 <branch>,但在一个且只有一个远程仓库(称为 <remote>)中存在具有匹配名称的跟踪分支,并且未指定 --no-guess,则将其视为等同于

$ git checkout -b <branch> --track <remote>/<branch>

您可以省略 <branch>,在这种情况下,该命令会退化为“检出当前分支”,这是一种带有相当昂贵副作用的伪操作,仅显示当前分支的跟踪信息(如果存在)。

git checkout -b|-B <new-branch> [<start-point>]

指定 -b 会创建一个新分支,就像调用 git-branch[1] 一样,然后检出该分支。 在这种情况下,你可以使用 --track--no-track 选项,这些选项将传递给 git branch。 为方便起见,没有 -b--track 意味着创建分支; 请参阅下面 --track 的描述。

如果给出了 -B,如果 <new-branch> 不存在,则创建该分支; 否则,将其重置。 这是以下命令的事务等效项

$ git branch -f <branch> [<start-point>]
$ git checkout <branch>

也就是说,除非“git checkout”成功(例如,当分支在另一个工作树中使用时),否则不会重置/创建分支,不仅当前分支保持不变,而且分支也不会重置为起始点。

git checkout --detach [<branch>]
git checkout [--detach] <commit>

准备在 <commit> 的基础上工作,方法是在它处分离 HEAD(请参阅“分离的 HEAD”部分),并更新索引和工作树中的文件。 保留对工作树中文件的本地修改,以便生成的工作树将是提交中记录的状态加上本地修改。

<commit> 参数是一个分支名称时,可以使用 --detach 选项在分支的顶端分离 HEADgit checkout <branch> 会检出该分支,而不会分离 HEAD)。

省略 <branch> 会在当前分支的顶端分离 HEAD

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>…​
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]

覆盖与路径说明符匹配的文件的内容。 当未给出 <tree-ish>(通常是一个提交)时,用索引中的内容覆盖工作树。 当给出 <tree-ish> 时,用 <tree-ish> 处的内容覆盖索引和工作树。

由于之前合并失败,索引可能包含未合并的条目。 默认情况下,如果你尝试从索引中检出这样的条目,则检出操作将失败,并且不会检出任何内容。 使用 -f 将忽略这些未合并的条目。 可以使用 --ours--theirs 从索引中检出合并的特定方面的内容。 使用 -m,可以丢弃对工作树文件所做的更改,以重新创建原始冲突的合并结果。

git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>…​]

这与之前的模式类似,但允许你使用交互界面来显示“diff”输出,并选择在结果中使用哪些代码块。 有关 --patch 选项的描述,请参见下文。

选项

-q
--quiet

安静模式,禁止反馈消息。

--progress
--no-progress

默认情况下,如果进度状态附加到终端,则会在标准错误流上报告进度状态,除非指定了 --quiet。 即使未附加到终端,此标志也会启用进度报告,而与 --quiet 无关。

-f
--force

切换分支时,即使索引或工作树与 HEAD 不同,或者即使存在未跟踪的文件,也继续进行。 这用于丢弃本地更改和任何妨碍操作的未跟踪文件或目录。

从索引中检出路径时,如果遇到未合并的条目,则不会失败; 相反,未合并的条目将被忽略。

--ours
--theirs

从索引中检出路径时,检出未合并路径的第 2 阶段(ours)或第 3 阶段(theirs)。

请注意,在 git rebasegit pull --rebase 期间,ourstheirs 可能会交换; --ours 提供将更改变基到的分支的版本,而 --theirs 提供保存你要变基的工作的分支的版本。

这是因为 rebase 用于将远程历史记录视为共享规范历史记录的工作流中,并将你在分支上完成的工作视为要集成的第三方工作,并且你在变基期间暂时承担规范历史记录的保管人的角色。 作为规范历史记录的保管人,你需要将来自远程的历史记录视为 ours(即“我们的共享规范历史记录”),而将你在你的侧分支上所做的工作视为 theirs(即“一个贡献者在其之上的工作”)。

-b <new-branch>

创建一个名为 <new-branch> 的新分支,从 <start-point> 处开始,然后检出结果分支; 有关详细信息,请参见 git-branch[1]

-B <new-branch>

创建分支 <new-branch>,从 <start-point> 处开始; 如果它已经存在,则将其重置为 <start-point>。 然后检出结果分支。 这等效于运行带有 "-f" 的 "git branch",然后运行该分支的 "git checkout"; 有关详细信息,请参见 git-branch[1]

-t
--track[=(direct|inherit)]

创建新分支时,设置“上游”配置。 有关详细信息,请参见 git-branch[1] 中的 "--track"。

如果未给出 -b 选项,则新分支的名称将从远程跟踪分支派生,方法是查看为相应远程配置的引用规范的本地部分,然后剥离起始部分直到“*”。 这将告诉我们在从 origin/hack(或 remotes/origin/hack,甚至 refs/remotes/origin/hack)分支出来时使用 hack 作为本地分支。 如果给定的名称没有斜杠,或者上述猜测导致空名称,则中止猜测。 在这种情况下,你可以使用 -b 显式地给出一个名称。

--no-track

即使 branch.autoSetupMerge 配置变量为 true,也不要设置“上游”配置。

--guess
--no-guess

如果未找到 <branch>,但在一个且只有一个远程仓库(称为 <remote>)中存在具有匹配名称的跟踪分支,则将其视为等同于

$ git checkout -b <branch> --track <remote>/<branch>

如果该分支存在于多个远程仓库中,并且其中一个远程仓库通过 checkout.defaultRemote 配置变量进行了命名,那么即使 <branch> 在所有远程仓库中不是唯一的,我们也会使用该远程仓库进行消歧。例如,将其设置为 checkout.defaultRemote=origin,以便在 <branch> 模糊不清但存在于 origin 远程仓库时,始终从该远程仓库检出远程分支。另请参阅 git-config[1] 中的 checkout.defaultRemote

--guess 是默认行为。使用 --no-guess 禁用它。

默认行为可以通过 checkout.guess 配置变量进行设置。

-l

创建新分支的 reflog;有关详细信息,请参阅 git-branch[1]

-d
--detach

检出一个提交进行检查和可丢弃的实验,而不是检出一个分支进行工作。当 <commit> 不是分支名称时,这是 git checkout <commit> 的默认行为。有关详细信息,请参阅下面的“DETACHED HEAD”部分。

--orphan <new-branch>

创建一个名为 <new-branch> 的新的未出生分支,从 <start-point> 开始,并切换到该分支。在这个新分支上进行的第一个提交将没有父提交,并且它将是一个与所有其他分支和提交完全断开的新历史的根。

索引和工作树会被调整,就像您之前运行了 git checkout <start-point> 一样。这使您可以启动一个新历史,该历史记录一组类似于 <start-point> 的路径,方法是轻松运行 git commit -a 来进行根提交。

当您想要发布来自提交的树而不公开其完整历史记录时,这可能很有用。您可能希望这样做来发布项目的开源分支,该项目的当前树是“干净的”,但其完整历史记录包含专有或以其他方式受限制的代码片段。

如果您想启动一个断开连接的历史记录,该历史记录记录一组与 <start-point> 完全不同的路径,那么您应该在创建孤立分支后立即通过从工作树的顶层运行 git rm -rf . 来清除索引和工作树。之后,您将准备好准备新文件,通过从其他地方复制它们、提取 tarball 等来重新填充工作树。

--ignore-skip-worktree-bits

在稀疏检出模式下,git checkout -- <paths> 将仅更新 <paths>$GIT_DIR/info/sparse-checkout 中的稀疏模式匹配的条目。此选项忽略稀疏模式,并将 <paths> 中的任何文件添加回来。

-m
--merge

在切换分支时,如果您对一个或多个文件进行了本地修改,这些文件在当前分支和您要切换到的分支之间有所不同,则该命令会拒绝切换分支,以保留您在上下文中的修改。但是,使用此选项,将在当前分支、您的工作树内容和新分支之间进行三向合并,并且您将位于新分支上。

当发生合并冲突时,冲突路径的索引条目保持未合并状态,您需要解决冲突并使用 git add(如果合并应导致删除路径,则使用 git rm)标记已解决的路径。

从索引中检出路径时,此选项允许您在指定的路径中重新创建冲突的合并。从树对象检出路径时,不能使用此选项。

使用 --merge 切换分支时,暂存的更改可能会丢失。

--conflict=<style>

与上面的 --merge 选项相同,但更改了冲突块的呈现方式,覆盖了 merge.conflictStyle 配置变量。可能的值为“merge”(默认)、“diff3”和“zdiff3”。

-p
--patch

交互式地选择 <tree-ish>(如果未指定,则为索引)和工作树之间的差异中的块。然后将所选块以相反的顺序应用于工作树(并且如果指定了 <tree-ish>,则应用于索引)。

这意味着您可以使用 git checkout -p 从当前工作树中选择性地放弃编辑。请参阅 git-add[1] 的“交互模式”部分,以了解如何操作 --patch 模式。

请注意,此选项默认使用无覆盖模式(另请参阅 --overlay),并且当前不支持覆盖模式。

--ignore-other-worktrees

当所需分支已被另一个工作树检出或以其他方式使用时,git checkout 会拒绝。此选项使其无论如何都要检出该分支。换句话说,该分支可以被多个工作树使用。

--overwrite-ignore
--no-overwrite-ignore

切换分支时,静默覆盖忽略的文件。这是默认行为。当新分支包含忽略的文件时,使用 --no-overwrite-ignore 中止操作。

--recurse-submodules
--no-recurse-submodules

使用 --recurse-submodules 将根据超级项目中记录的提交更新所有活动子模块的内容。如果子模块中的本地修改将被覆盖,则检出将失败,除非使用 -f。如果不使用任何内容(或 --no-recurse-submodules),则不会更新子模块工作树。就像 git-submodule[1] 一样,这将分离子模块的 HEAD

--overlay
--no-overlay

在默认覆盖模式下,git checkout 永远不会从索引或工作树中删除文件。指定 --no-overlay 时,将删除索引和工作树中出现但不在 <tree-ish> 中的文件,以使它们与 <tree-ish> 完全匹配。

--pathspec-from-file=<file>

Pathspec 在 <file> 中传递,而不是命令行参数。如果 <file> 正好是 -,则使用标准输入。Pathspec 元素由 LF 或 CR/LF 分隔。Pathspec 元素可以像配置变量 core.quotePath (参见 git-config[1]) 中解释的那样引用。另请参见 --pathspec-file-nul 和全局 --literal-pathspecs

--pathspec-file-nul

仅对 --pathspec-from-file 有意义。Pathspec 元素用 NUL 字符分隔,所有其他字符按字面意思处理(包括换行符和引号)。

<branch>

要检出的分支;如果它引用一个分支(即,一个以 "refs/heads/" 为前缀时是有效 ref 的名称),那么该分支将被检出。否则,如果它引用一个有效的提交,您的 HEAD 将变为“分离”,并且您不再位于任何分支上(有关详细信息,请参见下文)。

您可以使用 @{-N} 语法来引用使用 "git checkout" 操作检出的第 N 个最后一个分支/提交。您还可以指定 -,它与 @{-1} 同义。

作为一种特殊情况,如果 AB 只有一个合并基础,您可以使用 A...B 作为 AB 的合并基础的快捷方式。您可以省略 AB 中的最多一个,在这种情况下,它默认为 HEAD

<new-branch>

新分支的名称。

<start-point>

启动新分支的提交的名称;有关详细信息,请参阅 git-branch[1]。默认为 HEAD

作为一种特殊情况,如果 AB 只有一个合并基础,您可以使用 "A...B" 作为 AB 的合并基础的快捷方式。您可以省略 AB 中的最多一个,在这种情况下,它默认为 HEAD

<tree-ish>

从中检出的树(当给出路径时)。如果未指定,将使用索引。

作为一种特殊情况,如果 AB 只有一个合并基础,您可以使用 "A...B" 作为 AB 的合并基础的快捷方式。您可以省略 AB 中的最多一个,在这种情况下,它默认为 HEAD

--

不要将任何更多参数解释为选项。

<pathspec>…​

限制受操作影响的路径。

有关更多详细信息,请参阅 gitglossary[7] 中的 pathspec 条目。

DETACHED HEAD

HEAD 通常指的是一个已命名的分支(例如 master)。同时,每个分支都指的是一个特定的提交。让我们看一个包含三个提交的存储库,其中一个提交被标记,并且检出了分支 master

           HEAD (refers to branch 'master')
            |
            v
a---b---c  branch 'master' (refers to commit 'c')
    ^
    |
  tag 'v2.0' (refers to commit 'b')

当在此状态下创建一个提交时,分支会被更新以引用新的提交。具体来说,git commit 创建一个新的提交 d,其父提交是提交 c,然后更新分支 master 以引用新的提交 dHEAD 仍然引用分支 master,因此间接引用提交 d

$ edit; git add; git commit

               HEAD (refers to branch 'master')
                |
                v
a---b---c---d  branch 'master' (refers to commit 'd')
    ^
    |
  tag 'v2.0' (refers to commit 'b')

有时能够检出不在任何已命名分支的尖端的提交,甚至创建一个未被已命名分支引用的新提交是很有用的。让我们看看当我们检出提交 b 时会发生什么(这里我们展示了两种方法)

$ git checkout v2.0  # or
$ git checkout master^^

   HEAD (refers to commit 'b')
    |
    v
a---b---c---d  branch 'master' (refers to commit 'd')
    ^
    |
  tag 'v2.0' (refers to commit 'b')

请注意,无论我们使用哪个检出命令,HEAD 现在都直接引用提交 b。这被称为处于分离的 HEAD 状态。它仅仅意味着 HEAD 引用一个特定的提交,而不是引用一个已命名的分支。让我们看看当我们创建一个提交时会发生什么

$ edit; git add; git commit

     HEAD (refers to commit 'e')
      |
      v
      e
     /
a---b---c---d  branch 'master' (refers to commit 'd')
    ^
    |
  tag 'v2.0' (refers to commit 'b')

现在有一个新的提交 e,但它只被 HEAD 引用。当然,我们可以在这种状态下添加另一个提交

$ edit; git add; git commit

	 HEAD (refers to commit 'f')
	  |
	  v
      e---f
     /
a---b---c---d  branch 'master' (refers to commit 'd')
    ^
    |
  tag 'v2.0' (refers to commit 'b')

事实上,我们可以执行所有正常的 Git 操作。但是,让我们看看当我们然后检出 master 时会发生什么

$ git checkout master

               HEAD (refers to branch 'master')
      e---f     |
     /          v
a---b---c---d  branch 'master' (refers to commit 'd')
    ^
    |
  tag 'v2.0' (refers to commit 'b')

重要的是要意识到,此时没有任何东西引用提交 f。最终,提交 f(以及扩展的提交 e)将被例行的 Git 垃圾回收过程删除,除非我们在此之前创建一个引用。如果我们尚未离开提交 f,则以下任何一项都将创建一个对它的引用

$ git checkout -b foo  # or "git switch -c foo"  (1)
$ git branch foo                                 (2)
$ git tag foo                                    (3)
  1. 创建一个新的分支 foo,它引用提交 f,然后更新 HEAD 以引用分支 foo。换句话说,在此命令之后,我们将不再处于分离的 HEAD 状态。

  2. 类似地,创建一个新的分支 foo,它引用提交 f,但使 HEAD 保持分离状态。

  3. 创建一个新的标签 foo,它引用提交 f,使 HEAD 保持分离状态。

如果我们已经离开了提交 f,那么我们必须首先恢复其对象名称(通常通过使用 git reflog),然后我们可以创建一个对它的引用。例如,要查看 HEAD 引用的最后两个提交,我们可以使用以下任一命令

$ git reflog -2 HEAD # or
$ git log -g -2 HEAD

ARGUMENT DISAMBIGUATION

当只有一个参数给出且它不是 -- 时(例如 git checkout abc),并且当该参数既是有效的 <tree-ish>(例如,存在一个分支 abc)又是有效的 <pathspec>(例如,存在一个名为 "abc" 的文件或目录)时,Git 通常会要求您消除歧义。但是,由于检出分支是一个非常常见的操作,因此在这种情况下,git checkout abc 将 "abc" 视为 <tree-ish>。如果您想从索引中检出这些路径,请使用 git checkout -- <pathspec>

EXAMPLES

1. Paths

下面的序列检出 master 分支,将 Makefile 恢复到两个版本前,错误地删除了 hello.c,并从索引中将其恢复。

$ git checkout master             (1)
$ git checkout master~2 Makefile  (2)
$ rm -f hello.c
$ git checkout hello.c            (3)
  1. 切换分支

  2. 从另一个提交中取出文件

  3. 从索引恢复 hello.c

如果你想从索引中检出所有 C 源代码文件,你可以这样说

$ git checkout -- '*.c'

注意 *.c 周围的引号。文件 hello.c 也会被检出,即使它已经不在工作树中,因为文件 globbing 用于匹配索引中的条目(而不是 shell 中的工作树)。

如果你有一个不幸的分支名为 hello.c,这一步会被误认为是切换到该分支的指令。你应该这样写:

$ git checkout -- hello.c

2. 合并

在错误的分支上工作后,切换到正确的 mytopic 分支应该使用:

$ git checkout mytopic

但是,你的“错误”分支和正确的 mytopic 分支可能在你本地修改过的文件中有所不同,在这种情况下,上面的检出将会失败,如下所示:

$ git checkout mytopic
error: You have local changes to 'frotz'; not switching branches.

你可以给命令 -m 标志,这将尝试一个三向合并

$ git checkout -m mytopic
Auto-merging frotz

在这个三向合并之后,本地修改不会被注册到你的索引文件中,因此 git diff 会显示你从新分支的尖端开始所做的更改。

3. 合并冲突

当使用 -m 选项切换分支时发生合并冲突,你将会看到类似这样的信息:

$ git checkout -m mytopic
Auto-merging frotz
ERROR: Merge conflict in frotz
fatal: merge program failed

此时,git diff 会显示像之前示例中一样干净地合并的更改,以及冲突文件中的更改。编辑并解决冲突,并像往常一样使用 git add 标记为已解决。

$ edit frotz
$ git add frotz

配置

本节中此行下面的所有内容都选择性地包含在 git-config[1] 文档中。内容与那里找到的相同

checkout.defaultRemote

当你运行 git checkout <something>git switch <something> 并且只有一个远程仓库时,它可能会隐式地回退到检出和跟踪,例如 origin/<something>。 只要你有多个带有 <something> 引用的远程仓库,这就会停止工作。 此设置允许设置首选远程仓库的名称,该远程仓库在消除歧义时应始终胜出。 典型的用例是将其设置为 origin

目前,git-switch[1]git-checkout[1]git checkout <something>git switch <something> 将检出另一个远程仓库上的 <something> 分支时使用此设置,并且 git-worktree[1]git worktree add 引用远程分支时使用此设置。 此设置将来可能用于其他类似检出的命令或功能。

checkout.guess

提供 git checkoutgit switch--guess--no-guess 选项的默认值。 请参阅 git-switch[1]git-checkout[1]

checkout.workers

更新工作树时要使用的并行工作线程数。 默认为 1,即顺序执行。 如果设置为小于 1 的值,Git 将使用与可用逻辑核心数量一样多的工作线程。 此设置和 checkout.thresholdForParallelism 会影响所有执行检出的命令。 例如,checkout、clone、reset、sparse-checkout 等。

注意:对于位于 SSD 上或通过 NFS 连接的存储库,并行检出通常可以提供更好的性能。 对于位于旋转磁盘上和/或具有少量核心的计算机上的存储库,默认的顺序检出通常表现更好。 存储库的大小和压缩级别也可能会影响并行版本的执行效果。

checkout.thresholdForParallelism

使用少量文件运行并行检出时,子进程生成和进程间通信的成本可能会超过并行化的收益。 此设置允许你定义应尝试并行检出的最小文件数。 默认值为 100。

GIT

属于 git[1] 套件

scroll-to-top