GIT 高手9问
- 1、git 比其它版控工具快的原因?
- 2、git 将版本库和工作区放在同一个目录,究竟是好是坏?
- 3、git 默认只在根目录有.git版本库,其子目录是如何发现版本库呢?
- 4、git config --global --system 究竟有什么区别?
- 5、git commit生成的`HASH`为什么不用顺序数字代替?
- 6、git 工作区如何归档压缩?
- 7、如何使用`GIT`找出`BUG`缔造者?
- 8、TAGS(里程碑)有什么用?
- 9、非技术问
开始阅读前,我估且认为您已经是
GIT
老手了。
1、git 比其它版控工具快的原因?
- 分布式,每个
client
都是server
,没有跨网络等待时延 git
的判别文件是否有变化是根据文件的时间缀、大小、指纹HASH
,变化的文件以快照的方式存储,没有变化则更改链接指向。而CVS,SVN
等传统工具,则是每次记录文件变化的内容,随时间长短和项目大小变化,计算量直接影响速度快慢。
综上:快
2、git 将版本库和工作区放在同一个目录,究竟是好是坏?
- 首先:传统版控工具特意将数据和版本库分开存放,是为了数据安全,主要是磁盘损坏等物理行为造成的数据不可逆损坏
- 其次:这是一个鸡生蛋,还是蛋生鸡的问题。到底哪种方式安全各有说法
- 最后,也是最重要:
git
本身分布式的架构方式已经解决了鸡生蛋,还是蛋生鸡的问题。不同于集中管理的方式,git
每个用户都是版控机 。即使server
挂了也丝毫不会影响版本库和数据。
综上:好
3、git 默认只在根目录有.git版本库,其子目录是如何发现版本库呢?
如前个问题所描述:git及分布式版本控制系统的显著特点是:版本库位置工作区根目录。以git
为例,是根目录下的.git
目录。
而传统的集中式版本控制系统的版本库和工作区是分开,甚至在不同主机上。因此,必须有额外的对应关系。
CVS每个工作区的根目录下及子目录下都有一个CVS目录,包括了配置文件。不安全,搜索结果混乱。
有些软件工作区看起来非常“干净”,但其实是通过服务器建立文件跟踪,在DB存储,哪个client哪个目录检出什么版本库。如果客户端将工作区移动或改名,则文件状态会丢失。
GIT
只在工作区根目录下设置.git
版本库,保证了目录的干净性,大大提高了安全性,但也意味着只有.git
版本库的目录才存储有版本库信信息。
- 但同步带来的问题是,子目录没有版本库信息,怎么记录工作状态呢?
其实,子目录下的执行命令其实会依次向上递归查找.git
目录,找到工作区对应的版本库。 并且提供命令追踪向上递归的过程。
strace -e 'trace=file' git status
- 结果如下:
execve("/usr/bin/git", ["git", "status"], [/* 44 vars */]) = 0
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/usr/lib/oracle/12.1/client64/lib/tls/x86_64/libz.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib/oracle/12.1/client64/lib/tls/x86_64", 0x7fff445d6c40) = -1 ENOENT (No such file or directory)
open("/usr/lib/oracle/12.1/client64/lib/tls/libz.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
...
题外话:
git
的检索甚至是从根目录开始的,这个是不是有点过分了。。
- 检索
git
根目录
git rev-parse --git-dir # 显示.git目录所在位置
git rev-parse --show-toplevel # 显示工作区根目录
git rev-parse --show-prefix # 相对工作区根目录的当前目录
综上:向上逐层递归
4、git config --global --system 究竟有什么区别?
- 对应关系如表所示
配置文件 | 命令 |
---|---|
/etc/gitconfig | # git config —system user.name … |
~/.gitconfig | # git config —global user.name … |
.git/config | # git config user.name … |
5、git commit生成的HASH
为什么不用顺序数字代替?
- 首先:
git
是分布式,每次是先提交本地,最后有需求才会推送SERVER
。即不仅仅要保证本地版本库ID
唯一,也要保证“全球”ID
唯一。 - 其次:
HASH
是通过SHASUM
加密算出来,即是版本唯一性的标识,更是文件是否的变化的标识。还记得问题1中git比传统工具快的原因吗?
- 最后: 版本是非线性增长,
GIT
提倡充分使用好分支特性
6、git 工作区如何归档压缩?
tar,zip? NO!
.git
目录不想打包,且.gitgnore
中记录的忽略文件也不想打包!写个shell
脚本读取.gitgnore
后,find
过滤?NO。。。。
其实git
提供了内置工具
- 基于最新的提交建立归档文件 latest.zip
git archive -o latest.zip HRAD
- 只将目录src和doc归档到partial.tar中
git archive -o partial.tar HEAD src doc
- 建议里程碑v1.0建立归档,并为归档的文件添加目录前缀1.0
git archive --format=tar --prefix=1.0/ v1.0| gzip > foo-1.0.tar.gz
7、如何使用GIT
找出BUG
缔造者?
- git blame值得拥有
git blame prod/alarm.php
git blame -L 6, 5 prod/alarm.php # 只想查看某几行
- 输出如下
e5a152be (gw 2018-04-26 09:48:39 0800 13) 'wx:?49d79ce274ca65ae04965864e1',
8041ad3e (stanley 2016-06-13 14:55:05 0800 14) ],
8041ad3e (stanley 2016-06-13 14:55:05 0800 15)
8041ad3e (stanley 2016-06-13 14:55:05 0800 16) 'jerror'=>[
可以清晰看到什么人,什么时间,在哪个版本、改了哪行代码。当然,我假设你已经定位到是哪个文件引发的
BUG
8、TAGS(里程碑)有什么用?
代码语言:javascript复制git tag v_2.0 -m 'my first tag'
tags
里程碑的构建先简单,但究竟有什么用呢?
- 通常情况下用不到,但是这非常好的使用习惯,推荐使用
- 如
git
长时间使用,库越来越大,希望清理很久以前的提交信息以减少磁盘占用或者希望将版本中的某部分提交去除时,tags
会提供非常大的帮助
9、非技术问
版本协同工具的鼻祖是CVS(Concurrent Version System)
,作者阿姆斯特丹Dick Grune
教授因工作协同问题被逼实现的作品。一经问世便红遍全球,唯 Linux
教父 linus
极度排斥。宁愿diff,patch
手工维护也不愿使用,遭受同样遭遇的还有众所周知的 SVN
。随着CVS, SVN
管理的项目越来越多,原子级提交对二进制文件的支持有限、版本追踪合并混乱、隐藏目录安全隐患、分支错乱等问题也逐一暴露出来。
随后的戏剧性的故事开始了,在 bitkeeper
的授权被回收后,linus
被逼花了**4
天写出了git
** 。对的,只有4
天。2个月就已经开始维护Linux
核心代码。而1996
年硕士毕业的 linus
40岁。30
岁的linus
就已经看出教授的产品是"垃圾".
那么问题来了:究竟是人成就了事,还是事成就了人呢?您怎么看
GIT 简介:
Linus
坚定的CVS
反对者,同样也反对SVN
,这也是其1991-2002
十余年间手动维护代码的原因。git
是其第二个伟大作品。在git
诞生之前,linux
社区使用的bitmover
公司的商业产品bitkeeper
进行版本管理。2005
年SAMBA
作者试图对bitKeeper
进行反工程,希望能与bitkeeper
交互的开源工具。bitmover
收回到linux
社区免费使用bitkeeper
的授权。 不得已, 2005.04.03 开始开发git
4.6号git
发布 4.29,性能达linus
预期 6.16 维护linux
核心源代码 07.26linus
功成身退,git
交由Junio C Hamano
维护 最开始,每个git
功能都是一条命令,如git-commit git-clone
等,使git
命令集过于庞大,随后封装成一个git
命令,贴近普通用户的使用习惯。git
在linux
平台下开发,但现在已经跨平台,也是迄今最为流行的版本管理工具。