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>] [--] <pathspec>…
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]
git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>]
更新工作树中的文件以匹配索引或指定树中的版本。如果没有给出路径规范 -- pathspec,git checkout也会更新HEAD以将指定的分支设置为当前分支。
使用
## 项目当前分支状态
$ git branch -a -vv
dev 26e602f [origin/dev] dev commit
* main 9df539e [origin/main] main file
relea c76aaf9 [origin/relea] rele
remotes/origin/HEAD -> origin/main
remotes/origin/dev 26e602f dev commit
remotes/origin/main 9df539e main file
remotes/origin/relea c76aaf9 rele
## 删除分支dev relea
$ git branch -d dev relea
warning: deleting branch 'dev' that has been merged to
'refs/remotes/origin/dev', but not yet merged to HEAD.
warning: deleting branch 'relea' that has been merged to
'refs/remotes/origin/relea', but not yet merged to HEAD.
Deleted branch dev (was 26e602f).
Deleted branch relea (was c76aaf9).
git checkout [<branch>]
为了准备在<分支>上工作,通过更新工作树中的索引和文件,并将HEAD指向分支来切换到它。保留对工作树中文件的本地修改,以便它们可以提交到<分支>。
如果未找到<branch>,但在一个具有匹配名称的远程(将其称为<远程>)中确实存在跟踪分支,并且未指定--no-guess,则将其视为等效于 git checkout -b <branch> --track <remote>/<branch>
## 当一个分支在本地和远程都找不到时会报错
xuyuansheng@XUYUANSHENG MINGW64 /d/VSCode/testgit (main)
$ git checkout abc
error: pathspec 'abc' did not match any file(s) known to git
## 如果本地没有该分支,远程有时就会从远程拉取分支
xuyuansheng@XUYUANSHENG MINGW64 /d/VSCode/testgit (main)
$ git checkout --no-guess dev
error: pathspec 'dev' did not match any file(s) known to git
$ git checkout dev
Switched to a new branch 'dev'
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
## 当着分支状态
$ git log --pretty=oneline --graph main dev
* 9df539ee86586d32d4349aa19e235941926cefec (origin/main, origin/HEAD, main) main file
| * 26e602f538ab6a74ac985853690136e064cbe172 (HEAD -> dev, origin/dev) dev commit
| * 1d40930975eaeef50830c457bdcd7811db6ef173 first main commit
|/
* a94823afd688061ad02285591fb36a7dbeb520dd Initial commit
您可以省略<branch>,在这种情况下,命令退化为“签出当前分支”,这是一种美化的无操作,具有相当昂贵的副作用,仅显示当前分支的跟踪信息(如果存在)。
$ git checkout --track origin/relea
Switched to a new branch 'relea'
Branch 'relea' set up to track remote branch 'relea' from 'origin'.
-b|-B 创建新分支
git checkout -b|-B <new_branch> [
指定-b
会创建一个新分支,就像 调用git-branch(1)然后签出一样。在这种情况下,您可以使用--track
or--no-track
选项,它将被传递给git branch。为方便起见, --track
没有-b
意味着创建分支;见下面的描述--track
。
如果-B
给出,<new_branch>
则在不存在时创建;否则,它被重置。
## 查看当前分支状态和提交log
$ git branch -vv
dev 26e602f [origin/dev] dev commit
main 9df539e [origin/main] main file
* relea c76aaf9 [origin/relea] rele
$ git log --pretty=oneline
c76aaf9fef36c80c2a315a2c4e859f1582270ec3 (HEAD -> relea, origin/relea) rele
26e602f538ab6a74ac985853690136e064cbe172 (origin/dev, dev) dev commit
1d40930975eaeef50830c457bdcd7811db6ef173 first main commit
a94823afd688061ad02285591fb36a7dbeb520dd Initial commit
## -b 创建并切换到新分支
$ git checkout -b fromRelea 1d40930975eaeef50830c457bdcd7811db6ef173
Switched to a new branch 'fromRelea'
$ git log --pretty=oneline
1d40930975eaeef50830c457bdcd7811db6ef173 (HEAD -> fromRelea) first main commit
a94823afd688061ad02285591fb36a7dbeb520dd Initial commit
## 再来一次,失败了、因为分支已经存在
$ git checkout -b fromRelea
fatal: A branch named 'fromRelea' already exists.
## 使用-B 强制签出,这里会重置已经存在的分支
$ git checkout relea
$ git checkout -B fromRelea
Switched to and reset branch 'fromRelea'
$ git log --pretty=oneline
c76aaf9fef36c80c2a315a2c4e859f1582270ec3 (HEAD -> fromRelea, origin/relea, relea) rele
26e602f538ab6a74ac985853690136e064cbe172 (origin/dev, dev) dev commit
1d40930975eaeef50830c457bdcd7811db6ef173 first main commit
a94823afd688061ad02285591fb36a7dbeb520dd Initial commit
--detach 分离头指针
git checkout --detach [<branch>] / git checkout [--detach] <commit>
准备在 之上工作<commit>
,方法是HEAD
在它上分离,并更新工作树中的索引和文件。保留对工作树中文件的本地修改,因此生成的工作树将是提交中记录的状态加上本地修改。当<commit>
参数是分支名称时,该--detach
选项可用于HEAD
在分支的HEAD分离(git checkout <branch>
将在不分离的情况下检查该分支HEAD
)。在当前分支的HEAD省略<branch>
分离HEAD
。
$ git checkout dev
$ cat .git/HEAD
ref: refs/heads/relea
## HEAD指向relea分支,相当于间接指向提交 c76aaf9
$ cat .git/refs/heads/relea
c76aaf9fef36c80c2a315a2c4e859f1582270ec3
$ git log --pretty=reference
c76aaf9 (rele, 2022-10-25)
26e602f (dev commit, 2022-10-25)
1d40930 (first main commit, 2022-10-25)
a94823a (Initial commit, 2022-10-25)
## --detach ,HEAD会直接指向特定的commit ,此时不在任何分支上
$ git checkout --detach dev
HEAD is now at 26e602f dev commit
Your branch is up to date with 'origin/dev'
$ git checkout --detach 26e602f
HEAD is now at 26e602f dev commit
$ cat .git/HEAD
26e602f538ab6a74ac985853690136e064cbe172
## 此时会可以在当前commit上创建新分支
-- <pathspec> 限制受checkout 操作影响的路径
如果没有指定时pathspec,会更新HEAD以将指定的分支设置为当前分支或HEAD指定指定commit
语法: git checkout [<tree-ish>] [--] [<pathspec>... ]
<tree-ish> checkout的树(当给出路径时)。如果未指定,将使用索引(HEAD)。
$ git branch -vv
dev 26e602f [origin/dev] dev commit
fromRelea c76aaf9 rele
main 9df539e [origin/main] main file
* relea 95ef627 [origin/relea: ahead 1] commit dev file in relea
## 在当前分支(relea)修改文件dev
$ echo 'edit file in relea' >> dev
$ git add dev
$ echo 'edit one more time' >> dev
$ git status
On branch relea
Your branch is ahead of 'origin/relea' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: dev
## 查看(索引)暂存区、工作树、Git库中dev文件内容
$ git ls-files --stage |grep -E 'dev$' |awk '{print$2}' |xargs git cat-file -p
dev file in relea
edit file in relea
## 查看Git库中文件内容(真难,有谁知道更好的办法请告诉我)
$ git cat-file -p HEAD |grep tree |awk '{print$2}' |xargs git cat-file -p |grep -E 'dev$' |awk '{print$3}' |xargs git cat-file -p
dev file in relea
## 查看工作树中文件
$ cat dev
dev file in relea
edit file in relea
edit one more time
## checkout 签出dev文件内容
## 错误,提示你本地有未提交的修改,无法切换到dev,这时候dev被识别为了一个分支
$ git checkout dev
error: Your local changes to the following files would be overwritten by checkout:
dev
Please commit your changes or stash them before you switch branches.
Aborting
##使用-- <pathspec> 语法,成功签出,dev文件的内容变成了暂存区的内容,所以不指定tree-ish时默认是从暂存区签出
$ git checkout -- dev
$ cat dev
dev file in relea
edit file in relea
## 指定tree-ish时,就会从指定的树(git中的树对象,不是工作树worktree)中签出文件内容
$ git checkout HEAD -- dev
$ cat dev
dev file in relea
-p/--patch
git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>... ]
<tree-ish>
在和工作树之间的差异中以交互方式选择大块(hunk ) 。然后将选择的块反向应用于工作树(如果<tree-ish>
指定了,则为索引)。这意味着您可以使用它git checkout -p
来选择性地丢弃当前工作树中的编辑。请参阅git-add(1)的“交互模式”部分以了解如何操作该--patch
模式。请注意,此选项默认使用无覆盖模式(另请参阅 --overlay
),目前不支持覆盖模式。
## 接上例 ,再次修改dev文件文件内容后
$ git status
On branch relea
Your branch is ahead of 'origin/relea' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
modified: dev
Changes not staged for commit:
modified: dev
## 以交互的模式签出指定文件
$ git checkout -p -- dev
diff --git a/dev b/dev
index 5753032..228d0b0 100644
--- a/dev
+++ b/dev
@@ -1,2 +1,3 @@
dev file in relea
edit file in relea
+edit dev noe more time agin
\ No newline at end of file
## 从工作树中丢弃这个大块头?? y=yes,n=no,q=quit...,具体交互方式参阅git-add
(1/1) Discard this hunk from worktree [y,n,q,a,d,e,?]?
## 输入y后 ,工作树中修改的内容被回退到暂存区一样了
$ git diff -- dev
## 指定<tree-ish>,这时会将tree-ish与工作树(worktree)对比
$ git checkout -p HEAD -- dev
diff --git a/dev b/dev
index f3e3544..e0b2374 100644
--- a/dev
+++ b/dev
@@ -1 +1,3 @@
dev file in relea
+edit file in relea
+asfdadasdasf
\ No newline at end of file
## 第一次输入了yes,但是提示错误,因为这个修改块(hunk)没有应用到(索引)暂存区中
(1/1) Discard this hunk from index and worktree [y,n,q,a,d,e,?]? y
error: patch failed: dev:1
error: dev: patch does not apply
The selected hunks do not apply to the index!
Apply them to the worktree anyway? y
## 上面再次输入yes,工作树中dev文件内容变为了和HEAD中文件一样
$ cat dev
dev file in relea
$ git diff -- dev
diff --git a/dev b/dev
index 5753032..f3e3544 100644
--- a/dev
+++ b/dev
@@ -1,2 +1 @@
dev file in relea
-edit file in relea
--ignore-other-worktrees 忽略其他工作树
git checkout
当想要的 ref 已经被另一个工作树签出时拒绝。这个选项使它无论如何都要检查参考。换句话说,ref 可以被多个工作树保存
$ git reset --hard HEAD
HEAD is now at 95ef627 commit dev file in relea
$ git branch -vv
dev 26e602f [origin/dev] dev commit
fromRelea c76aaf9 rele
main 9df539e [origin/main] main file
* relea 95ef627 [origin/relea: ahead 1] commit dev file in relea
## 从dev分支新建一个工作树
$ git worktree add ../wtree_dev dev
Preparing worktree (checking out 'dev')
HEAD is now at 26e602f dev commi
## 切换到新的工作树目录并查看分支状态(去掉了无关的分支)
$ cd ../wtree_dev/ && git branch -v
* dev 26e602f dev commit
wtree 95ef627 commit dev file in relea
user@NAME MINGW64 /d/VSCode/wtree_dev (dev)
## 切换回Git仓库,并签出到指定(dev)分支
$ cd ../testgit/
$ git checkout dev
fatal: 'dev' is already checked out at 'D:/VSCode/wtree_dev'
## --ignore-other-worktrees 忽略其他工作树
$ git checkout --ignore-other-worktrees dev
Switched to branch 'dev'
Your branch is up to date with 'origin/dev'.
--overwrite-ignore 覆盖忽略的文件(默认)
--no-overwrite-ignore
切换分支时静默覆盖忽略的文件。这是默认行为。--no-overwrite-ignore
当新分支包含被忽略的文件时,用于中止操作。
$ git checkout relea
## 添加.gitignore文件(内容为 *.sh),并提交后,新建一个ab.sh文件
$ echo 'sadfa' > ab.sh
## 没有看懂,后续再看
--overlay /--no-overlay
在默认覆盖模式下,git checkout
从不从索引或工作树中删除文件。指定--no-overlay
时,将删除出现在索引和工作树中但不在其中的<tree-ish>
文件,以使它们<tree-ish>
完全匹配。
## 没有看懂,后续再看
标签:git,--,relea,dev,Git,file,checkout
From: https://www.cnblogs.com/xysgo/p/16834291.html