Git学习
一.(cvs/svn) vs git.
1.集中式 vs 分布式
集中式版本控制系统如下:
缺点:必须联网才能工作,受网络和带宽影响较大;单点故障
分布式版本控制系统如下:
优点:更大程度上避免网络和带宽影响,安全性更高
二.Git基本概念
1.工作区-暂存区-本地版本库
- 工作区:就是你的项目文件夹,即.git文件夹所在的目录。
- 暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
- 版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。
下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系:
2.commit-tree-blob
Blob对象
添加文件以使用Git进行跟踪时,Git使用zlib压缩算法对其进行压缩。使用SHA-1哈希函数对结果进行哈希处理。这将产生一个唯一的40位哈希值,该值对应于该文件中的内容。Git将其存储在位于隐藏的.git/objects文件夹中的对象数据库中。文件的名称为生成的哈希值,内容为压缩的内容。这些对象文件称为Blob,每次将新文件添加到存储库时会创建Blob对象。
树对象对应于文件目录,它将blob对象连接到它们的真实文件名,文件许可权和到其他树的链接,并以此方式表示特定文件和目录集的状态。一旦所有相关更改都准备好提交,索引树就可以提交到存储库。
commit对象保存特定修订的标题树以及提交作者,电子邮件地址,日期和描述性提交消息。每个commit对象还保存对其父提交的引用,因此随着时间的推移,将建立项目开发的历史记录。
3. .git下部分目录
三.基础命令
1.git diff 几种不同的使用方式
2.git reset
refs/heads/master游标的改变表示版本的重置/回退。 (git relog或者./git/logs/refs/heads/master)
第一种用法(包含了路径<paths>的用法)不会重置引用,更不会改变工作区,而是用指定提交状态(<commit>)下的文件(<paths>)替换掉暂存区中的文件。例如命令git reset HEAD <paths>相当于取消之前执行的git add <paths>命令时改变的暂存区。
第二种用法(不使用路径<paths>的用法)则会重置引用。根据不同的选项,可以对暂存区或者工作区进行重置。参照下面的版本库模型图,来看一看不同的参数对第二种重置语法的影响。
-
在之前曾经介绍过一个修补提交命令git commit –amend,用于对最新的提交进行重新提交以修补错误的提交说明或者错误的提交文件。相当于:
$ git reset --soft HEAD^ $ git commit -e -F .git/COMMIT_EDITMSG
3.git checkout
用法一: git checkout [-q] [<commit>] [--] <paths>... 用法二: git checkout [<branch>] 用法三: git checkout [-m] [[-b|--orphan] <new_branch>] [<start_point>]
上面列出的第一种用法和第二种用法的区别在于,第一种用法在命令中包含路径<paths>。为了避免路径和引用(或者提交ID)同名而冲突,可以在<paths>前用两个连续的短线(减号)作为分隔。
第一种用法的<commit>是可选项,如果省略则相当于从暂存区(index)进行检出。这和上一章的重置命令大不相同:重置的默认值是 HEAD,而检出的默认值是暂存区。因此重置一般用于重置暂存区(除非使用--hard参数,否则不重置工作区),而检出命令主要是覆盖工作区(如果<commit>不省略,也会替换暂存区中相应的文件)。
第一种用法(包含了路径<paths>的用法)不会改变HEAD头指针,主要是用于指定版本的文件覆盖工作区中对应的文件。如果省略<commit>,会拿暂存区的文件覆盖工作区的文件,否则用指定提交中的文件覆盖暂存区和工作区中对应的文件。
第二种用法(不使用路径<paths>的用法)则会改变HEAD头指针。之所以后面的参数写作<branch>,是因为只有HEAD切换到一个分支才可以对提交进行跟踪,否则仍然会进入“分离头指针”的状态。在“分离头指针”状态下的提交不能被引用关联到而可能会丢失。所以用法二最主要的作用就是切换到分支。如果省略<branch>则相当于对工作区进行状态检查。
第三种用法主要是创建和切换到新的分支(<new_branch>),新的分支从<start_point>指定的提交开始创建。新分支和我们熟悉的master分支没有什么实质的不同,都是在refs/heads命名空间下的引用。
下面通过一些示例,具体的看一下检出命令的不同用法。
-
命令:git checkout branch
检出branch分支。要完成如图的三个步骤,更新HEAD以指向branch分支,以branch指向的树更新暂存区和工作区。
-
命令:git checkout
汇总显示工作区、暂存区与HEAD的差异。
-
命令:git checkout HEAD
同上。
-
命令:git checkout – filename
用暂存区中filename文件来覆盖工作区中的filename文件。相当于取消自上次执行git add filename以来(如果执行过)本地的修改。
这个命令很危险,因为对于本地的修改会悄无声息的覆盖,毫不留情。
-
命令:git checkout branch – filename
维持HEAD的指向不变。将branch所指向的提交中的filename替换暂存区和工作区中相应的文件。注意会将暂存区和工作区中的filename文件直接覆盖。
-
命令:git checkout – . 或写做 git checkout .
注意:git checkout命令后的参数为一个点(“.”)。这条命令最危险!会取消所有本地的修改(相对于暂存区)。相当于将暂存区的所有文件直接覆盖本地文件,不给用户任何确认的机会!