# git-checkout
> 原文: [https://git-scm.com/docs/git-checkout](https://git-scm.com/docs/git-checkout)
## 名稱
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|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>…?
git checkout [<tree-ish>] [--] <pathspec>…?
git checkout (-p|--patch) [<tree-ish>] [--] [<paths>…?]
```
## 描述
更新工作樹中的文件以匹配索引或指定樹中的版本。如果沒有給出路徑, _git checkout_ 也會更新`HEAD`以將指定的分支設置為當前分支。
```
git checkout <branch>
```
要準備處理< branch>,請通過更新工作樹中的索引和文件,并將HEAD指向分支來切換到它。保留對工作樹中文件的本地修改,以便可以將它們提交到< branch>。
如果< branch>找不到但是在一個遙控器(稱為< remote>)中確實存在一個具有匹配名稱的跟蹤分支,視為等同于
```
$ git checkout -b <branch> --track <remote>/<branch>
```
如果分支存在于多個遙控器中,并且其中一個由`checkout.defaultRemote`配置變量命名,我們將使用該分支用于消除歧義,即使`<branch>`在所有遙控器中都不是唯一的。將其設置為例如如果`<branch>`不明確但存在于_原點_遙控器上,`checkout.defaultRemote=origin`總是從那里檢出遠程分支。另見 [git-config [1]](https://git-scm.com/docs/git-config) 中的`checkout.defaultRemote`。
你可以省略< branch>,在這種情況下命令退化為“檢查當前分支”,這是一個帶有相當昂貴的副作用的美化無操作,只顯示當前分支的跟蹤信息(如果存在) 。
```
git checkout -b|-B <new_branch> [<start point>]
```
指定`-b`會導致創建一個新分支,就像調用 [git-branch [1]](https://git-scm.com/docs/git-branch) 然后檢出一樣。在這種情況下,您可以使用`--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(參見“DETACHED HEAD”部分),并更新工作樹中的索引和文件。保留對工作樹中文件的本地修改,以便生成的工作樹將是提交中記錄的狀態加上本地修改。
當< commit>參數是分支名稱,`--detach`選項可用于在分支的末端分離HEAD(`git checkout <branch>`將檢查該分支而不分離HEAD)。
省略< branch>將HEAD分離到當前分支的頂端。
```
git checkout [<tree-ish>] [--] <pathspec>…?
```
通過替換索引中的內容或< tree-ish>中的內容來覆蓋工作樹中的路徑。 (通常是提交)。當< tree-ish>給出了與< pathspec>匹配的路徑在索引和工作樹中都會更新。
由于先前失敗的合并,索引可能包含未合并的條目。默認情況下,如果您嘗試從索引中檢出此類條目,則結帳操作將失敗,并且不會檢出任何內容。使用`-f`將忽略這些未合并的條目。可以使用`--ours`或`--theirs`從索引中檢出合并的特定一側的內容。使用`-m`,可以放棄對工作樹文件所做的更改,以重新創建原始沖突的合并結果。
```
git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>…?]
```
這類似于上面描述的“從索引或樹狀結構中檢查工作樹的路徑”,但是允許您使用交互式界面顯示“diff”輸出并選擇要在結果。有關`--patch`選項的說明,請參見下文。
## OPTIONS
```
-q
```
```
--quiet
```
安靜,抑制反饋信息。
```
--[no-]progress
```
除非指定`--quiet`,否則默認情況下,標準錯誤流在連接到終端時會報告進度狀態。無論`--quiet`如何,即使未連接到終端,該標志也會啟用進度報告。
```
-f
```
```
--force
```
切換分支時,即使索引或工作樹與HEAD不同,也要繼續。這用于丟棄本地更改。
檢查索引中的路徑時,不要在未合并的條目上失敗;相反,未合并的條目將被忽略。
```
--ours
```
```
--theirs
```
檢查索引中的路徑時,請查看階段#2(_我們的_)或#3(_他們的_)的未合并路徑。
請注意,在`git rebase`和`git pull --rebase`期間,_我們的_和_他們的_可能會出現交換; `--ours`給出了更改被重新分配到分支的版本,而`--theirs`給出了保留您正在重新定位的工作的分支的版本。
這是因為`rebase`用于將遠程歷史記錄視為共享規范的工作流程,并將您要重新分支的分支上的工作視為要集成的第三方工作,并且您暫時假設在rebase期間,規范歷史的守護者的角色。作為規范歷史的守護者,您需要將遠程歷史記錄視為`ours`(即“我們共享的規范歷史記錄??”),而您在分支上所做的事情為`theirs`(即“一個貢獻者的工作”頂部“)。
```
-b <new_branch>
```
創建一個名為< new_branch>的新分支并在< start_point>開始;有關詳細信息,請參閱 [git-branch [1]](https://git-scm.com/docs/git-branch) 。
```
-B <new_branch>
```
創建分支< new_branch>并在< start_point>開始;如果它已經存在,則將其重置為< start_point>。這相當于用“-f”運行“git branch”;有關詳細信息,請參閱 [git-branch [1]](https://git-scm.com/docs/git-branch) 。
```
-t
```
```
--track
```
創建新分支時,請設置“上游”配置。有關詳細信息,請參閱 [git-branch [1]](https://git-scm.com/docs/git-branch) 中的“--track”。
如果沒有給出`-b`選項,則通過查看為相應遠程配置的refspec的本地部分,從遠程跟蹤分支派生新分支的名稱,然后將初始部分剝離到“ *”。這將告訴我們在分支“origin / hack”(或“remotes / origin / hack”,甚至“refs / remotes / origin / hack”)時使用“hack”作為本地分支。如果給定名稱沒有斜杠,或者上面的猜測結果為空名稱,則中止猜測。在這種情況下,您可以使用`-b`明確指定名稱。
```
--no-track
```
即使branch.autoSetupMerge配置變量為true,也不要設置“上游”配置。
```
-l
```
創建新分支的reflog;有關詳細信息,請參閱 [git-branch [1]](https://git-scm.com/docs/git-branch) 。
```
--detach
```
不要檢查分支機構來處理它,而是檢查提交檢查和可丟棄的實驗。這是“git checkout< commit>”的默認行為何時< commit>不是分支名稱。有關詳細信息,請參閱下面的“DETACHED HEAD”部分。
```
--orphan <new_branch>
```
創建一個名為< new_branch>的新_孤兒_分支,從< start_point>開始。并切換到它。在這個新分支上進行的第一次提交將沒有父項,它將成為與所有其他分支和提交完全斷開的新歷史的根。
調整索引和工作樹,就像之前運行“git checkout< start_point>”一樣。這允許您開始記錄一組類似于< start_point>的路徑的新歷史記錄。通過輕松運行“git commit -a”來進行root提交。
當您想要從提交中發布樹而不公開其完整歷史記錄時,這可能很有用。您可能希望這樣做以發布項目的開源分支,該分支的當前樹是“干凈的”,但其完整歷史記錄包含專有或其他受阻的代碼。
如果要啟動記錄一組與< 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`)。
從索引檢出路徑時,此選項允許您在指定路徑中重新創建沖突的合并。
```
--conflict=<style>
```
與上面的--merge選項相同,但更改了沖突的帥哥的呈現方式,覆蓋了merge.conflictStyle配置變量。可能的值是“merge”(默認)和“diff3”(除了“merge”樣式顯示的內容外,還顯示原始內容)。
```
-p
```
```
--patch
```
以< tree-ish>之間的差異交互式選擇帥哥。 (或索引,如果未指定)和工作樹。然后將所選擇的帥哥反向應用于工作樹(并且如果指定了< tree-ish>,則為索引)。
這意味著您可以使用`git checkout -p`有選擇地丟棄當前工作樹中的編輯內容。請參閱 [git-add [1]](https://git-scm.com/docs/git-add) 的“交互模式”部分,了解如何操作`--patch`模式。
```
--ignore-other-worktrees
```
`git checkout`拒絕所需的ref已被另一個工作樹檢出。此選項使其無論如何都會檢查引用。換句話說,ref可以由多個工作樹保存。
```
--[no-]recurse-submodules
```
使用--recurse-submodules將根據超級項目中記錄的提交更新所有初始化子模塊的內容。如果子模塊中的局部修改將被覆蓋,則除非使用`-f`,否則檢出將失敗。如果沒有使用(或--no-recurse-submodules),子模塊的工作樹將不會更新。就像 [git-submodule [1]](https://git-scm.com/docs/git-submodule) 一樣,這將分離子模塊HEAD。
```
--no-guess
```
如果存在同名的遠程跟蹤分支,請勿嘗試創建分支。
```
<branch>
```
分店結帳;如果它引用了一個分支(即一個名稱,當它以“refs / heads /”為前綴時,是一個有效的引用),則檢查該分支。否則,如果它引用了有效的提交,則您的HEAD將變為“已分離”,并且您不再處于任何分支上(有關詳細信息,請參閱下文)。
您可以使用`"@{-N}"`語法來引用使用“git checkout”操作檢出的第N個最后一個分支/提交。您也可以指定與`"@{-1}"`同義的`-`。
作為特殊情況,如果只有一個合并庫,則可以使用`"A...B"`作為`A`和`B`的合并庫的快捷方式。您最多可以省略`A`和`B`中的一個,在這種情況下,它默認為`HEAD`。
```
<new_branch>
```
新分支的名稱。
```
<start_point>
```
用于啟動新分支的提交的名稱;有關詳細信息,請參閱 [git-branch [1]](https://git-scm.com/docs/git-branch) 。默認為HEAD。
```
<tree-ish>
```
從結帳的樹(當給出路徑時)。如果未指定,將使用索引。
## 脫落的頭
HEAD通常指的是命名分支(例如 _master_ )。同時,每個分支指的是特定的提交。讓我們看一下有三個提交的repo,其中一個被標記,并且分支 _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_ ,所以現在間接指的是commit _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')
```
請注意,無論我們使用哪個checkout命令,HEAD現在直接引用commit _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操作。但是,讓我們來看看當我們檢出大師時會發生什么:
```
$ 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垃圾收集過程刪除,除非我們在此之前創建引用。如果我們還沒有離開commit _f_ ,那么其中任何一個都會創建對它的引用:
```
$ git checkout -b foo (1)
$ git branch foo (2)
$ git tag foo (3)
```
1. 創建一個新分支 _foo_ ,它指的是commit _f_ ,然后更新HEAD以引用分支 _foo_ 。換句話說,在此命令之后我們將不再處于分離的HEAD狀態。
2. 類似地創建一個新的分支 _foo_ ,它指的是commit _f_ ,但讓HEAD分離。
3. 創建一個新標簽 _foo_ ,它指的是commit _f_ ,讓HEAD分離。
如果我們已經離開commit _f_ ,那么我們必須首先恢復其對象名稱(通常使用git reflog),然后我們可以創建對它的引用。例如,要查看HEAD引用的最后兩個提交,我們可以使用以下任一命令:
```
$ git reflog -2 HEAD # or
$ git log -g -2 HEAD
```
## 論據歧視
當只有一個參數給出且它不是`--`時(例如“git checkout abc”),并且當參數既是有效`<tree-ish>`(例如分支“abc”存在)又有效`<pathspec>`時(例如,文件或名稱為“abc”的目錄存在),Git通常會要求您消除歧義。因為檢查分支是一種常見的操作,然而,在這種情況下,“git checkout abc”將“abc”作為`<tree-ish>`。如果要從索引中檢出這些路徑,請使用`git checkout -- <pathspec>`。
## 例子
1. 以下序列檢出`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`也將被檢出,即使它不再在工作樹中,因為文件通配符用于匹配索引中的條目(不是由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`將顯示自新分支的提示以來您所做的更改。
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
部分 [git [1]](https://git-scm.com/docs/git) 套件
- git
- git-config
- git-help
- git-init
- git-clone
- git-add
- git-status
- git-diff
- git-commit
- git-reset
- git-rm
- git-mv
- git-branch
- git-checkout
- git-merge
- git-mergetool
- git-log
- git-stash
- git-tag
- git-worktree
- git-fetch
- git-pull
- git-push
- git-remote
- git-submodule
- git-show
- git-log
- git-shortlog
- git-describe
- git-apply
- git-cherry-pick
- git-rebase
- git-revert
- git-bisect
- git-blame
- git-grep
- gitattributes
- giteveryday
- gitglossary
- githooks
- gitignore
- gitmodules
- gitrevisions
- gittutorial
- gitworkflows
- git-am
- git-format-patch
- git-send-email
- git-request-pull
- git-svn
- git-fast-import
- git-clean
- git-gc
- git-fsck
- git-reflog
- git-filter-branch
- git-instaweb
- git-archive
- git-bundle
- git-daemon
- git-update-server-info
- git-cat-file
- git-check-ignore
- git-checkout-index
- git-commit-tree
- git-count-objects
- git-diff-index
- git-for-each-ref
- git-hash-object
- git-ls-files
- git-merge-base
- git-read-tree
- git-rev-list
- git-rev-parse
- git-show-ref
- git-symbolic-ref
- git-update-index
- git-update-ref
- git-verify-pack
- git-write-tree