diff 的输出格式,能够分为:正常格式,上下文格式,合并格式.这里只介绍合并格式.经过 -u 选项指定了 diff 的输出为合并格式.如: linux
$ cat f1 a a a b a a a $ cat f2 a a a a a a a $ diff f1 f2 -u --- f1 2014-06-03 00:47:10.859206823 +0800 +++ f2 2014-06-03 00:47:06.319206762 +0800 @@ -1,7 +1,7 @@ a a a -b +a a a a
diff -u 的输出能够分为三个部分,其中第一部分以下:git
--- f1 2014-06-03 00:47:10.859206823 +0800 +++ f2 2014-06-03 00:47:06.319206762 +0800 # --- 表示改动前的文件.+++ 表示改动后的文件.
第2部分以下:shell
@@ -1,7 +1,7 @@ # @@ ... @@ 指明了一个改动位置. # -1,7 中;'-'表示 --- 指向的文件,即改动前的文件.'1' 表示第1行,'7'表示连续7行. # +1,7 中;'+'表示 +++ 指向的文件,即改动后的文件.'1' 表示第1行,'7'表示连续7行. # @@ ... @@ 的总的意思就是文件 f1 的[1,8)行通过以下改动后变为 f2 的[1,8)行.
第3部分就是改动的详细内容:工具
a a a -b # '-' 表示移除该行. +a # '+' 表示新增该行. a a a
智能协议,会话的两个版本库会打开辅助程序进行数据传输,直观感觉: 具备进度显示,按需传输速度快.测试
哑协议,会话的两个版本库不会打开辅助程序,直观感觉: 不具备进度显示,速度慢.fetch
远程版本库相应分支的最新提交是本地版本库相应分支最新提交的祖先,则此时 git push 为快进式推动.ui
日志空间,该目录下全部文件均是日志.url
每个引用文件在 .git/logs 下都有对应的日志文件,用于记录引用文件内容的变动,即当引用文件内容发生变化时,就将新的内容追加在它对应的日志文件的末尾.如:spa
$ cat .git/refs/heads/master # 显示 master 引用文件的内容 485499 $ cat .git/logs/refs/heads/master # 显示 master 对应日志文件的内容 000000 f3e91c commit (initial): 初始化 f3e91c 236aa5 commit: * get_modify_args.c 236aa5 4f7bff merge 重作: Fast-forward 4f7bff 11176b commit: 添加了 unmap 子命令 11176b e137ac commit: 新增 protect 子命令 e137ac 49a5d7 commit (amend): 新增 protect 子命令 49a5d7 485499 commit (amend): 新增 protect 子命令 $ git commit -m"测试" --allow-empty # 建立一个空的提交. [master 903b0f] 测试 $ cat .git/refs/heads/master # master 引用文件内容变化,指向着最新提交. 903b0f $ cat .git/logs/refs/heads/master # master 对应日志文件内容也变化 000000 f3e91c commit (initial): 初始化 f3e91c 236aa5 commit: * get_modify_args.c 236aa5 4f7bff merge 重作: Fast-forward 4f7bff 11176b commit: 添加了 unmap 子命令 11176b e137ac commit: 新增 protect 子命令 e137ac 49a5d7 commit (amend): 新增 protect 子命令 49a5d7 485499 commit (amend): 新增 protect 子命令 485499 903b0f commit: 测试
该目录用于存放全部的 git object.即 commit object,tag object,blob object,tree object.3d
若一个 git object 的 SHA1 值为 XYXXX...YYY,则其在 .git/objects 下的路径为: XY/XXX...YYY.如 commit object 903b0f4f9ad3d1f59a9cd12eb63ab6f21dbec1b9 的路径为:
$ ls -l .git/objects/90/3b0f4f9ad3d1f59a9cd12eb63ab6f21dbec1b9 -r--r--r-- .git/objects/90/3b0f4f9ad3d1f59a9cd12eb63ab6f21dbec1b9
.git/index 能够认为就是一个 tree object,存放着暂存区目录树的信息.
当使用git status.
若一个文件仅在工做区或者暂存区中存在,则输出相应的提示信息.
不然一个文件在工做区,暂存区中均存在,此时:
// 在 tree object 中保存着文件的最后一次修改时间 if(文件在工做区的最后一次修改时间 == 文件在暂存区中的最后一次修改时间){ 说明文件没有通过改动; 略过该文件,继续下一个文件; }else{ 比较文件的内容; // 在 tree object 中存在着保存文件内容的 blob object 的 SHA1 值. if(文件内容没有通过改变) 更新文件在暂存区中的最后一次修改时间; // 这样下一次调用 git status 就没必要要读取文件内容. else 输出相应的提示信息,代表文件通过改动. }
当使用 git diff 时,与 git status 相似,只不过当文件内容通过改动时,输出改动信息.
当使用 git add 时:
if(文件在暂存区中不存在 || 文件通过改动){ 新建一个 blob object,将改动后的文件信息写入该 blob object 中; 更新文件在暂存区的文件状态信息,以及对应 blob object 的 SHA1 值; // 参考 tree object 的结构. }else 直接返回.
存放着 .git/refs/tags/ 下,也是引用文件,经过对 commit object/tag object 的引用来代表当前提交具备'里程碑'的意义.
轻量级标签,仅是经过 commit object 的引用来代表当前提交具备里程碑的意义,并无新建一个 tag object.轻量级标签不能够带有注释,以及不能够被签名.
重量级标签,是对 tag object 的引用,即经过新建一个 tag object 来代表当前提交具备里程碑的意义,能够带有注释,以及能够被签名.如:
$ git tag Qing # 建立一个轻量级标签 $ git tag -m"注释" Zhong # 建立一个重量级标签 $ ls -l .git/refs/tags/ 总用量 8 -rw-r--r-- 1 root root 41 6月 1 13:12 Qing -rw-r--r-- 1 root root 41 6月 1 13:12 Zhong $ git cat-file -t $(cat .git/refs/tags/Zhong) # 重量级标签是对 tag object 的引用. tag $ git cat-file -t $(cat .git/refs/tags/Qing) # 轻量级标签是对 commit object 的引用 commit
当使用 git push 时,默认是不会上传标签的,即 tag object 与 .git/refs/tags/ 下的内容不会被上传.除非显式上传,如使用 --tags 选项,或者在 git push 时使用引用表达式.
当使用 git pull 时,默认会下载当前远程分支上的 tag ,而不会获取其余分支.
当本地已有同名 tag ,则默认不会下载对应的 tag ,除非显式使用引用表达式!
此时下载下来的 tag 引用并非存放在 .git/refs/remote/<远程版本库名>/tags 中,而是统一存放在 .git/refs/tags 下.
当使用 git branch -d -r 删除远程分支时,并不会删除关联的 tag object.
git init 建立的 .git 目录就被成为 git 版本库;.git 目录所处的目录为工做区.
工做区,也至关于一个 tree object,保存着位于工做区的文件,目录信息.
裸版本库,也即没有工做区的版本库,此时 core.bare==true.如:
$ git clone --bare Test/ Git_bare 克隆到裸版本库 'Git_bare'... 完成。 Checking connectivity... done $ cd Git_bare/ $ ls # 裸版本库没有工做区, branches config description HEAD hooks info objects packed-refs refs $ git config core.bare true # 而且 core.bare 为真
分支,就是由若干个 commit object 组成的一条链.从应用的角度,分支能够分为:
发布分支,待补充
特性分支,待补充
卖主分支,待补充
git 配置文件是由一系列名值对组成,而且使用'节'的概念将这些名值对组织在一块儿,如:
$ cat .git/config [core] # 就是一个节, repositoryformatversion = 0 filemode = true # 经过 core.filemode 来访问该选项. bare = false logallrefupdates = true [remote "origin"] url = git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git fetch = +refs/heads/*:refs/remotes/origin/* # 经过 remote.origin.fetc 来访问该选项. [branch "master"] remote = origin # 经过 branch.master.remote 来访问该项 merge = refs/heads/master
注意,对配置项的访问方式.
级别名称 |
文件位置 |
访问/修改 |
优先级别 |
系统级别 |
/etc/gitconfig |
git config --system |
最低 |
用户级别 |
~/.gitconfig |
git config --global |
中等 |
项目级别 |
项目目录/.git/config |
git config |
最高 |
优先级高的会覆盖优先级低的
ui true/false,若 color.ui 为真,则在 git 的输出中会开启颜色显示.
logAllRefUpdates true/false 若为 true,代表启用引用日志功能,即每当引用文件(.git/HEAD,.git/refs/heads/*.*,.git/refs/stash)改变时,就将改变信息记录在 .git/logs/ 指定的文件中.裸版本库不会将该属性设置为 true,因此如有必要,应该手动设置.
denyNonFastForwards true/false 若未真,则总会拒绝其余版本库的非快进式提交.
denyDeletes true/false 若为真,则禁止其余版本库经过 git push :remote-ref 来删除本地引用,效果以下:
A$ git branch # 版本库 A 当前分支. b1 b2 * master A$ git config receive.denyDeletes true B$ git push origin :refs/heads/b1 # 在 B 中试图删除 A 的 b1 分支. remote: error: denying ref deletion for refs/heads/b1 To /root/CCProject/A ! [remote rejected] b1 (deletion prohibited) error: 没法推送一些引用到 '/root/CCProject/A' # 因为在 A 中 receive.denyDeletes==true,因此删除失败 A$ git branch -D b1 # denyDeletes 只是禁止其余版本库删除,而不是本地版本库 已删除分支 b1(曾为 787d106). A$ git config receive.denyDeletes false B$ git push origin :refs/heads/b2 To /root/CCProject/A - [deleted] b2 # 因为 receive.denyDeletes==false,因此在 B 中删除 A 的 b1 分支成功. A$ git branch * master
tool 配置了调用 git mergetool 时启用的工具.若配置的工具不被 git 内部支持,则还须要配置 merge.<tool>.path(肯定路径) merge.<tool>.cmd(调用该工具时的命令),不过通常下 git 支持不少种工具,包括: kdiff3,meld.
conflictstyle merge/diff3
# 若其值为 merge,则会在冲突文件使用'<<<<<<<','=======','>>>>>>>'对冲突内容标识,如: <<<<<<< #本地修改的版本 ======== >>>>>>> #他人修改的版本 # 若其值为 diff3,则会在冲突文件下使用'<<<','|||','>>>','==='对冲突内容进行标识,如: <<<<<<<#本地修改的版本 |||||||#祖先版本 =======#他人修改的版本 >>>>>>>