转自:http://www.cnblogs.com/hutaoer/archive/2013/05/07/git_checkout.html?utm_source=tuicool&utm_medium=referral

在日常的git操作中,git checkout——检出,是我们的常用命令。最为常用的两种情形是创建分支和切换分支。

在下面的命令中,使用了一些简写,在这里说明一下:

git st # git status
git ci  # git commit
git br # git branch
git co # git checkout
git mg # git merge
git line # git log --oneline

当然,你也可以直接在git中敲命令,将这些简写添加到git配置中

git config --global -e

然后,可以插入下面的配置:

[alias]st = statusco = checkoutbr = branchmg = mergeci = commit md = commit --amenddt = difftoolmt = mergetoollast = log -1 HEADcf = configline = log --onelinelatest = for-each-ref --sort=-committerdate --format='%(committerdate:short) %(refname:short) [%(committername)]'ls = log --pretty=format:\"%C(yellow)%h %C(blue)%ad %C(red)%d %C(reset)%s %C(green)[%cn]\" --decorate --date=shorthist = log --pretty=format:\"%C(yellow)%h %C(red)%d %C(reset)%s %C(green)[%an] %C(blue)%ad\" --topo-order --graph --date=shorttype = cat-file -tdump = cat-file -p

这样,你也就可以使用这些简写的命令咯。下面步入正题啊。

(一)基础——千里之行,始于切糕(checkout)

先熟悉下常用操作,创建分支和切换分支,也可以称为检出分支。

首先我们新建一个仓库gitTest,然后新建文件a,为什么要用a命名呢,这里是故意为之,后面为大家揭晓分支。呵呵。或许下面的介绍会有些枯燥乏味,因为您已经对这些命令烂熟于胸,而且运用得相当熟练,那么您可以直接跳过这一步。

在master分支上,做一次提交c1,然后现在新建一个分支a,并切换到a分支。

这个操作主要会用到两个命令:

创建新分支:git branch branchName

切换到新分支:git checkout branchName

然后,上面两个命令也可以合成为一个命令:

git checkout -b branchName

(二)真相——HEAD是checkout的灵魂

其实,我们在切换分支,和新建分支的时候,有没有想过,这些操作操作背后的工作原理是怎样的呢?最大的功臣就是.git目录下的HEAD引用,她宛如一个芭蕾舞者,从一个分支飘逸的跳到另一个分支,虽无声无息,却精准无比。

在我们身处master分支的时候,您一定很好奇,当前的HEAD的内容是什么?不妨来看看吧。

我们看到c1的提交hash值和HEAD对应分支master的当前hash值是一样的。也就是说,HEAD指向的是当前分支名master,而master又对应了当前的最新的一次提交ID.

好,那么我们再做一次提交,看看master对应的hash值有无变化。

从上图,我们可以不难看出,HEAD对应的ref没有变化,还是master,但是master对应的commit ID却变成了c2对应的commit ID,即更新为最后一次提交的ID咯。

现在,提交一次的原理,我们已然了解,那么切换分支的时候呢??

现在我们身处master分支,然后我们切换到a分支,看看会发生什么样的情况吧。

从上图分析,在master分支上的时候,HEAD指向的是master,对应的是c2的commit ID。而切换到a分支的时候,HEAD也相应的指向了a,同时a对应的是a分支上的最新commit ID。因此,我们可以得出结论,在切换分支的时候,HEAD也会相应的指向对应的分支引用。

但是,使用checkout命令的时候,并不是每次都会改变HEAD指针的指向哦。在什么情况下HEAD一直坚定不移的拥护者他的女神呢?可谓衣带渐宽终不悔,长使英雄泪满襟啊!让我们接着往下看。

(三)进阶——HEAD懂不懂,看你怎么用

checkout命令用法如下:

1. git checkout [-q] [<commit>] [--] <paths> ...

2. git checkout [<branch>]

3. git checkout [-m] [ [-b | -- orphan ] <new_branch>]  [start_point]

用法2比用法1的区别在于,用法1包含了路径。为了避免路径和引用(或提交ID)同名而发生冲突,可以在<paths>前用两个连续的连字符作为分隔。用法1的<commit>是可选项,如果省略,则相当于从暂存区进行检出。

来看个例子:

情景1,省略掉<commit>

现在我们处于master分支下,然后我们修改了文件a,输入“c3”文本到a中,这时候,暂存区中的内容是没有"c3"的,通过git diff可以比较。现在我们从当前分支暂存区中检出文件a。那么我们可以直接使用git checkout a。

这时候,提示检出失败,git以为我们想检出仓库a。还记得为什么在第一步中,我们曾新建的文件a吗?这里终于派上用场了,由于仓库中还存在分支a,同时当前分支中又存在文件a,于是git傻傻分不清楚了。这时候怎么办?有两个办法,第一,我们在命名分支的时候要注意语义性,分支名要具有一定的意义,不能使用简单的a,b,c来命名,这样很容易导致分支名和文件名重复;第二,参照用法1,使用两个连字符来分隔。在目前的情形中,我们使用第二种方法吧。

这时候,发现工作区的内容被暂存区的内容覆盖,"c3"文本也没有了,当然HEAD指针也没有什么变化,一切又恢复了平静。

再看一个例子:

情景2,不省略<commit>

在不省略<commit>的时候,<commit>既可以是某一个具体的commit hash值,也可以是某个分支名称,tag名称。不论分支也好,tag也好,它们本质上对应的都是一个commit hash值。

在检出a分支下的a文件的时候,最好把两个连字符加上,不然git也会无法区分。整个过程中,HEAD头指针没有发生改动。

总结:第1种用法(包含<paths>的用法)不会改变HEAD头指针,主要使用于指定版本的文件覆盖工作区中对应的文件。如果省略<commit>,则会用暂存区的文件覆盖工作区中的文件,否则用指定提交中的文件覆盖暂存区和工作区中的对应文件。

接下来,我们看看用法2,在第一部分中,我们知道切换分支,会改变HEAD的指向,那么如果我们是检出某个commit会怎样呢?同检出分支一样,会用该commit下的内容覆盖当前分支工作区和暂存区的内容,请看例子。

目前我们处于master分支上,且已经有了两次提交,分别是c1和c2,然后我们修改a,给a文件添加内容"c3",并add到暂存区,随即使用checkout到c1的commit 上。注意,刚开始checkout的时候,git不会允许你直接切换,因为你修改了暂存区的内容, 它会提醒你提交后再切换,这时候,你可以使用-f 强行切换。再查看状态的时候,git提示我们已经不在任何分支上,HEAD指针也是指向具体的c1的commit值,进入了“分离头指针”状态。这个状态下,要回到master上面,只需要git checkout master即可,也可以在这个状态上新建分支。

如果,checkou后面不跟任何参数,则就是对工作区进行检查,请看例子。

我们身处master分支上,并且没有任何改动,这时候git checkout没有任何输出。然后,我们给a文件添加内容“c3”,然后再git checkout一下,git就会提示a文件有修改,是不是很简单?

总结:对于第2种用法,不是检出某个具体文件的的时候,即不指定<paths>的时候,单纯的检出某个commit或分支,是会改变HEAD头指针的。而且只有当HEAD切换到某个分支的时候才可以对提交进行跟踪,否则就会进入“分离头指针”的状态。如果省略用法2后面的<branch>,则默认对工作区进行状态检查。

(四)熟悉的checkout,陌生的用法,妈妈再也不用担心我的checkout啦!

1. git branch <branch> <start point>

以某个commit创建新分支。 在通常情况下,我们都会在当前分支的基础上,创建新分支。比如git branch new_branch

也许你不知道,我们还可以基于当前分支的某一次commit来创建分支。请看!

从上图可见,我们想基于master分支的c1 提交ID创建新分支new_branch,创建成功后,切换到new_branch,查看log,只有c1,耶~~成功啦!

当然,也可以使用git checkout -b <new_branch> <start point>这个常用的命令。

2.  git checkout --datch <branch>

切换到分支的游离状态,默认以该分支下的最后一次提交ID,请看下面的例子。

当前分支为a,然后使用git checkout --detach master,那么HEAD就会切换到master的最后一次commit值的状态下!

3. git checkout -B <branch>

这个命令,可以强制创建新的分支,为什么加-B呢?如果当前仓库中,已经存在一个跟你新建分支同名的分支,那么使用普通的git checkout -b <branch>这个命令,是会报错的,且同名分支无法创建。如果使用-B参数,那么就可以强制创建新的分支,并会覆盖掉原来的分支。请看具体操作。

当前分支为master,且仓库中已经存在分支a,我们先用git checkout -b a来创建a分支,必然会失败的,并提示我们仓库中已经有了一个a分支咯,仿佛在说“hi,哥们,你已经有了一个老婆了,一夫一妻制你的不懂?你以为这里是印度啊?”。随后,我们使用git checkout -B a,耶~~,it works!

4. git checkout --orphan <branch>

是的,假如你的某个分支上,积累了无数次的提交,你也懒得去打理,打印出的log也让你无力吐槽,那么这个命令将是你的神器,它会基于当前所在分支新建一个赤裸裸的分支,没有任何的提交历史,但是当前分支的内容一一俱全。新建的分支,严格意义上说,还不是一个分支,因为HEAD指向的引用中没有commit值,只有在进行一次提交后,它才算得上真正的分支。还等什么呢?赶紧试试!

好了,现在我们终于找到组织了!

5. git checkout --merge <branch>

这个命令适用于在切换分支的时候,将当前分支修改的内容一起打包带走,同步到切换的分支下。

有两个需要注意的问题。

第一,如果当前分支和切换分支间的内容不同的话,容易造成冲突。

第二,切换到新分支后,当前分支修改过的内容就丢失了。

所以这个命令,慎用!

6. git checkout -p <branch>

这个命令可以用来打补丁。这个命令主要用来比较两个分支间的差异内容,并提供交互式的界面来选择进一步的操作。这个命令不仅可以比较两个分支间的差异,还可以比较单个文件的差异哦!

结束语:至此,关于git checkout命令暂告一段落,对于checkout命令,你也有所熟悉了吧。当然,git checkout还有一些其它用法,本文并没有讲到,你可以在git bash或终端中使用git checkout --help去进一步了解

git checkout 命令详解相关推荐

  1. git checkout 命令详解—— Git 学习笔记 16

    git checkout 命令详解 概览 git checkout 这条命令的常用格式如下: 用法一 git checkout [<commit>] [--] <paths> ...

  2. Git(8)-- 撤消操作(git commit --amend、git reset 和 git checkout 命令详解)

    文章目录 1.撤消操作:`git commit --amend` 实例详解: 2.取消暂存的文件:`git reset` 3.撤消对文件的修改:`git checkout` 超详细 Git 图文版小白 ...

  3. git reset 命令详解(一)—— Git 学习笔记 07

    git reset 命令详解(一) 简而言之,git reset 命令是用来将当前 branch 重置到另外一个 commit 的,这个动作可能同时影响到 index 以及 work director ...

  4. Git 常用命令详解

    Git 常用命令详解 1. Git 常用命令 1.1 常用git 命令图表汇总 1.2 配置个人信息 1.3 创建版本库 1.4 常用Git命令汇总 2. Git 解决代码冲突 3. Git 分支管理 ...

  5. git reset 命令详解(二)—— Git 学习笔记 08

    git reset 命令详解(二) 上一篇博文git reset 命令详解(一)讲了 git reset 命令的基本原理和用法,这篇博文谈一谈 git reset 的另一种用法--后面跟一个路径(或文 ...

  6. git diff命令详解

    git diff命令详解 diff里面a表示前面那个变量,b表示第二个变量 HEAD     commit版本 Index     staged版本 a.查看尚未暂存的文件更新了哪些部分,不加参数直接 ...

  7. git log 命令详解

    git log 命令详解 git log 命令用于查看提交历史: git log [options] [<file> <commit> <tag>...] 如果不加 ...

  8. 运维之道 | Git log 命令详解

    Git log 命令详解 Git log 可以让我们查看提交commit history [root@localhost villian]# git log commit 7a690b414f87fb ...

  9. git reset 命令详解 git revert命令详解。

    git reset 命令详解 reset命令 介绍 参数 补救 git revert命令 revert说明 举例: 命令 reset命令 介绍 git reset 命令格式为: git reset [ ...

最新文章

  1. 使用 NSUserDefaults 存储字典的一个坑
  2. VS快捷键大全(总结了一些记忆的口诀)
  3. Android日志系统分析之日志设备驱动程序代码阅读
  4. linux 性能测试 antutu,除了安兔兔跑分,还有这6种办法能证明手机强弱
  5. sizeof 是关键字不是函数!使用sizeof需要注意?
  6. 7年Java后端被淘汰,一路北漂辛酸史。。。
  7. const 作用 c语言,在C语言中const 作用的的全面总结.doc
  8. [占坑] 近几天正在准备的文章
  9. 闭包,sync使用细节
  10. win10高分辨率下修改字体显示大小(不是缩放百分比)
  11. 浙江师范大学c语言函数实验答案,浙江师范大学2012年秋C语言考试卷与答案
  12. 融合大数据能力,解决在存量时代下的力分之困
  13. iOS应用日志:开始编写日志组件与异常日志
  14. 机器学习基础:核密度估计(Machine Learning Fundamentals: Kernel Density Estimation)
  15. 单目相机与激光标定相关文章与代码(草稿)
  16. 74.android 简单的跳转到小米安全中心首页和小米安全中心的权限管理
  17. android转场动画的两种方式
  18. 从Outlook到python都可以使您的工作减少一半
  19. Python打印表格
  20. mysql存储过程 根据查询的结果集向表中插入数据

热门文章

  1. eclipse中的maven build、maven clean、maven install和maven test的区别
  2. Aiiage Camp Day4 A Board game
  3. angular2 组件交互
  4. SVN报错working copy is not uptodate
  5. Xamarin 中Visual Studio创建项目提示错误
  6. Java知多少(96)绘图之设置字型和颜色
  7. 使用httpHandlers进行url rewrite时,提示http 404 error 错误
  8. 怎样用java写一个简单的文件复制程序
  9. 【数据结构与算法】之深入解析“按要求补齐数组”的求解思路与算法示例
  10. Algorithm Master Road:算法的时间/空间复杂度