以跟踪,未跟踪文件详情:
2.6 打标签
轻量标签与附注标签的区别
轻量标签很像一个不会改变的分支————它只是某个特定提交的引用,它本质上是将提交校验和存储到一个文件中。
而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。
如果你只是想用一个临时的标签, 或者因为某些原因不想要保存这些信息,可以用轻量标签。
7.7 重置揭密
三颗树
| 树 | 用途 | | —- | —- |
| HEAD | 上一次提交的快照,下一次提交的父结点 |
| Index | 预期的下一次提交的快照 |
| Working Directory | 沙盒 |
下图就是这三棵树的工作流程:
当初始化一个 Git 仓库时,这三棵树长这样:
通过几次提交,就成了这样
Git reset 与 Git checkout 对比
|
| HEAD | Index | Workdir | WD Safe? (磁盘安全) | | —- | —- | —- | —- | —- |
| Commit Level | | | | |
|
reset --soft [commit]
| REF
| NO
| NO
| YES
|
|
reset [commit]
| REF
| YES
| NO
| YES
|
|
reset --hard [commit]
| REF
| YES
| YES
| NO
|
|
checkout
| HEAD
| YES
| YES
| YES
|
| File Level | | | | |
|
reset [commit]
| NO
| YES
| NO
| YES
|
|
checkout [commit]
| NO
| YES
| YES
| NO
|
7.8 高级合并
revert 的注意事项
revert 在还原合并分支提交时,有一些需要注意的点。
想来看一个案例:现在有两个分支:master
和 topic
,且两分支已经合并
你可以使用 git reset --hard HEAD~
来很好的返回这次合并。但是该提交已经被传到云上,为了照顾你的队友,你选择使用 revert
:
$ git revert -m 1 HEAD
这里 -m 1
是为了和 C6
保持一致,如果换成 -m 2
那就和 C4
保持一致了
第一个需要注意的点是,你现在无法合并了
$ git merge topic
Already up-to-date.
因为 topic
已经成了 master
分支的子节点,所以会显示目前没有什么要合并的(你可以选择 rebase topic
,他会将 C5
、C6
变基到 C4
的后面)
如果你继续在 topic
上提交代码,并合并到 master
分支上,Git 只会引入被还原的合并 之后 的提交(如下图所示,只有 C7
的修改引入了 C8
,而 C3
、C4
没有)
解决这个最好的方式是撤消还原原始的合并,这样你想要引入被还原出去的修改。但会提交看起来会更加复杂
$ git revert ^M
[master 09f0126] Revert "Revert "Merge branch 'topic'""
$ git merge topic
在本例中,M
与 ^M
抵消了。 ^^M
事实上合并入了 C3
与 C4
的修改,C8
合并了 C7
的修改,所以现在 topic
已经完全被合并了。
7.11 子模块
8.2 Git 属性
基于路径的设置项被称为 Git 属性,可以在你的目录下的 .gitattributes
文件内进行设置(通常是你的项目的根目录)。如果不想让这些属性文件与其它文件一同提交,你也可以在 .git/info/attributes
文件中进行设置。
.gitattributes
// 把所有 pbxproj 文件当成二进制文件
*.pbxproj binary
// 所有匹配 .docx 模式的文件都应该使用 "word" 过滤器。 "word" 过滤器需要自己配置
*.docx diff=word
// 所有匹配 .png 模式的图片都应该使用 "exif" 过滤器。
*.png diff=exif
// 对 filter 属性设置 "indent" 过滤器来过滤 *.c 文件
*.c filter=indent
// 不想在使用 git archive 创建的压缩包中包含 test/ 子目录或文件,但想把它们纳入项目的版本管理中
test/ export-ignore
// 在项目中包含一个叫做 LAST_COMMIT 的文件, 并在运行 git archive 的时候自动向它注入最新提交的元数据(可以直接使用 git log 中 pertty=format 中的处理器)
LAST_COMMIT export-subst
// 配置 database.xml 使用自定义的 ours 策略
database.xml merge=ours
设置在 .gitattributes
中的文件,不会尝试转换或修正回车换行(CRLF),运行 git show
或 git diff
时,也不会比较或打印该文件的变化。
配置过滤器
# 配置 "word" 过滤器,其中 docx2txt 是可执行命令,也可以是自己创建的 shell 文件
$ git config diff.word.textconv docx2txt
# 配置 "exif" 过滤器,其中 exiftool 是可执行命令
$ git config diff.exif.textconv exiftool
# 配置 "indent" 过滤器在 smudge 和 clean 时分别该做什么
$ git config filter.indent.clean indent(此处,也可以是一个脚本文件)
$ git config filter.indent.smudge cat(或一段命令)
# 自定义虚拟合并策略为 ours ,这样会让该文件保持主干分支中的原始版本
git config merge.ours.driver true
自定义过滤器真的很强大。不过注意的是,因为 .gitattributes
文件会随着项目一起提交,而过滤器(不会,所以过滤器有可能会失效。
8.3 Git 钩子
10.1 内部原理
从根本上来看,Git 是一个内容寻址文件系统。
对于一个全新的 git 版本库来说 .git
目录下的内容为:
$ ls -F1
branches/ ->
config -> 包含项目的配置选项
description -> GitWeb 程序使用
HEAD -> 当前被检出的分支,如果不是分支,那就是分离 HEAD 情况
hooks/ -> 包含服务端或客户端的钩子脚本
info/ -> 包含一个全局性排除文件,用于放置不希望记录在 .gitignore 文件中忽略模式
objects/ -> 存储所有的数据内容
+--- info -> 索引文件,包含了包文件的偏移信息
\--- pack -> 包目录,将对象进行打包。包文件可以通过索引文件快速定位任意指定对象
refs/ -> 存储指向数据(分支、远程仓库和标签等)的提交对象的指针
# 以下是第一次创建并不会有,但是在后续的使用中会出现
index -> 保存暂存区信息
│ │ └── 49b077972391ad58037050f2a75f74e3671e92
│ ├── info
│ │ └── packs
│ └── pack
在 Git 中,都用 zlib 压缩的内容来写入磁盘上的某个对象