前端工程化——版本控制

什么是版本控制

版本控制是一种系统性的方法,用于管理和跟踪软件开发项目中的代码、文件和资源。它的核心目标是在不同时间点的开发中保持代码的一致性、可追溯性和可维护性。

为什么要做版本控制

这个问题可以从定义中的关键词可以看出端倪:不同时间点下的代码一致性、可追溯性、可维护性。这里额外补充一点:当今的互联网开发早已步入敏捷迭代,各种动态化方案层出不穷都有着顺应时代潮流的意思,因此软件开发一定会越来越多地涉及到团队开发,团队之间的协作也一定需要这样一个机制去保障稳定性。

代码一致性

版本控制系统允许开发人员有效地管理和组织项目中的代码。它跟踪每个文件的历史记录,记录了每个版本的变更,包括谁做了什么修改、何时以及为什么。

可追溯性

版本控制系统允许为重要的里程碑或发布创建标签(tag),以便轻松识别和回滚到特定版本。

并且当某个版本的代码出现问题,版本控制系统允许开发人员轻松地回滚到之前的稳定版本,并在不破坏其余代码的情况下进行修复。

可维护性

开发人员可以创建分支(branch),这是一个独立的代码副本,用于开发新功能、修复错误或进行实验性工作。然后,这些分支可以与主代码库合并,以实现功能集成。

团队协作

在多人协作的环境中,不同开发者可能同时修改代码。版本控制系统确保不同的修改不会互相冲突,以及如何解决冲突。

版本控制系统促进了团队之间的协作,可以通过代码审查工具进行代码审查,以确保代码质量和一致性。

版本控制工具Git

Git的安装

WIndows

访问 Git官网,选择对应的操作系统下载即可。

这里下载独立安装包即可

install就行,会自动安装一个git GUI工具,但通常不会直接用它

下载完成安装即可,输入以下命令验证安装是否成功

复制代码
git version

图形化工具

安装

这里推荐TortoiseGit这个工具,非常方便。但我觉得Git本身学习成本并不高,GUI工具更多是为了提升效率,基本的Git知识点还是需要掌握的。

下载本体

然后是语言包

安装时一路next即可,安装完本体后再安装语言包。

配置好Github的账户、邮箱、秘钥等,注意配置好了密钥也不会在下述部分显示,可以打开编辑全局进行查看

使用

在使用之前先提前补充一个点(后续会详细介绍),Git有本地仓库和远端仓库的概念,通常支持HTTPSSSH两种协议进行关联,两种方式优缺点也十分明显:

  • HTTPS:无需额外配置,但是在每次连接远端仓库时需要输入账号密码进行校验。
  • SSH:生成一组密钥对,需要本地进行配置,好处是配置好后每次连接远端仓库时会自动比较密钥对,无需额外校验。关于SSH详细可以参考这篇文章ssh-远程登录协议

为了一劳永逸,我们这里配置下SSH,首先打开Git bash

ruby 复制代码
ruby
复制代码
# 输入下列命令,最后一个参数是您的邮箱
$ ssh-keygen -t rsa -C yourEmail.com

可以看到密钥对已经生成了

进入上述目录,注意.ssh文件夹默认是隐藏的,直接访问路径就行

Github为例,配置公钥

创建一个Demo项目,平时学习的话就创建公有项目就行

复制一下我们的项目链接

选取一个你喜欢的目录作为本地工作区,然后按鼠标右键

然后喜提报错,但没事是因为我们确实一个配置,导致TortoiseGitGit冲突了

首先我们找到安装Git的目录,拷贝一下ssh.exe的路径,比如D:\software\Git\usr\bin\ssh.exe

Here We Go

我们进到这个目录,创建一个README.md,随便写点什么保存

将代码提交到本地暂存区

提交完成后会有一个推送按钮,作用是将暂存区里的代码推送到远端

当然又可以鼠标右键,进行推送

然后我们重新起一个目录验证一下,代码是否被推送到了远端,和前面一样手动Clone一下

到此为止,GUI工具就先简易把玩到这里,你可能会疑惑拉取、同步按钮这些不是还没讲吗?别着急,我们先从Git的机制入手,看看GUI工具背后都做了哪些工作,到时候不用我说你也会细细把玩了~

VS Code插件推荐

这里主要推荐官方自带的Git工具和两个补充插件

官方自带+Gitlen

Gitlen是非常全面的git插件,这里就结合官方自带能力演示一下常规用到的一些功能点。

查看某行代码的提交信息

可以很直观地看到本地和远端代码的版本差异

将代码添加到缓存中

将代码提交到本地暂存区

将代码推送到远端

查看刚刚提交的信息

Git Graph

一个优美的Git提交可视化插件,在团队开发时可以很直观地看出各版本之前的差异。

本地仓库、暂存区、远端仓库

相信通过前面的实操你已经对这三个概念有了基本的认识,接下来我们详细了解一下他们之前的区别把。

本地仓库

  • 本地仓库是物理存储在您电脑上的Git仓库副本
  • 它包含了完整的项目记录和文件版本信息
  • 您可以在本地仓库中进行增删改查等所有你想对代码干的事儿

暂存区

  • 暂存区是本地仓库的一部分,可以理解为本地仓库变更的一个快照,用于准备要提交的更改
  • 当你完成文件粒度的代码变更后,需要将这些文件提交到暂存区,以便一次性提交一个或多个更改。这使得你可以有选择地进行提交更改,而不是一次性提交所有更改
  • 暂存区和当前正在开发的本地仓库是一一对应的,也就是说当代码已经保存到暂存区后,不再运行进行诸如分支切换等变更本地仓库文件版本的操作

远程仓库

  • 远程仓库是位于网络上的Git仓库副本,通常托管在代码托管服务上。(如GitHub、Gitlab等)
  • 它允许多个开发者协同工作,共享项目代码。
  • 具备私有和公有属性,由开发者决定是否将项目开源
  • 具备特定分支保护性,通常将master(主干)分支作为受保护的分支,不允许开发者在主干分支上进行开发,亦不允许开发者将本地分支代码直接推送到主干。那么怎么把分支同步到主干呢?一般托管平台会提供一个PR(pull request)能力,即一种向其他分支提交合并代码请求的能力。开发者创建PR,由项目的主要负责人和团队中的成员进行代码的审核后,合并到master分支
  • 当然你可以从远程仓库拉取最新代码以及将本地更改推送远端,并解决版本不一致带来的冲突

分支、提交、标签

这三个概念都是用作Git的版本控制的,可以细分出下面这些差异。

分支(branch

  • 分支是Git中用于并行开发和代码管理的核心机制,它允许你创建一个独立的开发线而不影响主线代码。(可以类比与世界线进行理解)
  • 每个分支都有自己的代码历史,你可以在分支上就行修改、提交和合并操作。
  • 常见的用途包含新增特性(feature分支)、修复代码(bugfix分支)、发布功能(release分支)、热修复(hotfix分支,一般用在native代码中)。这些分支命名是一种约定俗成的规范,我们在开发过程中也请尽量遵循这样的规范以减少沟通理解带来的gap
bash 复制代码
bash
复制代码
# 常用的分支命令,多的不用记,用到了再查就行
​
# 创建一个本地分支
git checkout -b branchName
​
# 拉取远端分支信息
git fetch
​
# 切换分支
git checkout newBranch
​
# 查看所有本地分支
git branch
​
# 查看远端所有分支,这里的-r指的是origin,也就是远端
git branch -r

提交(commit

前文在实践过程中已经提到过部分commit的知识点了,我们再来温习一下。

  • 提交操作相当于是一个快照,将本次更改的文件和提交信息存储到了暂存区。
  • 提交是代码历史的基本单位,可以有效地追踪和回溯项目的演变。
  • 提交时需要附带一条有意义的提交信息,以便更好理解每次更改的目的。
perl 复制代码
perl
复制代码
# 常用命令
​
# 提交代码到暂存区
git commit -m "本次提交干了啥"
​
# 提交代码到暂存区并跳过检查(不是很推荐跳过git hook的检查,但我就喜欢这样干,最后再统一修正)
git commit -m '本次干了啥' --no-verify

标签

  • 标签是Git中用于标记特定提交的方式,通常用于标记项目的重要里程碑。注意:在我们使用一些热门库时经常会看见诸如@latest、@release、@beta-0.1这样紧跟在npm包后面的小东西,这也就是标签,但不是git的标签而是npm包的标签,我们会在后续包管理的文章里再提到这一点。
  • 不同于分支。标签是静态的,不会随着新的提交而发生移动,除非你手动再次进行标记。
  • 标签所带来的语义能够让你很方便地找到和回滚到特定版本。
bash 复制代码
bash
复制代码
# 常用命令
​
# 创建标签
git tag 'release'
​
# 查看所有便签
git tag
​
# 查看特定标签的提交信息
git show tagName

如何运用Git创建一个工作区

这个小节其实已经在GUI工具哪里浅浅地操作了一遍了,我们再复习一下~

克隆代码,将代码从远端拉到本地

perl 复制代码
perl
复制代码
# 参数是仓库的ssh或https链接
git clone git@xxxxx
​
# clone后会自动关联远端,当然也可以通过下面命令进行关联
git remote add origin git@xxxxx

创建分支

bash 复制代码
bash
复制代码
# 创建分支
git checkout -b feature/git-demo

拉取代码

这一步通常会有git fetchgit pull两种方式,几乎所有的教程都会告诉你git pullgit fetch + git merge的命令语法糖,但并不会告诉你怎么用git fetch,因为我们在git fetch后无论是ide还是命令窗口都不会像git pulldiff的有效信息展示到我们眼前,所以接下来我们来仔细讲讲这个问题吧!

git fetch

执行git fetch不止会把远端代码变更拉取下来,还能将分支等信息也一并拉取下来,我们可以用前面的命令来进行检索git brach -a

那么我们怎么看,拉取的远端代码有哪些变更呢?结合我们之前安装的Vs code插件可以进行预览(二选一即可)

合并代码

检索完代码变更后我们如何合并呢?这里有git mergegit rebase两种方式,并且均会在有冲突时被打断,因此不用担心将代码冲突也一并合并了

merge VS rebase

一图胜千言,这是merge合并后的git graph

这是rebase后的git graph

区别在于git merge后形成了一条commit,合并HEAD指针指向了新的提交,并且仍然存在两条时间线。而git rebase会在提交后销毁自身的世界线,融入主干的世界线,并且不会引起HEAD指针的变化。实际使用合理使用git rebase能有效减少世界线的条数,降低合并的复杂度。更多详情我推荐这篇文章面试官:说说你对Git Rebase 和 Git Merge的理解?区别?

解决冲突属于一个重要的部分,我们在后面一个场景小节单独说下。

提交代码

perl 复制代码
perl
复制代码
# 创建分支后首次提交,需要关联下远端
git push --set-upstream origin feature/git-demo
​
# 后续提交无需再关联
git push

提PR

在别人审核通过后,merge按钮会变绿,我们就可以合并到主干啦

特殊场景处理

合并冲突

接着上面的例子,我们创建了一个新的分支并修改了同一个文件,然后推送到远端

这时我们直接提PR会直接被打回,提示我们需要在合并前解决冲突。

ok接下来,我们来解决冲突。

首先是拉取并合并主干代码,这时我们发现会有传入更改和当前更改两段代码。

这里我提供一个个人解决冲突常用的思路:优先接收传入的变更,因为我对于自己的变更更熟悉,所有我通常会先备份自己的代码变更,然后接受传入的变更,最后再融入个人的代码变更,这对于我来说是一个高效的解决思路,但仍有一些细节需要处理。涉及到package.json、yarn.lcok等变更时,在解决冲突记得重新yarn一下,防止npm包的冲突;涉及到核心业务逻辑和细粒度很高的地方(比如修改了同一个函数并且是不兼容变更)时需要和同事一起确认正确的逻辑后再进行冲突合并,否则很容易因解决冲突而发生代码丢失的情况。当然这种冲突本身是应该尽量避免的,避免两个甚至多个同学对同一个模块进行并发开发。

回到案例中,这两个冲突属于兼容性冲突,我们按上面的策略先拷贝我的变更,再接受传入的变更,最后将拷贝的变更合入,(PS:我当然知道可以直接点保留双方更改,但我不推荐这样做,这个操作往往会带来一些麻烦)最后我们提交一条新的commit用于解决冲突。

然后我们刷新PR页面会发现此时已经可以合并到主干了

回撤代码

当我们一步小心错误地合并代码了或者想要回退一些变更时,通常有两个做法,分别是revertreset,下面是他们的一些特征对比:

  • revert
  • reset

revert

用于撤销一个或多个提交,并用一个新的提交来反转这些更改。这意味着原有的提交仍然存在,只是添加了一个新的提交来撤销之前的更改。在能用revert解决的情况下,我不建议使用reset,但revert无法回撤merge时形成的commit,此时就需要借助reset了。

bash 复制代码
bash
复制代码
# 查看 commit 信息
git log 
​
# 回撤对应的commit
git revert commitId

reset

用于移动分支的指针,以便于指向不同的提交,模式上包含软重置和硬重置。在回撤操作时通常使用硬重置,特别需要注意的是硬重置是强制将分支指针移动到特定commit,会丢失部分历史记录,使用时需要特别小心。

perl 复制代码
perl
复制代码
# 查看 commit 信息
git log 
​
# 回撤对应的commit
git reset --hard commitId

使用旧功能进行新功能开发,如何将这些变更迁移到新分支

分三步走:

  • 将旧分支的commit记录提交到远端,使用git log查看commitId并手动记录下来
  • 切换新分支
  • 执行git cherry-pick commitId

更多cherry-pick相关知识,参考git cherry-pick 教程

你可能并不需要这些命令

看到不少博主都推荐使用git stash来处理并发更改的问题,我个人使用下来并不是很推荐这样做,原因很简单,经常会忘记,忘记保存过,忘记该恢复到哪个版本,恢复时误操作把代码给删了...

简单介绍一下git stash

perl 复制代码
perl
复制代码
# 临时存储
git stash
​
# 查看存储记录
git stash list
​
# 恢复并且不删除stash内容
git stash apply
​
# 恢复并且删除stash内容
git stash pop

那么有没有什么办法规避呢,很简单嘛,把当前代码先提交一下;或者重新创建一个工作区拉取代码都能解决。并且想要某个文件在某一时段的变化,直接用VS code的时间轴功能不香吗?

结语

这是前端工程化系列的第一篇文章,预计后续还有 10 篇的样子,个人精力有限,尽量周更。还是老规矩,如果对你有帮助的话点个👍和收藏吧❤️

参考文献

www.cnblogs.com/anayigeren/...

面试官:说说你对Git Rebase 和 Git Merge的理解?区别?

git cherry-pick 教程

作者:lemon橙汁

链接:juejin.cn/spost/72789...

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关推荐
undefined&&懒洋洋5 分钟前
Web和UE5像素流送、通信教程
前端·ue5
潘多编程19 分钟前
Spring Boot微服务架构设计与实战
spring boot·后端·微服务
2402_8575893624 分钟前
新闻推荐系统:Spring Boot框架详解
java·spring boot·后端
2401_8576226625 分钟前
新闻推荐系统:Spring Boot的可扩展性
java·spring boot·后端
大前端爱好者2 小时前
React 19 新特性详解
前端
Amagi.2 小时前
Spring中Bean的作用域
java·后端·spring
随云6322 小时前
WebGL编程指南之着色器语言GLSL ES(入门GLSL ES这篇就够了)
前端·webgl
随云6322 小时前
WebGL编程指南之进入三维世界
前端·webgl
熬夜学编程的小王2 小时前
C++类与对象深度解析(一):从抽象到实践的全面入门指南
c++·git·算法
2402_857589362 小时前
Spring Boot新闻推荐系统设计与实现
java·spring boot·后端