等雨成冰的个人主页

http://www.qtcn.org/bbs/u/130507  [收藏] [复制]

等雨成冰

不求与人相比,但求超越自己。

  • 8

    关注

  • 6

    粉丝

  • 43

    访客

  • 等级:新手上路
  • 总积分:8
  • 保密,2011-01-01

最后登录:2016-09-09

更多资料

日志

Git 工作区、暂存区、本地仓、远程仓 关系梳理

2016-07-15 16:57
1,工作区,暂存区,本地仓,远程仓之间的关系

Worksapce:工作区,即工作目录,存储着你现在签出(checkout)来用来编辑的文件。当你在项目的不同分支间切换时, 工作目录里的文件经常会被替换,删除,修改。工作目录只用来临时保存签出(checkout) 文件的地方,你可以编辑工作目录的文件直到下次提交(commit)为止。
Index:一个在你的工作目录和项目仓库间的暂存区(staging area)。有了它,你可以把许多内容的修改一起提交(commit)。通过git add将工作目录的内容提交到这里,再通过git commit提交到本地项目仓,它是工作目录和项目仓之间的桥梁。
Repository:本地库,git commit 后,从暂存区将修改的代码会提交到这里来。
Remote:远程库;
注: 'Git目录' 一般就是指项目根目录下的'.git'目录.

2,.git 目录真容
     .git 目录是为你的项目存储所有历史和元信息的目录 - 包括所有的对象(commits, trees, blobs, tags)。每一个项目的根目录下都有一个隐藏 .git 目录 (较老版本的 svn 每一个子目录都有个 .svn 的文件)。如果查看这个目录的内容,可以看所有的重要文件:
|-- HEAD # 指向当前分支的一个游标(指针),默认是指向最新的节点
|-- config # 仓库的配置信息,git config命令会改动它(当然,也可以手改)
|-- description # 仓库的描述信息
|-- index # 索引
|-- hooks/ # 钩子脚本目录
|-- logs/ # 历史信息
|-- objects/ # git 对象库,包含提交(commit)、文件内容(blob)、目录树(tree)等
|-- refs/ # 保存引用的命名空间

这些配置文件会记录工作区的文件名称、修改时间和版本等信息,通过时间戳的对比可以快速扫描工作区的改动。在.svn文件夹下还包括原始文件的拷贝,这些拷贝文件可以脱离版本库独立操作。此外,SVN的版本库与工作区是分离的。
虽然Git将仓库放在本地使得操作非常简便,但是从安全的角度分析,是不是很不安全呢?因为如果因为某个错误的操作将工作区所在的文件夹整个删除了,那么这样是危险的。事物总有其两面性,但是考虑到之前SVN等版本控制系统将版本库与工作区分离的设计,因为两者是分离的,那么就必须引入第三方的配置文件等机制实现对工作区文件的跟踪,这样的机制势必就会出现类似SVN的问题。
然而,Git针对存储安全的问题,Git引入了克隆操作降低了因为版本库和工作区放在一起导致被破坏的危险。当在工作区发生了修改,只需要手动使用git push或在克隆的工作区使用git pull就可以轻松实现两个工作区的同步与更新。
注:.svn目录并不是本地仓库,而是为了建立与远端版本仓库的关联而引入的配置文件,所以SVN的版本库与工作区是分离的。

3,理解暂存区和版本库
    从上文可以看出,暂存区是你的工作目录和项目仓库间沟通的桥梁,有了它, 你可以把许多内容的修改一起提交(commit)。如果你创建了一个提交(commit),那么提交的是当前索引(index)里的内容,而不是工作目录中的内容。
那为什么不直接提交到项目仓弄一个临时缓存区,感觉多余了?答案是肯定不会多余,因为工作目录里面的内容更改会相当频繁,如果改一次就上一次库,这么频繁的上库效率太低,还容易出错,而暂存区的出现可以极大地避免出现该问题;只要修改了没有提交到(git add)缓存区,你的(git commit)就不会影响项目库,给了你更多思考和修改问题的时间。
另外,当需要扫描工作区的改动的时候,根据缓存区中记录的时间戳、长度的信息,就可以判断出工作区文件是否改变。如果时间戳变化了,再去读取文件内容,和原始文件比对来判断是否被更改,并刷新时间戳。这样子比较时间戳、文件长度信息的方法,和直接比较文件内容相比要快,这也是 git 高效的原因之一。
从如下原理图可以得出以下信息:

1)    左侧为工作区,右侧为版本库;
2)    objects 为 git 的对象库,实际位于 .git/objects 目录下;
3)    index 为暂存区,是一个目录树,包含索引文件,记录文件名、文件状态(时间戳、文件长度等信息,而文件内容,记录在objects 中);
4)    HEAD,是一个指向最新commit的引用,可以通过版本回退的方式改变HEAD的指向;
5)    执行 git add 会更新暂存区的目录树,同时将工作区的文件内容生成一个对象放入 objects 对象库中,在暂存区记录该对象实体和文件的关联关系;
6)    执行 git commit 会更新版本库的目录树,commit 成功后版本库指向的目录树就是原来暂存区的目录树。
分类:Git|回复:0|浏览:1748|全站可见|转载
 

Powered by phpwind v8.7 Certificate Copyright Time now is:04-25 01:02
©2005-2016 QTCN开发网 版权所有 Gzip disabled