为什么使用Git

孔子曾经曰过的,名正则言顺 言顺则事成。

我们在学习一项新技术之前,弄清楚为什么要学它至关重要,至于为什么要学习Git,我用一段if-else语句告诉你原因:

if(你相信我){
      我推荐你学习;
} else if(诚然,我又不是什么大牛,你可以不相信我,但是你应该相信大多数人的选择){
      世界上越来越多的人、越来越多的项目在使用Git,大势所趋,势不可挡;
}else if(用的人多算什么,你可能认为真理掌握在少数人手中){
      你可以不相信大众,但是你应该相信LinusTorvalds,就是靠一己之力写出了Linux内核原型的大神//我说的是内核的原型,不是内核的全部,不要挑我毛病!
      Git就是他创造的第二个作品
}else{
      什么?!你没听过LinusTorvalds,更不知道Linux是个什么东西……
      throw new Exception(“好吧,你赢了,你可以不用学Git,我运行不下去了”);
}

Git是什么

首先,Git是一个版本管理工具。

我们自己平时写个“HelloWorld”程序,或者写一个只有几百行代码的小项目,不需要专门的代码管理工具,依靠自己的记忆就能把代码捋顺。

但是,一旦涉及到代码量巨大的项目,往往需要经过很多人协同工作数周乃至数月才能完成。开发过程中,会面临着代码的修改、增删、恢复等工作,开发人员不可能清楚的记得每次变化,这时候就需要借助版本管理工具来跟踪代码的变化历程。

版本管理工具赋予每个文件一个版本号,每次修改之后,哪怕只改动了一个字母,版本管理工具都会精确地记录下来,并改变该文件的版本号。这样,每个版本号就对应着文件的一次变化,依此可以进行文件的对比、恢复等操作。

最早广泛应用的版本管理工具是CVS(Concurrent Versions System),后来逐渐被SVN(Subversion)替代,两者的工作原理类似,都是以一台服务器为核心进行集中式代码管理:

集中式 vs 分布式

SVN属于典型的集中式版本控制系统,集中式版本控制系统都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。

这种做法带来了许多好处,特别是相较于老式的本地VCS 来说。现在,每个人都可以一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限。

事分两面,有好有坏。这么做最显而易见的缺点是中央服务器的单点故障。若是宕机一小时,那么在这一小时内,谁都无法提交更新、还原、对比等,也就无法协同工作。如果中央服务器的磁盘发生故障,并且没做过备份或者备份得不够及时的话,还会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,被客户端提取出来的某些快照数据除外,但这样的话依然是个问题,不能保证所有的数据都已经有人提取出来。

SVN只关心文件内容的具体差异。每次记录有哪些文件作了更新,以及都更新了什么内容。如下图所示:

与SVN不同,Git记录版本历史只关心文件数据的整体是否发生变化。Git 并不保存文件内容前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一连接。Git 的工作方式如下图所示:

在分布式版本控制系统中,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。这类系统都可以指定和若干不同的远端代码仓库进行交互。借此,就可以在同一个项目中,分别和不同工作小组的人相互协作。可以根据需要设定不同的协作流程。

另外,因为Git在本地磁盘上保存着所有有关当前项目的历史更新,并且Git中的绝大多数操作都只需要访问本地文件和资源,不用连网,所以处理起来速度飞快。用SVN的话,没有网络或者断开VPN就无法做任何事情。但用Git的话,就算你在飞机或者火车上,都可以非常愉快地频繁提交更新,等到了有网络的时候再上传到远程的镜像仓库。换作其他版本控制系统,这么做几乎不可能,抑或是非常麻烦。

简略的说,Git具有以下特点:

1、Git中每个克隆(clone)的版本库都是平等的。可以从任何一个版本库的克隆来创建属于自己的版本库,同时你的版本库也可以作为源提供给他人,只要你愿意。

2、Git的每一次提取操作,实际上都是一次对代码仓库的完整备份

3、提交完全在本地完成,无须别人给你授权,你的版本库你作主,并且提交总是会成功。

4、Git的提交不会被打断,直到你的工作完全满意了,PUSH给他人或者他人PULL你的版本库,合并会发生在PULL和PUSH过程中,不能自动解决的冲突会提示你手工完成。

全局版本号 vs 全球版本号

SVN的全局版本号和CVS的每个文件都独立维护一套版本号,在看似简单的全局版本号的背后,是SVN提供对于事物处理的支持,每一个事物处理(即一次提交)都具有整个版本库全局唯一的版本号。

Git的版本号则更进一步,版本号是全球唯一的。在保存到 Git 之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。换句话说,不可能在你修改了文件或目录之后,Git 一无所知。这项特性作为 Git 的设计哲学,建在整体架构的最底层。所以如果文件在传输时变得不完整,或者磁盘损坏导致文件数据缺失,Git 都能立即察觉。

Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及a-f)组成,看起来就像是这个样子:

24b9da6552252987aa493b52f8696cd6d3b00373

1、所有保存在Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。

2、使用哈希值作版本号的好处就是对于一个分布式的版本控制系统,每个人每次提交后形成的版本号都不会出现重复。另一好处是保证数据的完整性,因为哈希值是根据内容或目录结构计算出来的,所以我们还可以据此来判断数据内容是否被篡改。

3、SVN 的版本号是连续的,可以预判下一个版本号,而 Git 的版本号则不是。因为 subversion 是集中式版本控制,很容易实现版本号的连续性。Git 是分布式的版本控制系统,而且Git 采用 40 位长的哈希值作为版本号,每个人的提交都是各自独立完成的,没有先后之分(即使提交有先后之分,也由于PUSH/PULL的方向和时机而不同)。Git 的版本号虽然不连续,但是是有线索的,即每一个版本都有对应的父版本(一个或者两个),进而可以形成一个复杂的提交链。

4、Git 的版本号简化:Git 可以使用从左面开始任意长度的字串作为简化版本号,只要该简化的版本号不产生歧义。一般采用7位的短版本号(只要不会出现重复的,你也可以使用更短的版本号)。

许多人可能会担心一个问题:在随机的偶然情况下,在他们的仓库里会出现两个具有相同 SHA-1 值的对象。那会怎么样呢?

如果你真的向仓库里提交了一个跟之前的某个对象具有相同 SHA-1 值的对象,Git 将会发现之前的那个对象已经存在在 Git 数据库中,并认为它已经被写入了。如果什么时候你想再次检出那个对象时,你会总是得到先前的那个对象的数据。

不过,你应该了解到,这种情况发生的概率是多么微小。SHA-1 摘要长度是 20 字节,也就是 160 位。为了保证有 50% 的概率出现一次冲突,需要 2^80 个随机哈希的对象(计算冲突机率的公式是p = (n(n-1)/2) *(1/2^160))。2^80 是 1.2 x 10^24,也就是一亿亿亿,那是地球上沙粒总数的 1200 倍。

现在举例说一下怎样才能产生一次SHA-1 冲突。如果地球上 65 亿的人类都在编程,每人每秒都在产生等价于整个 Linux 内核历史(一百万个 Git 对象)的代码,并将之提交到一个巨大的 Git 仓库里面,那将花费 5 年的时间才会产生足够的对象,使其拥有 50% 的概率产生一次 SHA-1 对象冲突……

所以,你还担心会冲突吗?

Git之(一)Git是什么的更多相关文章

  1. git init和git init -bare区别

    1 Git init  和 git init –bare 的区别 用"git init"初始化的版本库用户也可以在该目录下执行所有git方面的操作.但别的用户在将更新push上来的 ...

  2. 小丁带你走进git世界一-git简单配置

    小丁带你走进git世界一-git简单配置 1.github的简单配置 配置提交代码的信息,例如是谁提交的代码之类的. git config  –global user.name BattleHeaer ...

  3. Git(远程仓库:git@oschina)-V2.0

    1.注册git@osc(也就是“码云”) 这里会提示注册密码==push密码,反正一定要记住的东西.   2.安装git 这里要设置个人信息 git config --list //查看git信息 g ...

  4. git pull和git fetch的区别

    Git中从远程的分支获取最新的版本到本地有这样2个命令:1. git fetch:相当于是从远程获取最新版本到本地,不会自动merge Git fetch origin master git log ...

  5. [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit

    [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit 读前必备: 接上篇: 分布式版本控制系统Git——使用GitS ...

  6. Git:Git初体验——Git安装配置

    作为即将成为一个程序员的男人,一直在听别人说Git多好多好,之前也随便了解了一些,但是始终没有决心去学会.现在大四了,只有毕设和一门开学六七周只去过一次课的全员必修课外,也没有什么事情做,何不去做这些 ...

  7. git rebase与 git合并(error: failed to push some refs to)解决方法

    1.遇到的问题 本地有一个git仓库,在github上新建了一个空的仓库,但是更新了REWADME.md的信息,即在github上多了一个提交. 关联远程仓库,操作顺序如下: git remote a ...

  8. Git fetch和git pull的区别

    Git中从远程的分支获取最新的版本到本地有这样2个命令:1. git fetch:相当于是从远程获取最新版本到本地,不会自动merge git fetch origin mastergit log - ...

  9. 代码回滚:git reset、git checkout和git revert区别和联系

    git reset.git checkout和git revert是你的Git工具箱中最有用的一些命令.它们都用来撤销代码仓库中的某些更改,而前两个命令不仅可以作用于提交,还可以作用于特定文件. 因为 ...

  10. git branch(git 的branch 使用方法)

    查看分支:         $ git branch    该命令会类出当先项目中的所有分支信息,其中以*开头的表示当前所在的分支.参数-r列出远程仓库中的分支,而-a则远程与本地仓库的全部分支. 创 ...

随机推荐

  1. line-height与图片底部间隙的学习整理转述

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 看大牛张鑫旭的视屏可能会理解的更深一些,点击这里: line-height,两行文字的基线之间的距离: 基 ...

  2. [LeetCode] Range Module 范围模块

    A Range Module is a module that tracks ranges of numbers. Your task is to design and implement the f ...

  3. [LeetCode] Output Contest Matches 输出比赛匹配对

    During the NBA playoffs, we always arrange the rather strong team to play with the rather weak team, ...

  4. gradlew在Travis CI没可执行权限 permission denied

    问题的来源 我给一个gradlew项目添加Travis CI的时候遇到一个问题,gradlew没有可执行权限.具体错误如下: /home/travis/build.sh: line 45: ./gra ...

  5. “百度杯”CTF比赛 九月场_SQLi

    题目在i春秋ctf大本营 看网页源码提示: 这边是个大坑,访问login.php发现根本不存在注入点,看了wp才知道注入点在l0gin.php 尝试order by语句,发现3的时候页面发生变化,说明 ...

  6. [BZOJ 5093]图的价值

    Description 题库链接 一个带标号的图的价值定义为每个点度数的 \(k\) 次方的和.给定 \(n\) 和 \(k\) ,请计算所有 \(n\) 个点的带标号的简单无向图的价值之和.对 \( ...

  7. [AHOI 2016初中组]迷宫

    Description 小雪和小可可被困在了一个无限大的迷宫中. 已经知道这个迷宫有 N 堵环状的墙,如果把整个迷宫看作是一个二维平面,那么每一堵墙都是平面上一个圆.任意两个圆不相交,不重合,也不会相 ...

  8. [HAOI2008]糖果传递

    题目描述 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. 输入输出格式 输入格式: 小朋友个数n 下面n行 ai 输出格式: 求使所有人获得均等糖果 ...

  9. 【BZOJ4003】【JLOI2015】城池攻占

    Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其 ...

  10. bzoj 5286: [Hnoi2018]转盘

    Description Solution 首先注意到一个点不会走两次,只会有停下来等待的情况,把序列倍长 那么如果枚举一个起点\(i\),答案就是 \(min(max(T[j]+n-(j-i)-1)) ...