设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.50.1 无更改
-
2.50.0
2025-06-16
- 2.47.2 → 2.49.1 无变更
-
2.47.1
2024-11-25
- 2.44.1 → 2.47.0 无变更
-
2.44.0
2024-02-23
- 2.43.2 → 2.43.7 无变更
-
2.43.1
2024-02-09
-
2.43.0
2023-11-20
- 2.41.1 → 2.42.4 无更改
-
2.41.0
2023-06-01
- 2.40.1 → 2.40.4 无更改
-
2.40.0
2023-03-12
- 2.39.4 → 2.39.5 无更改
-
2.39.3
2023-04-17
- 2.38.1 → 2.39.2 无更改
-
2.38.0
2022-10-02
- 2.35.1 → 2.37.7 无更改
-
2.35.0
2022-01-24
- 2.34.1 → 2.34.8 无更改
-
2.34.0
2021-11-15
- 2.30.1 → 2.33.8 无变更
-
2.30.0
2020-12-27
- 2.29.1 → 2.29.3 无更改
-
2.29.0
2020-10-19
- 2.27.1 → 2.28.1 无变更
-
2.27.0
2020-06-01
- 2.25.1 → 2.26.3 无更改
-
2.25.0
2020-01-13
- 2.23.1 → 2.24.4 无更改
-
2.23.0
2019-08-16
- 2.22.1 → 2.22.5 无更改
-
2.22.0
2019-06-07
- 2.21.1 → 2.21.4 无更改
-
2.21.0
2019-02-24
- 2.19.3 → 2.20.5 无更改
-
2.19.2
2018-11-21
- 2.19.1 无更改
-
2.19.0
2018-09-10
- 2.17.0 → 2.18.5 无更改
-
2.16.6
2019-12-06
- 2.15.4 无更改
-
2.14.6
2019-12-06
-
2.13.7
2018-05-22
- 2.11.4 → 2.12.5 无变更
-
2.10.5
2017-09-22
-
2.9.5
2017-07-30
- 2.8.6 无更改
-
2.7.6
2017-07-30
- 2.6.7 无更改
-
2.5.6
2017-05-05
-
2.4.12
2017-05-05
- 2.1.4 → 2.3.10 无更改
-
2.0.5
2014-12-17
概要
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>-
通过将
HEAD
分离到 <commit> 上(参见“分离 HEAD”章节),并更新索引和工作区中的文件,准备在 <commit> 之上工作。工作区中文件的本地修改会保留,因此最终的工作区将是提交中记录的状态加上本地修改。当 <commit> 参数是分支名称时,可以使用
--detach
选项将HEAD
分离到该分支的末端(git
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”输出,并选择结果中要使用的代码块(hunks)。有关
--patch
选项的描述,请参见下文。
选项
-q
--quiet
-
安静模式,抑制反馈消息。
--progress
--no-progress
-
默认情况下,当连接到终端时,进度状态会在标准错误流上报告,除非指定了
--quiet
。即使未连接到终端,此标志也会启用进度报告,无论是否指定--quiet
。 -f
--force
-
切换分支时,即使索引或工作区与
HEAD
不同,或者存在未跟踪的文件阻碍,也要继续进行。这用于丢弃本地修改以及任何阻碍的未跟踪文件或目录。从索引中检出路径时,遇到未合并的条目时不失败;相反,未合并的条目将被忽略。
--ours
--theirs
-
从索引中检出路径时,对于未合并的路径,检出阶段 #2 (
ours
) 或 #3 (theirs
)。请注意,在执行
git
rebase
和git
pull
--rebase
时,ours
和theirs
可能会互换;--ours
提供更改被 rebase 到其上的分支的版本,而--theirs
提供包含你正在 rebase 的工作的分支的版本。这是因为
rebase
在一个工作流中使用,该工作流将远程仓库的历史视为共享的规范历史,并将你在正在 rebase 的分支上所做的工作视为要集成的第三方工作,并且你在 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-branch[1]。 -t
--track
[=
(direct
|inherit
)]-
创建新分支时,设置“upstream”配置。有关详细信息,请参见 git-branch[1] 中的
--track
。如果没有给出
-b
选项,新分支的名称将从远程跟踪分支派生,方法是查看为相应远程配置的引用规范的本地部分,然后剥离直到“*”的初始部分。这将告诉我们在从origin/hack
(或remotes/origin/hack
,甚至refs/remotes/origin/hack
)分支时,使用hack
作为本地分支名称。如果给定的名称没有斜杠,或者上述猜测导致名称为空,则猜测中止。在这种情况下,你可以使用-b
显式指定名称。 --no-track
-
不设置“upstream”配置,即使
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
-
创建新分支的引用日志;有关详细信息,请参见 git-branch[1]。
-d
--detach
-
不是检出一个分支来在其上工作,而是检出一个提交用于检查和可丢弃的实验。这是当 <commit> 不是分支名称时,
git
checkout
<commit> 的默认行为。有关详细信息,请参见下方的“分离 HEAD”章节。 --orphan
<new-branch>-
创建一个名为 <new-branch> 的新“孤儿”分支,从 <start-point> 开始并切换到它。在此新分支上进行的第一次提交将没有父级,它将成为一个与所有其他分支和提交完全断开的新历史的根。
索引和工作区会进行调整,就像你之前运行了
git
checkout
<start-point> 一样。这允许你通过轻松运行git
commit
-a
来创建根提交,从而开始一个记录与 <start-point> 类似路径集的新历史。当你想要发布一个提交的树结构而不暴露其完整历史时,这会很有用。你可能希望这样做,以发布一个项目(其当前树结构是“干净”的)的开源分支,但其完整历史包含专有或受其他限制的代码片段。
如果你想开始一个记录与 <start-point> 完全不同的路径集的新历史,那么在创建孤儿分支后,你应该立即从工作区的顶层运行
git
rm
-rf
.
来清空索引和工作区。之后,你就可以准备你的新文件,通过从其他地方复制、解压 tarball 等方式重新填充工作区。 --ignore-skip-worktree-bits
-
在稀疏检出模式下,
git
checkout
--
<path>... 将只更新与 <paths> 和$GIT_DIR/info/sparse-checkout
中的稀疏模式匹配的条目。此选项会忽略稀疏模式,并重新添加 <path>... 中的任何文件。 -m
--merge
-
切换分支时,如果你的一个或多个文件有本地修改,并且这些修改在当前分支与你要切换的分支之间存在差异,命令会拒绝切换分支,以便在上下文中保留你的修改。然而,使用此选项,将执行当前分支、你的工作区内容和新分支之间的三方合并,然后你将位于新分支上。
当发生合并冲突时,冲突路径的索引条目会保持未合并状态,你需要解决冲突并使用
git
add
(如果合并应导致路径删除,则使用git
rm
)标记已解决的路径。从索引中检出路径时,此选项让你可以在指定路径中重新创建冲突合并。从树对象(tree-ish)中检出路径时,不能使用此选项。
使用
--merge
切换分支时,暂存的更改可能会丢失。 --conflict=
<style>-
与上面的
--merge
选项相同,但改变了冲突代码块的呈现方式,覆盖了merge.conflictStyle
配置变量。可能的值有merge
(默认)、diff3
和zdiff3
。 -p
--patch
-
交互式地选择 <tree-ish>(如果未指定,则为索引)与工作区之间差异中的代码块(hunks)。然后将选定的代码块反向应用于工作区(如果指定了 <tree-ish>,则也应用于索引)。
这意味着你可以使用
git
checkout
-p
从当前工作区中选择性地丢弃编辑。有关如何操作--patch
模式的详细信息,请参见 git-add[1] 的“交互模式”章节。请注意,此选项默认使用无覆盖模式(另请参见
--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>-
路径规范通过 <file> 传递,而不是通过命令行参数。如果 <file> 精确为
-
,则使用标准输入。路径规范元素由 LF 或 CR/LF 分隔。路径规范元素可以按照配置变量core.quotePath
的说明进行引用(参见 git-config[1])。另请参见--pathspec-file-nul
和全局--literal-pathspecs
。 --pathspec-file-nul
-
仅在与
--pathspec-from-file
一起使用时有意义。路径规范元素由 NUL 字符分隔,所有其他字符都被视为字面值(包括换行符和引号)。 - <分支>
-
要检出的分支;如果它指向一个分支(即,一个加上“refs/heads/”前缀后是有效引用的名称),那么将检出该分支。否则,如果它指向一个有效的提交,你的
HEAD
将变为“分离”状态,你将不再位于任何分支上(详见下文)。你可以使用
@{-N}
语法来引用使用“git checkout”操作检出的倒数第 N 个分支/提交。你也可以指定-
,它等同于@{-1}
。作为特例,如果 <rev-a> 和 <rev-b> 只有一个合并基准,你可以使用 <rev-a>
...
<rev-b> 作为它们的合并基准的快捷方式。你可以最多省略 <rev-a> 和 <rev-b> 中的一个,在这种情况下它默认为HEAD
。 - <新分支>
-
新分支的名称。
- <起始点>
-
新分支的起始提交名称;有关详细信息,请参见 git-branch[1]。默认为
HEAD
。作为特例,如果 <rev-a> 和 <rev-b> 只有一个合并基准,你可以使用 <rev-a>
...
<rev-b> 作为它们的合并基准的快捷方式。你可以最多省略 <rev-a> 和 <rev-b> 中的一个,在这种情况下它默认为HEAD
。 - <树对象>
-
要从中检出的树(当给定路径时)。如果未指定,将使用索引。
作为特例,如果 <rev-a> 和 <rev-b> 只有一个合并基准,你可以使用 <rev-a>
...
<rev-b> 作为它们的合并基准的快捷方式。你可以最多省略 <rev-a> 和 <rev-b> 中的一个,在这种情况下它默认为HEAD
。 --
-
不再将任何后续参数解释为选项。
- <路径规范>...
-
限制受操作影响的路径。
有关更多详细信息,请参阅 gitglossary[7] 中的 pathspec 条目。
分离 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
分支以指向新提交 d
。HEAD
仍然指向 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)
-
创建了一个新分支
foo
,它指向提交f
,然后更新HEAD
以指向分支foo
。换句话说,执行此命令后,我们将不再处于分离HEAD
状态。 -
类似地,创建了一个指向提交
f
的新分支foo
,但保留了分离的HEAD
。 -
创建了一个指向提交
f
的新标签foo
,保留了分离的HEAD
。
如果我们已经离开了提交 f
,那么我们必须首先恢复它的对象名称(通常通过使用 git reflog),然后我们才能创建指向它的引用。例如,要查看 HEAD
引用过的最后两个提交,我们可以使用以下任一命令:
$ git reflog -2 HEAD # or $ git log -g -2 HEAD
参数消歧
当只给定一个参数且不是 --
(例如 git
checkout
abc
),并且该参数既是一个有效的 <树对象>(例如,分支 abc
存在)又是一个有效的 <路径规范>(例如,名为“abc”的文件或目录存在)时,Git 通常会要求你进行消歧。然而,由于检出分支是一个非常常见的操作,在这种情况下,git
checkout
abc
将“abc”视为一个 <树对象>。如果你想从索引中检出这些路径,请使用 git
checkout
--
<路径规范>。
示例
1. 路径
以下序列将检出 master
分支,将 Makefile
恢复到两个修订版本之前,不小心删除了 hello.c
,然后从索引中将其恢复。
$ git checkout master (1) $ git checkout master~2 Makefile (2) $ rm -f hello.c $ git checkout hello.c (3)
-
切换分支
-
从另一个提交中取出文件
-
从索引中恢复
hello.c
如果你想从索引中检出 所有 C 语言源文件,你可以这样说:
$ git checkout -- '*.c'
请注意 *.c
周围的引号。文件 hello.c
也将被检出,即使它不再在工作区中,因为文件通配符用于匹配索引中的条目(而不是由 shell 在工作区中匹配)。
如果你有一个不幸地命名为 hello.c
的分支,这一步将被误认为是切换到该分支的指令。你应该改为这样写:
$ git checkout -- hello.c
2. 合并
在错误的分支上工作后,切换到正确的分支将使用以下方式完成:
$ 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
会显示自新分支尖端以来你所做的更改。
配置
本节中以下所有内容均从 git-config[1] 文档中选择性地包含。内容与彼处相同:
checkout.defaultRemote
-
当你运行
git
checkout
<something> 或git
switch
<something> 并且只有一个远程仓库时,它可能会隐式地回退到检出和跟踪例如origin/
<something>。一旦你有多个包含 <something> 引用的远程仓库,这将停止工作。此设置允许指定一个首选远程仓库的名称,该远程仓库在消歧时应始终优先。典型的用例是将其设置为origin
。目前,当
git
checkout
<something> 或git
switch
<something> 将检出另一个远程仓库上的 <something> 分支时,此设置被 git-switch[1] 和 git-checkout[1] 使用;当git
worktree
add
引用远程分支时,此设置被 git-worktree[1] 使用。将来,此设置可能会用于其他类似检出命令或功能。 checkout.guess
-
提供
git
checkout
和git
switch
中--guess
或--no-guess
选项的默认值。参见 git-switch[1] 和 git-checkout[1]。 checkout.workers
-
更新工作区时使用的并行工作进程数。默认值为一,即顺序执行。如果设置为小于一的值,Git 将使用与可用逻辑核心数相同的工作进程数。此设置和
checkout.thresholdForParallelism
影响所有执行检出操作的命令。例如 checkout、clone、reset、sparse-checkout 等。注意并行检出通常对于位于 SSD 或通过 NFS 的仓库提供更好的性能。对于位于旋转磁盘和/或核心数量较少的机器上的仓库,默认的顺序检出通常表现更好。仓库的大小和压缩级别也可能影响并行版本的性能。 checkout.thresholdForParallelism
-
当并行检出少量文件时,子进程生成和进程间通信的开销可能超过并行化带来的收益。此设置允许你定义应尝试并行检出的最小文件数量。默认值为 100。