git深入理解(六):git checkout详解
Switch branches or restore working tree files
$ git checkout -h
usage: git checkout [<options>] <branch>
or: git checkout [<options>] [<branch>] -- <file>...
-q, --quiet suppress progress reporting
-b <branch> create and checkout a new branch
-B <branch> create/reset and checkout a branch
-l create reflog for new branch
--detach detach HEAD at named commit
-t, --track set upstream info for new branch
--orphan <new-branch>
new unparented branch
-2, --ours checkout our version for unmerged files
-3, --theirs checkout their version for unmerged files
-f, --force force checkout (throw away local modifications)
-m, --merge perform a 3-way merge with the new branch
--overwrite-ignore update ignored files (default)
--conflict <style> conflict style (merge or diff3)
-p, --patch select hunks interactively
--ignore-skip-worktree-bits
do not limit pathspecs to sparse entries only
--ignore-other-worktrees
do not check if another worktree is holding the given ref
--recurse-submodules[=<checkout>]
control recursive updating of submodules
--progress force progress reporting
usage后面的or表示这个命令有两种用法,第一种是切换分支,第二种是撤销修改。
checkout 本意是检出的意思,也就是将某次commit的状态检出到工作区;所以它的过程是先将HEAD
指向某个分支的最近一次commit,然后从commit恢复index,最后从index恢复工作区。
切换分支
git checkout branchname
git checkout -b branchname
创建并切换到新的分支.
这个命令是将git branch newbranch
和git checkout newbranch
合在一起的结果。
创造 index 和 工作区 都有变动的场景
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: t5.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: t2.txt
查看分支
$ git branch
b1
* master
从 master 切换到 b1
$ git checkout b1
error: Your local changes to the following files would be overwritten by checkout:
t5.txt
Please commit your changes or stash them before you switch branches.
Aborting
只提到了 index 中的文件 t5.txt,那是不是我把他提交了就可以了呢?
$ git commit -m 'add'
$ git checkout b1
Switched to branch 'b1'
M t2.txt
$ git branch
* b1
maste
$ git status
On branch b1
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: t2.txt
no changes added to commit (use "git add" and/or "git commit -a")
由此可见 index 中的变动会阻止切换分支,那是因为一旦切换了,index 的变动就会消失;而工作区的变动会体现在切换后的分支上。
重新创造 index 和 工作区 都有变动的场景,然后使用 -f 来强制切换分支呢?
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: t2.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: a/b/c/t3.txt
$ git checkout -f b1
Switched to branch 'b1'
$ git status
On branch b1
nothing to commit, working tree clean
切回 master 看一看
$ git checkout master
Switched to branch 'master'
$ git status
On branch master
nothing to commit, working tree clean
可见 -f 参数会强制切换分支,并清除掉 index 和 工作区的全部变动!!
那么,如果既要切换分支,又希望全部修改在切换后的分支中体现,那么只需要将 index 中的变动撤销即可(git reset HEAD filename),这样之前add进来的文件就成了Unstaged,然后切换分支即可。
放弃修改
如果不指定切换到哪个分支,那就是切换到当前分支,虽然HEAD的指向没有变化,但是后面的两个恢复过程依然会执行,于是就可以理解为放弃index和工作区的变动。但是出于安全考虑 git 会保持 index 的变动不被覆盖。
1、只放弃工作区的改动,index 保持不变,其实就是从当前 index 恢复 工作区:
放弃工作区中全部的修改
git checkout .
放弃工作区中某个文件的修改:
git checkout -- filename
先使用 git status
列出文件,然后 git checkout -- app/Http/Controllers/Read/Read3Controller.php
2、强制放弃 index 和 工作区 的改动:
git checkout -f
这是不可逆的操作,会直接覆盖,但是还是很有用的,有时候想放弃这些改动,使用svn的时候可以直接把文件删掉再update,但是使用git就不能这么操作,使用 git checkout
可以满足这一点。
因篇幅问题不能全部显示,请点此查看更多更全内容