上一篇讲解了IDEA中的git操作看这一篇就够了
这篇侧重原理讲解:
git是开发者必需掌握的技能之一,在日常的使用过程中,经常有一些小白由于对git的原理没有吃透,经常会出现一些坑队友的操作。
对于初识git的开发者,简单的认为git就是提交代码到仓库。
在看完这一篇博客后、重新认识git。掌握git的核心原理
如果我写的好,希望给个小星星,加个关注。
git的诞生缘由
比如:
- 程序的某一行代码被多人修改(在自己的电脑上修改)进行合并代码?----多人写代码合并代码难题
- 程序员A由于电脑宕机,写的代码丢失了。-------代码丢失问题
- 程序员A想对之前写的程序进行优化,然后直接修改代码,结果程序跑不起来了。如果重新修改回去也比较麻烦,而且也记不起来修改了那些,以及修改前的代码--------代码无法回滚
- 等....
就前面3个问题任意一个一个问题,如果在自己头上,都会抓耳挠腮,异常烦恼。
git原理剖析
在将一个项目进行版本控制后,git会在项目中创建一个.git的隐藏文件夹,下面和我一样显示隐藏文件夹
会看到一个.git文件夹,里面存放的就git相关的数据
完成上面操作后,我将带着大家一起去挖掘git,去思考创造git的作者是怎么思考问题的
下面请和我一起去思考下面这些问题
抛出第一个问题
当我们修改了代码后,git如何去检测到代码进行了修改?
如果让你来设计一个程序来检测一个文件代码有没有修改,你改如何去设计?
请发挥自己的想象,暂停阅读然后去思考一下这个问题。
大胆发挥想象,错了没有关系,注重思考问题的过程,一个好的解决方案往往是经过反复推敲诞生的。
比如:
文件状态(时间,文件大小等)、文件中的代码等
- 时间:可能我两个时间的代码是一样的,这样等于代码没有进行修改
- 文件大小:这个也不能解决问题,因为可能我文件的大小是一样的,但是里面的字符我实际上是修改过的。这样根本检测不到文件代码是否被修改过。
文件代码:这个好理解,如果我检测到代码发生变化自然就是变化了,哪如何检测代码发生改变了呢?
联想到一些加密算法,比如md5、比如SHA-1、比如SHA-256等Hash算法。
这些加密算法可以将一串字符串算出另一个字符串,如果修改前的字符串和修改后进行算法后得到的字符串两个进行比较,如果不同,自然代码是进行了修改了。
显然md5不合适,因为md5可能得到同一个字符串。
SHA-1:git实际真正采用的算法就是SHA-1,哪也就是说我可以通过hash算法中的SHA-1将文件进行一次运算,会得到一个hash值,当我修改了代码,我将修改后的文件进行sha-1运算会得到一个新的hash值,然后比较两个hash值是否是一样的
如果是一样的则说明文件中的代码没有进行修改
如果hash不一样,则说明文件的代码进行了修改
到此第一个问题解决了,就是通过hash算法对文件(文件中的所有字符)进行运算,得到一个唯一的一个hash,如果修改后的代码运算的hash值是一样则代码没有进行改变,不一样则说明源文件代码进行了修改。------说明一下就算是加了一个空格也算是修改了源代码文件,空格也是一个字符。
既然已经能通过sha-1算法来检测出代码是否被修改了
抛出第二个问题
假设有两个程序员,程序员A和程序员B同时修改代码提交代码,如何让两个程序员修改的代码都能得到管理?始终保证仓库中的代码是正确的?
案例:
程序员A和程序员B同时从仓库下拉代码,他们得到了通一份代码。
经过一段时间后,两人都代代码进行了修改,两人修改完代码后都需要将代码提交到仓库中。提交总有先后的问题。
假设程序员A先提交了,那么程序员B能否正确提交?
程序员提交肯定会遭到拒绝,因为程序员A先将代码提交上了远程仓库,那么远程仓库的代码已经被修改了,也就是说远程仓库中的hash值也变了,程序员B提交的时候,用旧的远程仓库hash值比较现在新的hash值。显而易见肯定不同,自然会遭受到拒绝提交。
那么程序员B改如何提交呢?
程序员B需要更新一下本地代码,将服务器的代码合并到本地,然后将合并后的代码推送到仓库中。合并过程就会将新的hash值更新过来。这样程序员B再次提交的时候就是用新的hash值和同样的新的hash值比较,匹配则允许你提交。
提交后远程仓库的hash值会变成新的hash值,对于程序员A来说如果他需要提交同样需要合并远程仓库的代码,更新本地的远程hash值,然后再提交上去。
hash值文件的记录示例:
在项目的隐藏.git文件夹中有logs文件夹,里面存放的就是每一次提交是产生的hash值
本地的heads有个master文件如下,用文本编辑器打开查看,如下:
每一次提交就会像这样比较一下hash值,如果相同才允许提交,CAS算法原理先比较修改前和之前的值比较是否一样,一样则允许你修改成新的值。
你会发现每一次提交对这样右边的上一行的hash和当前行的前面的一个hash值比较。
程序员A和程序员B同时下拉代码后得到通一个hash值A1
然后程序员A修改代码产生一个新的hash值A2
程序员A提交代码时:它会比较hash值A1 和远程仓库中的A1
发现相同提交成功,于是远程仓库的hash值变成了A2
由于程序员B不知道程序员A提交了代码,远程仓库的hash值变成了A2
程序员修改完代码后,得到了一个新的hash值A3,而此时他也是拿A1和A2比较
显然不同自然就会冲突,拒绝提交。
因此需要合并代码将远程代码合并到本地,也就是或程序B将本地的A1更新为了A2,然后拿A2和A2比较,将A3更新上去
git中的工作区、暂存区、仓库
工作区:实时修改的代码文件
仓库:提交的代码
暂存区:介于工作区和仓库之间。相当于汉诺塔中的第三方工具,目的是为了抽取工作区需要进行版本控制的文件
例如一个项目结构如下:其中框出来的是不需要进行版本控制的文件
工作区中的.idea、target、xxxx.iml文件,如果之间用工作区很难将这些文件去除,加个暂存区就可以将这些去除,然后提交暂存区的文件到仓库。
soft、mixed、hard、keep之间的区别
在使用回滚操作的时候有上面4个选项
如果你还没有搞懂,我将四个概念总结出来
soft:
只是修改指针的位置,不修改暂存区的文件,工作区文件不变 。作用是改变提交的轨迹
mixed
改变指针指向、回滚到选择的仓库记录、同时暂存区也会恢复到选择的记录。工作区文件不变。
hard
回滚操作会将指针、暂存区、工作区都恢复到选中的仓库记录状态
keep
文件将恢复到所选提交的状态,但本地更改将保持不变。
(Files will be reverted to the state of the selected commit,but local changes will be kept intact)