浅尝GIT

268 阅读7分钟

关键词

版本控制、分布式VS集中式、版本回退、工作区&暂存区、分支管理

GIT是啥?

git分布式版本管理系统

什么是版本控制,为什么需要以git为代表的版本控制系统?

想必经历过毕业的人都有过写毕业论文的经历,一遍遍改论文,一遍遍折磨,一遍遍怀疑人生。。。 你写完初稿后,需要送交老师修改,你保存了一份毕业论文_初.doc。随后交由王老师修改,得到毕业论文_王.doc,再交给李老师毕业论文_李.doc,孙老师毕业论文_孙.doc,袁。。。

于是你的文件夹就变成了这样

截屏2021-10-11 23.10.43.png 参加答辩时,答辩老师指出你的正文缺少关键的实验数据,你记得有一位老师叫你加上过相关数据,但是你不记得是哪位老师了。怎么办呢?你只有一个文件一个文件的去找。

于是你就想,如果能有个系统能把各个版本的文件都整理起来,每次改动文件都记录下改动点改动时间甚至是改动人等等,那该多好啊,巧了,git就是你想要的

分布式 VS 集中式

git是分布式版本管理系统的代表,而与之相对的集中式的代表是svn,他两最大的差异是什么呢?

借用廖雪峰老师的一句话: 分布式的核心是同步,集中式的核心是主从

  • git

image.png (ps:为了方便描述,简单地将本地版本和远端版本的维度的视作相等,实际上本地一个commit是一个版本,远端一个tag即若干个commit是一个版本)

如图所示,每个人本地都有一份git版本库,远端(githubgitlab)还会有一份完整的版本库。

每个人在自己本地修改代码,addcommit只是在本地对改动做暂存、存储,push的时候才将改动上传到远端。所以每个人改了自己代码后,只需要push一次到远端,远端就结合你的改动生成了最新版本的代码。而其他人想要这个最新版本的代码,就pull从远端拉下来,并且他本地的git仓库也会存储他之前版本的代码,所以他本地是有历史版本当前最新版本的代码的。

若是中央服务器突然崩溃,远端版本库全部丢失,其实完全可在本地的各个主机中找到完整或是最接近完整的版本库,再上传到全新的远端服务器即可。

所以 分布式的核心是同步

远端可同步本地,本地可同步远端,二者相辅相成,一方缺失后可由另一方辅助重构。

  • svn

image.png

如图所示,每个人本地没有完整的版本库,本地只有从远端pull下来的当前最新版本代码。

每个人本地只有当前的开发版本,若是其他人修改了代码,推到远端生成了新版本,你从远端拉下最新版本,这会覆盖原有版本的代码。

虽然远端有完整的版本库,但是你本地没有对应的版本库,你想查看历史版本,就只能从远端去拉。

若是中央服务器突然崩溃,远端版本库全部丢失。本地都只有当前的开发版本,即使可以通过diff出本地改动,拿到远端最新版本代码,但是历史版本全部丢失,对项目也是极大地损害。

所以 集中式的核心是主从

远端可同步本地,本地不可同步远端,本地从属远端

版本回退

在本地版本库中,一次commit就会生成一个版本

git log 可查看commit记录(版本记录)

我们需要commit_id进行版本回退

截屏2021-10-12 00.26.20.png

进行版本回退可用两种命令: git reset commit_idgit revert commit_id

wecom-temp-99e9888534bffc608d646e4727ce46d0.png

  • git reset

上图是一个版本库,若想由版本D回到版本B,可使用命令git reset BBB1

wecom-temp-64e6f7779eaf5764accf044b18cc7ba2.png

git reset简单粗暴,回到版本B嘛,删掉他前面的版本C和版本D不就回到B了吗

这样做的确起了作用,但如果我们哪天想回到版本D咋办呢?删了还能回去吗?能,git reset虽粗暴,但可退可进。想要回到版本D的话,我们还是需要版本D的commit_id

此时需要git reflog命令去查找git命令的所有历史记录,查找可知版本D的commit_id是DDD1,git reset DDD1即可回到版本D。

使用git reset的关键就是需要知道版本的commit_id,若是不知道就回不去了。

  • git revert

wecom-temp-400b94c877bb6c33f669fe4c9a30e1fb.png

相比起git reset的简单粗暴,git revert要含蓄的多。

若是想回到版本C,则要使用git revert DDD1,代表需要回滚版本D,这可在不改变原有版本的前提下,生成一个最新的C’的版本,该版本和版本C代码相同,只是commit_id不同,是一个复制品。

且若想回到版本D,则git revert CCC2,则可生成代码和D相同的版本D‘,这样做的好处是保留了原始版本,相当于保留了完整的操作记录,可方便复盘、回退。

工作区 && 暂存区

image.png

  • 工作区(Working Directory) 工作区就是你的项目的文件夹,你可以使用各种编辑器打开此文件夹进行日常工作。

  • 暂存区(stage) 字面意思,可使用git add将改动存入暂存区,git commmit 可将暂存区的所有改动合到当前分支。

其实可将git管理下的项目看作网购软件。

工作区就是商品列表,你在工作区选中可提交的改动(想买的商品),add到暂存区(购物车)中,当你选择完所有的改动(商品)后,可将暂存区(购物车)中的所有改动(商品)commit到当前分支(提交订单),最后推送远端(付账)就行。

  • 暂存区的意义是什么?为什么不能直接commit代码到当前分支?

【存疑】找过很多解释,但一直没真正搞懂暂存区存在的意义是什么,待解答

分支管理

git的每一次commit都是一个时间点,若干个时间点相连接汇聚成一条时间线。

在日常项目开发中,都是多人协助,每一个人开发一个新需求一般都会新拉一个分支单独开发,开发完成后再合并测试或是线上分支。

虽然是多分支管理,但其实 项目文件还是那一套项目文件,只是不同分支所处的项目版本不同

image.png

git init时,git会默认生成master分支,即图中的master指针,head指针指向的是当前所在分支,也就是master分支。

而后续的devissue#1issue#2分支都是以master为base,git checkout -b而来。

他们与master其实还是处于统一项目文件即统一时间线上,只是在不同的分支进行了不同的操作,生成了不同的改动被git给记录下来了,这也是这些分支的差异。

而由于git的分支管理本质上是指针管理,若是此时想将issue#1合并到master,其实就是改变指针所指位置即可。

image.png

而若此时想将dev分支合到master,因为master已经合并了issue#1提交的代码了,就需要先git pull拉下master的最新代码,再进行合并操作。