-
Notifications
You must be signed in to change notification settings - Fork 23
Git 笔记系列(一)—— Git简介
| 时间 | 更新备注 |
|---|---|
| 2018-02-27 | 新建文章 |
| 2018-06-07 | 整理补充 |
Git很多开发团队在使用,但是Git很多强大的特性不一定都很了解,基于以前的使用以及参考Git的博客,将用一系列文章介绍Git, 从原理到常用命令,希望能更好的使用Git, 提高团队开发效率。
- Git 笔记系列(一)—— Git简介
- Git 笔记系列(二)—— Git工作流程
- Git 笔记系列(三)—— Git常用命令-一览
- Git 笔记系列(四)—— Git常用命令-Checkout
- Git 笔记系列(五)—— Git常用命令-Branch
- Git 笔记系列(六)—— Git常用命令-Reset
- Git 笔记系列(七)—— Git常用命令-Rebase
- Git 笔记系列(八)—— Git常用命令-Stash等
- Git 笔记系列(九)—— Git进阶
什么是“版本控制”?我为什么要关心它呢?
版本控制系统,或VCS,是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。跟踪变化的历史, 因为人们和团队共同合作的项目。随着项目的发展,团队可以运行测试,修复错误,并提供新的代码,并相信任何版本都可以在任何时候恢复。开发人员可以查看项目历史以找出:
- 做了哪些改变?
- 谁做了这些改变?
- 这些变化是什么时候发生的?
- 为什么需要改变?
版本控制的软件和设计模式有很多,但是,你来阅读这Git这一系列文章我相信至少是对Git产生了兴趣,那就不妨点击阅读全文,进来坐坐。
版本控制(Revision control)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。
- 实现跨区域多人协同开发
- 追踪和记载一个或者多个文件的历史记录
- 组织和保护你的源代码和文档
- 统计工作量
- 并行开发、提高开发效率
- 跟踪记录整个软件的开发过程
- 减轻开发人员的负担,节省时间,同时降低人为错误
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是由Linux的缔造者Linus Torvalds,在2005年基于使用BitKeeper时的经验教训,开发出自己的版本系统。
Git的目标:
- 速度
- 简单的设计
- 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
- 完全分布式
- 有能力高效管理类似
Linux内核一样的超大规模项目(速度和数据量)
Git 作为现在最流行的开源的版本控制系统,了SVN的一些特性(tag, branch),采用了巧妙的设计(本地库),让并行开发更高效。 可以说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和其它版本控制系统(包括Subversion和近似工具)的主要差别在于Git对待数据的方法。 -
SVN——以文件变更列表的方式存储信息。
将保存的信息看作是一组文件+文件随时间累积的差异。
-
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 有三种状态,你的文件可能处于其中之一:
- 已修改(
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 add files 把把文件修改添加到暂存区。
- git commit 给暂存区域生成快照并提交。
- git reset -- files 用来撤销最后一次git add files,你也可以用git reset 撤销所有暂存区域文件。
- git checkout -- files 把文件从暂存区域复制到工作目录,用来丢弃本地修改。暂存区的所有内容提交到当前分支
所有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
如果本地有多个Git账号,添加ssh秘钥后,就会在~/.ssh/文件夹中生成多个对应的ssh秘钥。
然而可能在你提交的时候,你当前ssh对应的git账号并非你所需要提交的目标账号,可以通过以下步骤制定目标Git账号:
- 用:
ssh -T git@github.com命令,检查当前配置的SSH对应的git账号; - 用
$ ssh-add -K ~/.ssh/id_rsa(id_rsa对应目标账户的私钥)命令,制定目标Git账号。
问题:More than one value for the key user.name Git
# If you just want to reset all of them:
git config --local --replace-all user.email "new@mail.com"
git config --global --replace-all user.email "new@mail.com"
github - More than one value for the key user.name Git - Stack Overflow
读完这篇相信你对 Git 有了更初步的理解,那么具体在开发中,如何使用用Git来完成版本控制,可以在下篇Git 笔记系列(二)—— Git工作流程得到回答,第二篇将会对 Git 的工作流和常用命令进行简单介绍。
- ProGit中文版 ProGit中文版
- learngitbranching 交互式学习Git的网站
- 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










