时间 | 更新备注 |
---|---|
2018-02-27 | 新建文章 |
2018-06-07 | 整理补充 |
2019-01-18 | 更新链接 |
目录
- Git 笔记系列(一)—— Git简介
- Git 笔记系列(二)—— Git工作流程
- Git 笔记系列(三)—— Git常用命令-一览
- Git 笔记系列(四)—— Git常用命令-Checkout
- Git 笔记系列(五)—— Git常用命令-Branch
- Git 笔记系列(六)—— Git常用命令-Reset
- Git 笔记系列(七)—— Git常用命令-Rebase
- Git 笔记系列(八)—— Git常用命令-Stash等
- Git 笔记系列(九)—— Git进阶
引言
Git
很多开发团队在使用,但是Git
很多强大的特性不一定都很了解,基于以前的使用以及参考Git
的博客,将用一系列文章介绍Git
, 从原理到常用命令,希望能更好的使用Git
, 提高团队开发效率。
关于版本控制
什么是“版本控制”?我为什么要关心它呢?
版本控制系统,或VCS,是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。跟踪变化的历史, 因为人们和团队共同合作的项目。随着项目的发展,团队可以运行测试,修复错误,并提供新的代码,并相信任何版本都可以在任何时候恢复。开发人员可以查看项目历史以找出:
- 做了哪些改变?
- 谁做了这些改变?
- 这些变化是什么时候发生的?
- 为什么需要改变?
版本控制的软件和设计模式有很多,但是,你来阅读这Git
这一系列文章我相信至少是对Git
产生了兴趣,那就不妨继续往下看。
版本控制的好处
- 实现跨区域多人协同开发
- 追踪和记载一个或者多个文件的历史记录
- 组织和保护你的源代码和文档
- 统计工作量
- 并行开发、提高开发效率
- 跟踪记录整个软件的开发过程
- 减轻开发人员的负担,节省时间,同时降低人为错误
集中化管理系统
Centralized Version Control Systems
,简称 CVCS
, 这类系统,诸如 CVS、Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。 多年以来,这已成为版本控制系统的标准做法。它的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
评价:这种方式解决了版本控制问题,但是过于依赖中央服务器——Central VCS Server
,如果中央服务器出现问题,将不可以再提交代码,如果数据未备份,无法恢复,则丢失所有的数据,文件和log提交记录,而且本地只是保存一个版本的快照,从而只剩下各个用户的本地快照记录。
所有的版本数据都存在服务器上,用户的本地只有自己以前所同步的版本,如果不连网的话,用户就看不到历史版本,也无法切换版本验证问题,或在不同分支工作。而且,所有数据都保存在单一的服务器上,有很大的风险这个服务器会损坏,这样就会丢失所有的数据,当然可以定期备份。
分布式版本控制系统
Distributed Version Control System
,简称DVCS
, 在这类系统中,代表的有 Git
、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
分布式版本控制系统允许对项目的每个文件、分支和迭代进行完全访问,并允许每个用户访问所有更改的完整和自包含的历史。不像曾经流行的集中式版本控制系统,像Git那样的DVCSs不需要与中央存储库的持续连接。开发人员可以在任何地方工作,并与任何时区异步协作。
简介
So, what hell is Git?
Git的历史
Git
是由Linux
的缔造者Linus Torvalds
,在2005年基于使用BitKeeper
时的经验教训,开发出自己的版本系统。
Git
的目标:
- 速度
- 简单的设计
- 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
- 完全分布式
- 有能力高效管理类似
Linux
内核一样的超大规模项目(速度和数据量)
Git
作为现在最流行的开源的版本控制系统,了SVN
的一些特性(tag, branch),采用了巧妙的设计(本地库),让并行开发更高效。 可以说Git
是目前用户最多,最火的版本控制系统。
Git的优点
- 客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。
- 可以指定和若干不同的远端代码仓库进行交互,就可以在同一个项目中,分别和不同工作小组的人相互协作(
Git
强大的分支功能)。 你可以根据需要设定不同的协作流程,而在集中式系统中是无法实现的。 - 近乎所有操作都是本地执行, 在
Git
中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。 因为你在本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间完成。 -
Git
保证完整性,Git
中所有数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在Git
不知情时更改任何文件内容或目录内容。 若你在传送过程中丢失信息或损坏文件,Git
就能发现。
Git常用术语
1)、仓库(Repository)
受版本控制的所有文件修订历史的共享数据库
2)、工作空间(Workspace)
本地硬盘或Unix 用户帐户上编辑的文件副本
3)、工作树/区(Working tree)
工作区中包含了仓库的工作文件。您可以修改的内容和提交更改作为新的提交到仓库。
4)、暂存区(Staging area)
暂存区是工作区用来提交更改(commit)前可以暂存工作区的变化。
5)、索引(Index)
索引是暂存区的另一种术语。
6)、签入(Checkin)
将新版本复制回仓库
7)、签出(Checkout)
从仓库中将文件的最新修订版本复制到工作空间
8)、提交(Commit)
对各自文件的工作副本做了更改,并将这些更改提交到仓库
9)、冲突(Conflict)
多人对同一文件的工作副本进行更改,并将这些更改提交到仓库
10)、合并(Merge)
将某分支上的更改联接到此主干或同为主干的另一个分支
11)、分支(Branch)
从主线上分离开的副本,默认分支叫master
12)、锁(Lock)
获得修改文件的专有权限。
13)、头(HEAD)
头是一个象征性的参考,最常用以指向当前选择的分支。
14)、修订(Revision)
表示代码的一个版本状态。Git通过用SHA1 hash算法表示的ID来标识不同的版本。
15)、标记(Tags)
标记指的是某个分支某个特定时间点的状态。通过标记,可以很方便的切换到标记时的状态。
Git的工作原理
处理数据的方式
Git
和其它版本控制系统(包括Subversion
和近似工具)的主要差别在于Git
对待数据的方法。SVN
——以文件变更列表的方式存储信息。
将保存的信息看作是一组文件+文件随时间累积的差异。
-
Git
——直接记录快照,而非差异比较
每次你提交更新,或在 Git
中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git
不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git
对待数据更像是一个快照流。
这是 Git
与几乎所有其它版本控制系统的重要区别, Git
分支管理时,将探究这种方式对待数据所能获得的益处。
Git的计算校验和的机制
Git
中所有数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在 Git
不知情时更改任何文件内容或目录内容。 若你在传送过程中丢失信息或损坏文件,Git
就能发现。
Git
用以计算校验和的机制叫做SHA-1
散列(hash,哈希)。 这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串,基于 Git
中文件的内容或目录结构计算出来。 SHA-1
哈希看起来是这样:
24b9da6552252987aa493b52f8696cd6d3b00373
为什么commit id
需要用这么一大串数字表示呢?因为Git
是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
Git
中使用这种哈希值的情况很多,你将经常看到这种哈希值。 实际上,Git
数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。
Git 一般只添加数据
你执行的 Git
操作,几乎只往 Git
数据库中增加数据。 很难让 Git
执行任何不可逆操作,或者让它以任何方式清除数据。
Git的工作流程
Git的三个工作区域
Git
有三种状态,你的文件可能处于其中之一:
- 已修改(
modified
): 修改了文件,但还没保存到数据库中。 - 已暂存(
staged
) :对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。 - 已提交(
committed
):数据已经安全的保存在本地数据库中
由此引入 Git
项目的的概念:Git
仓库、工作目录以及暂存区域。一个Git
项目可以被看做一下三个部分:
-
Working Directory: 工作目录是对项目的某个版本独立提取出来的内容。 这些从
Git
仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。你将在里面完成文件的创建、编辑、删除、整理的所有工作。 -
Staging Area: 暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在
Git
仓库目录中。 有时候也被称作`‘索引’',不过一般说法还是叫暂存区域,列出对工作目录所做的更改。 -
Repository:
Git
仓库是Git
用来保存项目的元数据和对象数据库的地方。Git
永久的保存着这个项目版本间的不同变化。这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。
工作区和暂存区概念:
工作区(Working Directory)就是你本地仓库文件夹里能看到的目录。
版本库(Repository) 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD
。
Git工作流程
- 在工作目录中修改文件。
- 暂存文件,将文件的快照放入暂存区域。
- 提交更新,找到暂存区域的文件,将快照永久性存储到
Git
仓库目录。
Git工作流程命令
- git add files 把把文件修改添加到暂存区。
- git commit 给暂存区域生成快照并提交。
- git reset -- files 用来撤销最后一次git add files,你也可以用git reset 撤销所有暂存区域文件。
- git checkout -- files 把文件从暂存区域复制到工作目录,用来丢弃本地修改。暂存区的所有内容提交到当前分支
Git 配置
所有config命令参数
语法: git config [<options>]
文件位置
--global #use global config file 使用全局配置文件
--system #use system config file 使用系统配置文件
--local #use repository config file 使用存储库配置文件
-f, --file <file> #use given config file 使用给定的配置文件
--blob <blob-id> #read config from given blob object 从给定的对象中读取配置
动作
--get #get value: name [value-regex] 获得值:[值]名[正则表达式]
--get-all #get all values: key [value-regex] 获得所有值:[值]名[正则表达式]
--get-regexp #get values for regexp: name-regex [value-regex] 得到的值根据正则
--get-urlmatch #get value specific for the URL: section[.var] URL 为URL获取特定的值
--replace-all #replace all matching variables: name value [value_regex] 替换所有匹配的变量:名称值[ value_regex ]
--add #add a new variable: name value 添加一个新变量:name值
--unset #remove a variable: name [value-regex] 删除一个变量名[值]:正则表达式
--unset-all #remove all matches: name [value-regex] 删除所有匹配的正则表达式:名称[值]
--rename-section #rename section: old-name new-name 重命名部分:旧名称 新名称
--remove-section #remove a section: name 删除部分:名称
-l, --list #list all 列出所有
-e, --edit #open an editor 打开一个编辑器
--get-color #find the color configured: slot [default] 找到配置的颜色:插槽[默认]
--get-colorbool #find the color setting: slot [stdout-is-tty] 发现颜色设置:槽[ stdout是TTY ]
类型
--bool #value is "true" or "false" 值是“真”或“假”。
--int #value is decimal number 值是十进制数。
--bool-or-int #value is --bool or --int 值--布尔或int
--path #value is a path (file or directory name) 值是路径(文件或目录名)
其它
-z, --null #terminate values with NUL byte 终止值与null字节
--name-only #show variable names only 只显示变量名
--includes #respect include directives on lookup 尊重包括查找指令
--show-origin #show origin of config (file, standard input, blob, command line) 显示配置(文件、标准输入、数据块、命令行)的来源
忽略文件
有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等
在主目录下建立".gitignore"文件,此文件有如下规则:
- 忽略文件中的空行或以井号(#)开始的行将会被忽略。
- 可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,...})代表可选的字符串等。
- 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。
- 如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。
- 如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。
如:
#为注释
*.txt #忽略所有 .txt结尾的文件
!lib.txt #但lib.txt除外
/temp #仅忽略项目根目录下的TODO文件,不包括其它目录temp
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
Where to Go Next
读完这篇相信你对 Git
有了更初步的理解,那么具体在开发中,如何使用用Git
来完成版本控制,可以在下篇Git 笔记系列(二)—— Git工作流程得到回答,第二篇将会对 Git
的工作流和常用命令进行简单介绍。
参考
- learngitbranching 交互式学习Git的网站
- ProGit中文版ProGit中文版
- Resources to learn Git Resources to learn Git
- Setting up a repository | Atlassian Git Tutorial
- Git-recipes 高质量的Git中文教程,Atlassian Git Tutorial的翻译
- Git - 关于版本控制
- Git-flow 备忘清单
- Beginning Git | Ray Wenderlich
- New Course: Mastering Git | Ray Wenderlich
- Git Handbook · GitHub Guides