标签: git
[TOC]
1.Git结构
- 工作区/工作树/工作目录:当前Git正在管理的这个文件夹
- 暂存区/索引区/缓存区:stage/index/cache,即工作区根目录下的'.git/index'文件
- 版本库/本地仓库/文档库:Repository,即工作区根目录下的'.git'目录
- 远程仓库
2.工作区目录追踪
当处于工作区目录或子目录下时,可用下面命令查询各目录:
- 显示版本库(.git)位置
$ git rev-parse --git-dir
- 显示工作区根目录
$ git rev-parse --show-toplevel
- 显示当前位置相对于工作区根目录的相对目录
$ git rev-parse --show-prefix
- 显示从当前目录(cd)后退(up)到工作区的根的深度
$ git rev-parse --show-cdup
- 浏览暂存区目录树
$ git ls-files
- 浏览HEAD目录树
$ git ls-tree HEAD
3.Git配置
Git的配置文件 "INI"格式的。
(1)配置文件及其优先级
Git共有3个配置文件,优先级高的配置会覆盖优先级低的配置。在git config
命令中加上配置文件的位置命令标识,可以配置指定级别的配置文件。默认不加则为 “--global”。
名称 | 优先级 | 命令标识 | 配置文件位置 | 别称 |
---|---|---|---|---|
仓库级 | 最高 | --local | 工作区的".git/config"文件 | 本地配置文件 |
全局级 | 中等 | --global | 用户主目录下的".gitconfig"文件 | 全局配置文件 |
系统级 | 最低 | --system | "/etc/gitconfig"文件 | 系统配置文件 |
(2)常用配置命令
Git的 "config" 命令可根据指定的配置文件位置标识来配置特定的文件,不指定则默认全局配置。
$ git config [--local|--global|--system] action
其中"action"可有以下取值(其中的键值格式为 "<section>.<key> [value]" ):
- --get : 获取键的值
- --add : 添加键值
- --unset : 删除键的值
- --list, -l : 查看已配置的选项
- --edit, -e : 直接编辑配置文件
另外,也可用下面的命令获取和设置键值(命令中省略了文件位置标识):
- 获取键值
$ git config <section>.<key>
- 设置旧键的新值或添加新键值
$ git config <section>.<key> value
(3)配置用户名和密码
Git中必须配置用户名和密码,它们的键分别为 "user.name" 和 "user.email" 。
(3)使用"git config"命令操作其他INI文件
- 设置键值
$ GIT_CONFIG=INI文件名.ini git config <section>.<key> value
- 读取键值
$ GIT_CONFIG=INI文件名.ini git config <section>.<key>
4.状态查看
使用下列命令可以查看文件状态:
$ git status
加上"-s"选项表示使用精简模式:
$ git status -s
精简模式下显示的文件状态中,格式如下:
状态标识1状态标识2 文件名
其中状态标识1和状态标识2分别位于第1列和第2列,其含义为:
- 第一列:"暂存区"相对于"版本库"中的文件有改动,蓝色标记
- 第二列:"工作区"相对于"暂存区"中的文件有改动,红色标记
每列的标识可取以下值:
- A: 新增了文件
- C: 文件的一个新拷贝
- D: 删除了文件
- M: 文件的内容或者mode被修改了
- R: 文件名被修改了
- T: 文件的类型被修改了
- U: 文件没有被合并(你需要完成合并才能进行提交)
- X: 未知状态(很可能是遇到Git的bug了,你可以向git提交bug report)
5.Git工作区、版本库、暂存区原理图
简要说明:
- 图中左侧为工作区,右侧为版本库。在版本库中标记为index的区域是暂存区,标记为master的是master分支所代表的的目录树。
- 图中的HEAD实际上是指向master分支的一个"游标",所以图示的命令中出现HEAD的地方可以用master替换。
- 图中的objects标识的区域为Git的对象库,实际位于".git/objects"目录下。
- 对工作区修改或新增的文件执行
git add
命令时,暂存区的目录树将被更新,同时工作区修改或新增的文件内容会被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。 - 当执行提交操作(
git commit
)时,暂存区的目录树会写到版本库(对象库)中,master分支会做相应的更新,即master最新指向的目录树就是提交时原暂存区的目录树。 - 当执行
"git reset HEAD"
命令时,暂存区的目录树会被重写,会被master分支指向的目录树所替换,但是工作区不收影响。 - 当执行
"git rm --cached <file>"
命令时,会直接从暂存区删除文件,工作区则不会做出改变。 - 当执行
"git checkout ."
或"git checkout -- <file>"
命令时,会用暂存区全部的文件或指定的文件替换工作区的文件。这个命令会清除工作区中未添加到暂存区的改动。 - 当执行
"git checkout HEAD ."
或"git checkout HEAD <file>"
命令时,会用HEAD指向的master分支中的全部或部分文件替换暂存和工作区中的文件。这个命令不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
6.工作区、暂存区和版本库之间的差异比较
(1)工作区与暂存区比较
$ git diff
(2)工作区与HEAD比较
$ git diff HEAD
(3)暂存区与HEAD比较
$ git diff --cached|--staged
7.HEAD与master
- master:在版本库的引用目录(.git/refs)中体现为一个引用文件".git/refs/head/master",其内容就是分支中最新提交的提交ID
- HEAD:位于版本库的".git/HEAD"文件,其内容指向了"master",因此和master是一样的
8.分支与ID查看
- 查看当前分支
$ git branch
- 根据对象SHA1 ID显示对象信息
$ git cat-file -t|-p|-s "对象ID"
- 显示分支对应的SHA1 ID
$ git rev-parse "分支名称(HEAD/master)"
9.重置命令
(1)用法1
不会重置引用,更不会改变工作区,而是用指定提交状态下的文件替换掉暂存区中的文件
$ git reset [-q] [<commit>] [--] <paths>...
<commit>为可选项,可以首映引用或提交ID;如果省略则相当于使用了HEAD的指向作为提交ID。
(2)用法2
会重置引用,根据不同选项,可以对暂存区或工作区进行重置。
$ git reset [--soft|--mixed|--hard|--merge|--keep] [-q] [<commit>]
- --soft:执行图中的动作1,只更改引用的指向,不改变工作区和暂存区
- --mixed:默认参数,执行图中的动作1、2。即更改引用的指向并重置暂存区,但不改变工作区
- --hard:会执行上图中的全部动作1、2、3,即:
a.替换引用的指向。引用指向新的提交ID
b.替换暂存区。替换后,暂存区的内容和引用指向的目录树一致
c.替换工作区。替换后,工作区的内容和暂存区一致,当然同时也和引用指向的目录树一致
(3)例子
-
git reset
或git reset HEAD
:仅用HEAD指向的目录树重置暂存区,工作区不会受到影响,相当于将之前用"git add"命令跟新到暂存区的内容撤出暂存区。引用也未改变,因为引用重置到HEAD相当于没有重置 -
git reset -- filename
或git reset HEAD filename
:仅将文件filename的改动撤出暂存区,暂存区中其他文件不改变。相当于对命令"git add filename"的反向操作 -
git reset --soft HEAD^
:工作区和暂存区不改变,但是引用向前回退一次。当对最新提交的提交说明或提交的更改不满意时,撤销最新的提交以便重新提交 -
git reset --mixed HEAD^
:工作区不改变,但是暂存区会回退到上一次提交之前,引用也会回退一次 -
git reset --hard HEAD^
:彻底撤销最近的提交。引用回退到前一次,而且工作区和暂存区都会回退到上一次提交的状态。自上一次一来的提交全部丢失。
10.检出命令
检出命令会重写工作区。
(1)用法1
$ git checkout [-q] [<commit>] [--] <paths>...
<commit>是可选项,如果省略则相当于从暂存区进行检出。
此种用法不会改变HEAD头指针,主要用于用指定版本的文件覆盖工作区中对应的文件。如果省略<commit>,则会用暂存区的文件覆盖工作区的文件,否则用指定提交中的文件覆盖暂存区和工作区中对应的文件。
注意:此用法和重置命令大不相同,重置命令默认值是HEAD,而检出命令默认值是暂存区。因此重置一般用于重置暂存区(除非使用--hard参数,否则不重置工作区);检出主要是覆盖工作区(如果<commit>不省略,也会提换暂存区中相应的文件)。
(2)用法2
$ git checkout [<branch>]
此种用法会改变HEAD头指针。主要是用来切换到分支。如果省略了<branch>则相当于对工作区进行状态检查。
(3)用法3
$ git checkout [-m] [[-b]--orphan] <new_branch>] [<start_point>]
此种用法主要是创建和切换到新的分支,新的分支从<start_point>指定的提交开始创建。
(4)例子
-
git checkout branch
:检出branch分支。会执行上图中的1、2、3步骤,并更新HEAD以指向branch分支 -
git checkout
或git checkout HEAD
:汇总显示工作区、暂存区与HEAD的差异 -
git checkout -- filename
:用暂存区中的filename文件来覆盖工作区中的filename文件。相当于取消自上次执行"git add filename"以来(如果执行过)的本地修改 -
git checkout -- .
或git checkout .
:会取消本地所有的相对于暂存区的更改,相当于用暂存区的所有文件直接覆盖工作区文件。 -
git checkout branch -- filename
:维持HEAD的指向不变。用branch所指向的提交中的filename替换暂存区和工作区中的filename文件。