当前位置: 首页 > news >正文

Git简明教程

请添加图片描述

1.Git的定位

在我们自己开发项目的过程中,经常会遇到这样的情况,为了防止代码丢失,或者新变更的代码影响到原有的代码功能,为了在失误后能恢复到原来的版本,不得不复制出一个副本,比如:“坦克大战1.0”“坦克大战2.0”“坦克大战-确定版”“坦克大战-验收版”…

虽然每个版本我们都进行了备份,但是每个版本都有自己的内容,随着版本的不断增多,各自版本修改的内容是什么我们就不清楚了。

因此,就需要有一个版本控制器,来记录每次的修改以及版本的迭代信息,比如“坦克大战2.0”在“坦克大战1.0”上变更了Move类中第3行的代码,那么git的作用就会记录此次的变更具体信息,以此来方便我们回滚或者继续开发。

Git可以控制电脑上所有格式的文档,不仅是文本文件,源代码,还可以是二进制文件,比如图片、视频(这类文件无法记录具体的变更,只能记录空间占用的变化,比如100kb–>200kb)

2.Git的安装(Linux-centos)

如果你的平台是centos,安装git如下操作,以我的centos7.6为例:

首先,你可以尝试输入git --version,如果提示类似于git version 1.8.3.1 ,说明你已经安装好了,如果提示-bash: git: command not found,则执行以下命令进行安装sudo yum install git -y,完成安装后,可以再通过命令git --version来检验自己是否安装完成。

3.Git基本操作

3.1创建git本地仓库

只有把文件放在git仓库中,我们才能对文件的版本进行控制,所以我们首先需要创建一个仓库出来。
先通过mkdir xxx命令创建一个目录,切换到对应目录后,输入命令git init,来创建一个git本地仓库,可以通过tree .git/命令来查看Git仓库的具体细节。
在这里插入图片描述
注意,不允许在.git下手动修改

3.2配置git

当安装git以后,首先要做的就是配置你的用户名和Email地址,命令如下:

git config [--global] user.name "Your Name" 
git config [--global] user.email "email@example.com" 
# 把 Your Name 改成你的昵称
# 把 email@example.com 改成邮箱的格式,只要格式正确即可。

其中--global是一个可选项,因为一台机器上可以创建多个Git仓库,通过该选项,就是给所有仓库都进行了配置(全局配置)。如果系统在不同仓库中使用不同的namee-mail,可以不要--global选项,但要注意,执行命令时必须要在想要操作的仓库中。
查看配置的命令为:

git config -l

删除对应配置的命令为:

git config [--global] --unset user.name
git config [--global] --unset user.email

在这里插入图片描述

3.3认识工作区、暂存区、版本库

我们前边说了,只有把文件放在git仓库中,才能对文件版本进行控制,那么我们在git仓库中通过touch ReadMe,来创建一个ReadMe文件以后,可以对ReadMe文件进行操作吗?在这里插入图片描述
答案是不行,通过以上命令,列举出来的,就划分为两个区域:
.git在版本库(仓库中)
ReadMe在工作区中
只有将工作区的内容,通过addcommit放入版本库中以后,才能进行文件版本控制。

下图展示了工作区、暂存区和版本库之间的关系:
在这里插入图片描述
第一步操作add,就是将工作区中文件的修改内容,添加进版本库中的暂存区中;

修改内容:包含增加、修改、删除

第二步操作commit,就是把暂存区中的内容,提交到版本库中的master分支下;
走完这两步操作,我们才可以真正意义上来管理ReadMe文件了


版本库中还存在一个对象区——objects工作区每次的修改内容都会写入到一个git对象中,每次add,都会把这个git对象来交给对象区来维护,那么也就相当于,对象区维护了文件所有的版本

暂存区存储一个个git对象的索引,master分支下,存储的也是一个个git对象的索引,不存储具体的对象。

在这里插入图片描述
如果文件出现变更,最下边应该还有分支index

3.4提交文件修改

我们在.git目录下创建了ReadMe文件,如果对ReadMe文件进行修改,需要通过addcommit的方式来进行记录,以下是具体的操作过程。

首先通过vim命令在ReadMe文件中添加一行内容hello git,如下展示,现在我们想要把ReadMe文件的变更记录进行保存,就需要下一步的add操作。
在这里插入图片描述

  • git add [文件名1] [文件名2]:添加一个或者多个文件到暂存区
  • git add .:添加当前目录下的所有文件到暂存区

完成add以后,我们紧接着就需要commit操作,来真正意义上把文件变更内容保存到本地仓库中。

  • git commit -m "此次变更的具体描述细节":提交暂存区的全部内容到本地仓库
  • git commit [文件名1] [文件名2] -m "此此变更的具体描述细节":提交暂存区的指定内容保存到本地仓库中

注意:git commit后边的-m选项,要跟上本次提交的message,由用户自己完成,这部分内容不可省略,并要好好描述,用于记录此次变更的细节,是给我们自己看的。

整体操作流程如下图所示:
在这里插入图片描述

我们可以通过git log命令来查看我们的提交记录,该命令可以帮我们打印出来时间由近到远的所有记录,下图中都标红部分,就是该次commit的commit ID,由这个唯一的ID,就可以定位到这次提交。
在这里插入图片描述
如果觉得输出的信息太多,可以加上 --pretty=oneline参数
在这里插入图片描述

3.5查看.git文件

在我们完成上边的提交操作以后,再通过tree .git命令来查看文件目录,如下图所示,多了index目录:

在这里插入图片描述
我们可以通过cat命令来查看不同的目录下的文件.

首先我们来看HEAD指针,通过cat .git/HEAD命令,面板上打印出ref: refs/heads/master(说明HEAD指针指向master分支),再通过命令cat .git/refs/heads/master命令(该命令打印出最新一次提交的commitID),面板上打印出一行commitID,再通过命令git cat-file -p commitID,面板打印如下图结果,打印出了这次commitID提交对应的提交信息。
在这里插入图片描述

我们可以发现,打印结果中的tree后也跟着一个commitID,打印这个commitID,得到提交文件的commitID,再打印这个commitID,就可以得到文件里具体修改的内容。
在这里插入图片描述
总结:
HEAD指针指向.git/refs/heads/master(master分支),打印该分支,可以得到最新一次提交的commitID,打印这个commitID可以得到该次commit的描述详情,打印结果的tree后还跟着一个commitID,打印这个ID可以得到具体提交的文件的commitID,再打印这个ID,就可以得到文件具体修改的内容。

3.6场景学习

在这里插入图片描述
如上图所示,提交后打印1 file changed, 0 insertions(+), 0 deletions(-),意思是只有一个文件改变了,这是因为我们只将file1提交到暂存区了,commit不会把暂存区以外的东西提交,想要提交file2,就需要再重新addcommit

3.7修改文件

Git跟踪并管理的是修改,而非文件。

新增、删除或更改都属于修改,甚至创建一个新文件,也算一个修改。

让我们通过vim命令将ReadMe文件进行一次修改,里边增加一行代码hello world
在这里插入图片描述
接着可以通过git status来查看当前仓库的状态:
在这里插入图片描述
上面的结果告诉我们,ReadMe文件被修改过了,但还没有完成添加与提交。
目前,我们只知道文件被修改了,如果想要知道具体哪些地方被修改了,可以通过git diff命令
在这里插入图片描述

git diff [file]命令用来显示暂存区和工作区文件的差异,显示的格式是Unix通用的diff格式。

我们add文件以后,再通过status命令来查看状态,显示有待提交。
在这里插入图片描述
commit文件并带上描述,再通过status命令来查看状态:
在这里插入图片描述

3.8版本回退

Git能够管理文件的历史版本,如果有一天你发现之前的工作做的出现了很大的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本回退了。
执行git reset命令用于回退版本,可以指定退回某一次提交的版本,回退的本质是将版本库中的内容进行回退,工作区或暂存区是否回退由命令参数决定:
git reset命令语法格式为:git reset [--soft | --mixed | --hard [HEAD]]

  • --soft参数对于工作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
  • --mixed为默认选项(使用时可以不带该参数),该参数将暂存区的内容退回为指定提交版本内容,工作区文件保持不变。
  • --hard参数将暂存区和工作区都退回到指定版本。该参数需要慎用,因为如果工作区有未提交的代码时,使用该命令工作区会回滚,你没有提交的代码就再也找不回了。

HEAD说明:

  • 可直接写成commit ID,表示指定退回的版本
  • HEAD 表示当前版本
  • HEAD^ 上一个版本
  • HEAD^^ 上上一个版本
  • 以此类推

可以使用~数字表示:

  • HEAD~0 表示当前版本
  • HEAD~1 上一个版本
  • HEAD~2 上上一个版本

以下是实际操作场景:
在这里插入图片描述
通过git reset --hard commit ID回退到指定版本,ReadMe文件里边的内容也发生了回滚。
如果想要再返回原来的状态,就再找到指定的commit ID进行回滚即可。
在这里插入图片描述
只要commit ID我们能找到,我们就可以回退到指定的版本,可以通过git reflog命令来查看所有的commit ID记录(此处我们发现gommit ID很短,但是通过这个短的ID也能够进行正常回退)
在这里插入图片描述

我们进行版本回退的速度很快,这是因为我们的每个版本都有一个commit ID,git只需要更改指针的指向(HEAD指针指向master,master存储最新一次commit ID)就可以进行版本的回退了。

总结:
在这里插入图片描述

3.9撤销修改

如果我们在工作区写了很长时间代码,但是后来写的代码质量都很差,想要撤销掉我们的修改,恢复到上一个版本,分以下几种情况来讨论。

  • 情况一:工作区的代码没有add
  • 情况二:已经add,但没有commit
  • 情况三:已经add,并且也commit了

我们还以ReadMe文件作为举例,我们在工作区,给ReadMe文件新增了一行代码xxx code
在这里插入图片描述

在这里插入图片描述

对应情况一,我们只需要命令git checkout --[filename]即可撤销
在这里插入图片描述
对应情况二,我们可以先通过命令git reset HEAD ReadMe(默认参数为--mixed),将暂存区的内容回退到当前版本区的内容(都为空),然后再通过git checkout --[filename]命令来撤销工作区修改的内容。
在这里插入图片描述
对于情况三,我们可以通过命令git reset --hard HEAD^将三个区域都回退到上一版本的内容【注意:该情况为commit之后,push之前】
在这里插入图片描述
总结:
在这里插入图片描述

3.10删除文件

在git中,如果我们想要做一个删除操作,只通过在工作区的rm命令是无法完成删除的,还需要addcommit操作才能完成暂存区和工作区的删除

所以我们一般可以直接通过命令git rm可以完成工作区和暂存区的删除,然后再通过git commit -m" ",来完成版本库中的删除。
在这里插入图片描述

4.Git分支管理

4.1理解分支

分支就是一个复制版本的概念,它与主版本互不干扰,可以在分支上进行操作,防止在主干上直接操作造成失误;在分支上完成开发操作以后,可以再合并分支到主干上。

在版本回退中,每次提交,Git都会把它们串成一条时间线,这条时间线就可以理解为一个分支,如果只有这一条时间线,那么这个分支就叫做主分支,即master分支。

HEAD指针不仅可以指向master,还可以指向其他分支,被指向的分支就是当前正在工作的分支。

4.2创建、切换、合并分支

Git支持我们查看或创建其他分支,在这里我们创建第一个自己的分支dev,对应的命令为:
在这里插入图片描述
*表示当前HEAD指向的分支是master分支,并且目前dev和master指向同一个修改。
在这里插入图片描述
如果我们想要在dev分支下进行开发工作,就需要将分支切换到dev上来,可以通过git checkout dev命令来完成切换,如下演示:
在这里插入图片描述
接下来我们在dev分支下修改ReadMe文件,新增一行内容,并进行一次提交操作:
在这里插入图片描述
在dev分支上commit以后,当前仓库的状态如下:
在这里插入图片描述

如果我们想要在master主分支上看到新的提交,就需要将dev分支合并到master分支,示例如下:
在这里插入图片描述
当前仓库的状态如下:
在这里插入图片描述
Fast-forward代表“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

命令:
git branch:查看本地所有分支
git branch -r:查看远程所有分支
git branch -a:查看所有分支

4.3删除分支

合并完成以后,dev分支对我们来说就没用了,那么dev分支就可以被删除掉,注意如果当前正处于某分支下,就不能删除当前分支,需要先切换到master分支下,再来删除dev分支。

git branch -d 分支名
在这里插入图片描述
此时的仓库状态如下所示:
在这里插入图片描述
因为创建、合并和删除分支非常快,所以更建议使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

如果我们在分支上开发了新功能,但是产品不要这个新功能了,这时候我们可以通过git branch -D 分支名来强制删除该分支。

4.4合并冲突

在我们合并分支的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。
比如我们在主分支上的ReadMe文件内容为aaa on dev1,我们创建并切换到新的分支上dev1,将aaa on dev1变更为bbb on dev1,再换回到主分支上,并将aaa on dev1改为ccc on dev1,这时候想要将dev1分支合并到master主分支上,就会产生合并冲突。
在这里插入图片描述

为了演示这个问题,我们需要创建一个新的分支,并切换到该分支上,可以使用git checkout -b dev1命令,一步完成创建分支并切换到该分支的操作。
在这里插入图片描述
接下来在dev1分支上,将aaa on dev1变更为bbb on dev1,并add commit
在这里插入图片描述
然后再切回到主分支上,将aaa on dev1变更为bbb on dev1,并add commit
在这里插入图片描述
此时仓库中的状态就如下图所示:
在这里插入图片描述
如果想要将dev1分支合并到master分支上,就会有以下合并冲突的提示:
在这里插入图片描述
修改冲突内容并提交
在这里插入图片描述
在这里插入图片描述
此时合并冲突就修改了,仓库的状态如下图所示,我们也可以通过命令git log --graph --pretty=oneline --abbrev-commit,来查看仓库的状态
在这里插入图片描述
在这里插入图片描述

4.5 分支管理策略

通常合并分支时,如果可能,Git会采用Fast forward模式。那么形成的合并结果将如下图所示:
在这里插入图片描述
在这种Fast forward模式下,删除分支以后,查看历史分支时,会丢掉分支信息,看不出来最新提交到底是merge进来的还是正常提交的。
但在合并冲突部分,我们也看到通过解决冲突问题,会再进行一次新的提交,得到的最终状态为:
在这里插入图片描述
那么这就不是Fast forward模式了,这样的好处是,从分支历史上就可以看出分支信息。比如我们现在已经删除了在合并冲突部分创建的dev分支,但依旧能看到master其实是由其他分支合并得到的。

Git支持我们强制禁用Fast forward模式,那么就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

下面是实战示例:
首先,创建新的分支dev,并切换至新的分支:
在这里插入图片描述
修改ReadMe文件,并提交一个新的commit
在这里插入图片描述
切回master分支,开始合并:
在这里插入图片描述
--no-ff参数,表示禁用Fast forward模式,禁用Fast forward模式后合并会创建一个新的commit,所以加上-m参数,把描述写进去。
合并后,查看分支历史:
在这里插入图片描述
可以看到,不使用Fast forward模式,merge后就像下图状态:
在这里插入图片描述

所以在合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾今做过合并,而fast forwad合并就看不出来曾经做过合并。

分支策略

在实际开发中,我们应该遵循几个基本原则来进行分支管理;
master分支是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
而干活平时应该在dev分支上,每个人都在dev分支上干活,且每个人都有自己的分支,时不时往dev分支上合并就可以了,然后再把dev分支合并到master分支上;
在这里插入图片描述
所以团队合作的分支看起来就像下图:
在这里插入图片描述

4.6 bug分支

假如我们现在正在dev分支上进行开发,开发到一半,突然发现master分支上面有bug,需要解决。在Git中,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
如果我们现在在dev分支上开发了一部分,还无法提交,这时候需要使用git stash命令,来将当前的工作区信息进行储藏(只存储被git追踪的文件),被储藏的内容可以在将来某个时刻恢复出来。
在这里插入图片描述
我们用git status命令查看工作区,是干净的,因此可以放心地创建分支来修复bug。
储藏dev分支的工作区以后,由于我们要基于master分支修复bug,所以需要切回master分支,再新建临时分支来修复bug,示例如下:
在这里插入图片描述
修复完成后,切换到master分支,并完成合并,最后删除fix_bug分支。
在这里插入图片描述
这时,我们已经完成了bug的修复,要继续回到dev分支上进行开发,切回dev分支,使用git stash list可以看到我们存储的工作现场版本,使用git stash pop命令恢复现场:
在这里插入图片描述
然后我们可以继续开发,开发完成后提交:
在这里插入图片描述
此时git仓库的状态如下所示:
在这里插入图片描述
master分支目前最新的提交,是要领先于dev基于master分支时提交的,我们最终想要让master分支合并dev分支,但如果切回master分支直接合并,有可能存在devfix_bug分支上的冲突,而代码冲突需要我们手动解决(在master上解决),直接在master分支上变更,是有一定风险的,这时更好的做法时,切回dev分支,将master分支合并到dev分支上,并在dev分支上解决代码冲突,解决冲突以后,再将dev分支合并到master分支上,此时的状态为:
在这里插入图片描述
在这里插入图片描述
实操如下:
在这里插入图片描述

5.远程操作

5.1 分布式版本控制系统

我们之前所介绍到的所有内容(工作区、暂存区、版本库等等),都是在本地,也就是在你的笔记本或者计算机上。而我们的Git其实是分布式版本控制系统

可以简单理解为,我们每个人的电脑上都是一个完整的版本库,大家可以在多台电脑上进行修改,然后可以把自己的修改推送到中央服务器上,其他同学可以通过拉取中央服务器上的代码来获取到最新的修改;中央服务器的作用就是方便“交换”大家的修改。
在这里插入图片描述

5.2 远程仓库

Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上,有一台电脑充当服务器的角色,每天24h开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。

网站GitHub或者gitee都是提供Git仓库托管服务的,下面我们来使用一下gitee(码云)远程仓库。

新建远程仓库

在这里插入图片描述
在这里插入图片描述
创建成功:
在这里插入图片描述
并且在刚创建好的仓库中,有且只有一个默认分支master
在这里插入图片描述

克隆远程仓库

克隆/下载远端仓库到本地,需要使用git clone命令,后面跟上我们的远端仓库链接:
在这里插入图片描述
SSH协议和HTTPS协议是Git最常使用的两种传输协议。SSH协议使用了公钥加密和公钥登录机制,体现了其实用性和安全性,使用此协议需要将我们的公钥放上服务器,由Git服务器进行管理。使用HTTPS方式时,没有要求,可以直接克隆下来。

  • 使用HTTPS方式:
    在这里插入图片描述
  • 使用SSH方式:
    SSH方式直接使用git clone命令是不能够将远程仓库克隆到本地的,需要我们将公钥添加到远端仓库中,才能够将仓库克隆下来。

第一步:创建SSH Key;在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsaid_rsa.pub这两个文件,如果已经有了,可以直接跳到下一步。如果没有,需要创建SSH Key:

注意此处要输入自己的邮箱,然后一路回车,使用默认值即可。

在这里插入图片描述
第二步:添加自己的公钥到远端仓库

再次打开ssh目录,查看公钥id_rsa.pub,将公钥复制,粘贴到gitee上。
在这里插入图片描述
在这里插入图片描述
然后再输入git clone命令就可以完成克隆操作了。

完成克隆以后,仓库的状态如下图所示:
在这里插入图片描述

向远程仓库推送

在向远程仓库推送时,需要注意设置的name和Email需要和gitee上配置的用户名和邮箱保持一致,否则会报错。
在这里插入图片描述

配置好以后,我们就可以向远程仓库推送了
推送的命令格式如下:

git push <远程主机名> <本地分支名><远程分支名># 如果本地分支名与远程分支名相同,则可以省略冒号后的内容
git push <远程主机名> <本地分支名>

具体的推送操作如下:
在这里插入图片描述

整个推送的流程如下图所示:

在这里插入图片描述

拉取远程仓库

如果其他同学向远端仓库push内容,那么远端仓库的代码是新于你本地的代码的,所以就需要通过命令来拉取远程仓库上最新的代码,代码格式如下:

git pull <远程主机名> <远程分支名>:<本地分支名># 如果远程分支是与当前分支合并,则冒号后面的部分可以省略
git pull <远程主机名> <远程分支名>

该命令会完成拉取合并分支两步操作。

命令git pull,后面不加其他内容,可以完成两种类型的拉取,一种是拉取对应分支下的内容【这种需要通过本地分支与远程分支建立连接】,另一种是拉取仓库的内容【即拉取远程最新的分支情况】

通过以下两种方式可以将本地分支与远程分支建立连接:
git checkout -b [branch-name] [origin/branch-name]【该方法在新建分支时建立连接】
git branch --set-upstream-to=origin/branch-name branch-name【该方法在建立好分支以后建立连接】

5.3 配置git

忽略特殊文件

在日常开发中,我们有些文件不想或者不应该提交到远端(比如说保存了数据库密码的配置文件),就需要在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件了。

.gitignore文件可以在gitee创建仓库时默认勾选生成,也可以由我们自己来创建,效果相同;
假如我们想要忽略以.so.ini结尾的所有文件,.gitignore的内容如下所示:

# 忽略以.so和.ini结尾的所有文件*.so
*.ini

如果某个以.so或者.ini结尾的文件又想要提交,可以在.gitignore文件中添加文件名,比如想要提交a.so,那么.gitignore的内容如下所示:

# 忽略以.so和.ini结尾的所有文件*.so
*.ini!a.so # 排除a.so文件

如果.gitignore文件里维护的代码太多了,而此时我们又新建了个文件(比如文件d.so),没有被git追踪管理,我们可以通过命令git check-ignore -v d.so 来查看被忽略的原因。

最后,配置好.gitignore文件以后,记得把.gitignore文件也提交到远端,就完成了。

给命令配置别名

在我们使用Git期间,可以通过配置,来将命令简化。

比如我们想要将git status命令简化为git st,对应的命令为(--global是全局参数):
git config --global alias.st status

git log --pretty=oneline --abbrev-commit命令简化为git lpa,对应的命令为:
git config --global alias.lpa 'log --pretty=oneline --abbrev-commit'

使用效果如下所示:
在这里插入图片描述

6.标签管理

标签tag,可以简单的理解为是对某次commit的一个标识,相当于起了一个别名。例如,在项目发布某个版本的时候,针对最后一次commit起一个v1.0这样的标签来标识里程碑的意义,相较于难以记住的commit IDtag可以很好的解决这个问题,因为其便于记忆且有意义,所以当我们需要回退到某个重要版本是,直接使用标签就能很快定位到。

6.1 操作标签

创建标签:

git tag v1.0给最新的一次commit打标

git tag -a[name] -m "xxx" [commit_id]
Git提供的带有说明的标签,用-a指定标签名,-m指定说明文字

如果想要给指定的commit打标签,找到历史提交的commit id,然后打标即可,如下命令
git tag v0.9 a009936

git tag:查看所有标签(按时间排序)
git show [tagname]:查看标签信息
git tag -d [tagname]:删除标签

6.2 推送标签

因为创建的标签都只保存在本地,不会自动推送到远程,如果想要推送某个标签到远程,使用命令git push origin <tagname>

如果你本地有很多的标签,也可以通过命令git push origin --tags,将所有标签一次性的全部推送到远端。

如果标签已经推送到远程,要删除远程标签,就需要两步操作,第一步先从本地删除,第二步再从远程删除。
git tag -d [tagname] #删除本地标签
git push origin :[tagname] #删除远程标签

7.多人协作

7.1 场景一:多人同一分支

现在我们有这样一个场景:

目标:在远程的master分支下的file.txt文件,新增代码aaabbb

实现:由开发者1新增aaa,由开发者2新增bbb
条件:在一个分支下协作完成

为了模拟实现以上场景,我们分别在linux和Windows上针对同项目进行协作开发。

目前,我们的远程仓库中只有一个master主分支,但在实际的项目开发中,在任何情况下其实都是不允许直接在master分支上修改代码的,这是为了保证主分支的稳定。所以在开发新功能是,常常会新建其他分支,供开发时进行迭代使用。

那么首先我们在gitee上新建dev远程分支供我们使用:
在这里插入图片描述
然后分别在linux和windows上更新最新的分支及代码情况

将仓库克隆到本地以后,分支情况如下图,因为我们需要在本地分支上做修改,所以需要在本地新建分支dev,并与远程分支dev建立连接,通过命令git checkout -b dev origin/dev来实现。
在这里插入图片描述

还可以通过命令git branch --set-upstream-to=origin/<远程分支名> <本地分支名>,来将本地分支与远程分支建立连接。

我们还可以通过git branch -vv命令来查看分支的连接情况,通过将本地分支与远程分支建立连接,在使用git push或者git pull命令时,就不用在指定分支了,直接就是两个连接分支之间的推送和拉取操作。


接下来我们在linux系统下,完成新增aaa的操作,并将新增操作推送到远程的仓库中。
在这里插入图片描述

然后再windows系统下,完成新增bbb的操作
在这里插入图片描述
并将新增bbb的操作变更,也推送到远程仓库中
在这里插入图片描述
但如果当我们输入git push命令推送时,由于远程仓库中file.txt文件新增了aaa代码,windows中的仓库并没有感知,所以如果直接推送会产生代码冲突,需要先通过git pull命令将远程仓库中的代码拉到本地,解决冲突以后再进行推送
在这里插入图片描述
在这里插入图片描述

完成远程分支的推送后,我们还需要将远程分支dev合并进远程分支master,才算完成了整个链路。
一般在远程仓库中进行合并操作时,需要在远程仓库中提交Pull Requests合并请求工单,将远程的dev分支合并到master分支上,工单会被审核员或者管理员审批,审批通过才能完成合并,这也是在公司经常用的合并提交代码的方式。
在这里插入图片描述
总结一下,在同一分支下进行多人协作的工作模式通常是这样的:

  • 首先,可以试图用git push 推送自己的修改;
  • 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
  • 如果合并有冲突,则解决冲突,并在本地提交;
  • 没有冲突或者解决掉冲突以后,再用git push推送就能成功;
  • 功能开发完毕,将远程分支mergemaster,然后将临时分支删除

7.2 场景二:多人不同分支

现有场景2:

目标:远程master分支下新增function1function2文件
实现:由开发者1新增function1,由开发者2新增function2
条件:在不同分支下协作完成,各自让某一个功能私有某一个分支

基于以上场景的分支创建,我们有两种方式来实现:
1、在远程仓库基于master创建分支,然后本地拉取该分支进行功能开发

这种方式比较建议,因为基于远程的master分支创建新的分支,得到的是最新的代码

2、基于本地分支创建新分支,完成代码开发后进行git push操作

这种方式需要注意的是,本地的master分支可能不是最新的代码,需要先通过git pull操作,拉取到最新的master分支,然后再基于该分支创建新的分支进行开发。

下边我们用第二种方式来做演示:

首先在linux系统下的仓库,完成开发者1的工作:
在这里插入图片描述
然后在windows系统下,完成开发者2的工作:
在这里插入图片描述
至此我们发现,远程仓库的分支情况符合我们的预期:(新建了两个分支,并新增了对应的功能)
在这里插入图片描述
接下来就可以通过提交PR,来完成分支合并的请求了。

如果将临时分支,合并到master分支上时,产生了冲突,就需要先将master分支合并到临时分支上,在临时分支上解决了冲突,再将临时分支合并到master分支上,该场景就如下图所示【先完成了分支feature-2的合并,然后在合并feature-1分支时,产生了冲突】:
在这里插入图片描述

在这里插入图片描述
本地解决完冲突并push以后,可以接着提交PR来完成合并分支的请求及操作了。

7.3 处理远程已经删除的分支

如果我们已经在远程仓库中删除了某些分支,但是我们通过git branch -a命令还是会看到这些被删除的分支
在这里插入图片描述
在这里插入图片描述
如果想处理掉这些在远程已经删除的分支,可以通过命令git remote show origin来查看这些分支的详情,并会提示你用git remote prune origin来删除这些在远程仓库中已经被删除的分支。
在这里插入图片描述

8.企业开发运用

当今企业,经常使用的软件迭代开发、维护的工具,是DevOps,在Devops的软件开发过程包含计划、编码、构建、测试、预发布、发布、运维、监控,由此可见DevOps的强大。

8.1系统开发环境

在系统开发中,有以下几个环境需要我们必须了解:
1、开发环境:开发环境是开发者们专门用于日常开发的服务器。
2、测试环境:一个程序在测试环境中是不稳定的,该环境是开发环境到生产环境的过渡环境。
3、预发布环境:该环境是为避免因测试环境和线上环境的差异带来的缺陷漏测而设立的一套环境。其配置等基本和生产环境一致,目的是能让我们发正式环境时更有把握!所以预发布环境是产品质量的最后一道防线,因为下一步项目就要上线了,要注意预发布环境服务器不在线上集成服务器范围之内,为单独的一些机器。
4、生产环境:是指正式提供对外服务的线上环境,例如我们目前在移动端或PC端能访问到的APP都是生产环境。

这几个环境也可以说是系统开发的三个重要阶段:开发–》测试–》上线。

在这里插入图片描述

8.2 Git分支管理规范

对于开发人员来说,一般会针对不同的环境来设计不同的分支,例如:

分支名称适用环境
master主分支生产环境
release预发布分支预发布/测试环境
develop开发分支开发环境
feature需求开发分支本地
hotfix紧急修复分支本地

master分支

  • master为主分支,该分支为只读且唯一分支。用于部署到正式发布环境,一般由合并release分支得到。
  • 主分支作为稳定的唯一代码库,任何情况下不允许直接在master分支上修改代码。
  • 产品的功能全部实现以后,最终在master分支对外发布,另外所有在master分支的推送应该打标签(tag)做记录,方便追溯。
  • master分支不可删除

release分支

  • release为预发布分支,基于本次上线所有的feature分支合并到develop分支以后,基于develop分支创建。可以部署到测试或预发布集群。
  • 命名以release/开头,建议命名的规则:release/version_publishtime
  • release分支主要用于提交给测试人员进行功能测试。发布提测阶段,会以release分支代码为基准进行提测。
  • 如果在release分支测试出问题,需要回归验证develop分支看是否存在此问题。
  • release分支属于临时分支,产品上线后可选删除。

develop分支

  • develop为开发分支,基于master分支创建的只读且唯一分支,始终保持最新完成以及bug修复后的代码。可部署到开发环境对应集群。
  • 可根据需求大小程度确定是由feature分支合并,还是直接在上面开发(不建议)。

feature分支

  • feature分支通常为新功能或新特性开发分支,以develop分支为基础创建feature分支
  • 命名以feature/开头,建议的命名规则:feature/user_createtime_feature
  • 新特性或新功能开发完成后,开发人员需要合到develop分支。
  • 一旦该需求发布上线,便将其删除。

hotfix分支

  • hotfix分支为线上bug修复分支或叫补丁分支,主要用于对线上的版本进行bug修复,当线上出现紧急问题需要马上修复时,需要基于master分支创建hotfix分支。
  • 命名以hotfix/开头,建议的命名规则:hotfix/user_createtime_hotfix
  • 当问题修复完成后,需要合并到master分支和develop分支并推送远程。一旦修复上线,便将其删除。

用一张图来总结:
在这里插入图片描述

8.3 DevOps开发实战

【Gitee企业版】
在这里插入图片描述

准备工作

创建项目
在这里插入图片描述
创建仓库
在这里插入图片描述
在这里插入图片描述
添加成员
在这里插入图片描述

实战演练

现有一个订单管理的新需求需要开发,首先可以基于develop分支创建一个feature/ldj_order_20231024分支。
在这里插入图片描述
1.需求在feature/ldj_order_20231024分支开发完毕,这时研发人员可以将代码合并到develop分支,将其部署在开发环境的服务器中,方便开发人员进行测试和调试。
a.开发者在feature分支下发起请求评审(PR)
b.审核员审查代码
c.审查通过,合并分支
d.合并通过,查看结果

2.在develop下开发人员自测通过后,先确定下develop不存在未测试完毕的需求,然后研发人员可基于develop分支创建一个release/xxx分支出来,可交由测试人员进行测试。

3.测试人员测试release通过后(包含测试环境和预发布环境的测试),就可将代码合并入master
4.测试人员在master(正式环境)测试通过后,便可删除feature/xxx分支。

修复bug

修复测试环境bug
develop测试出现了Bug,建议大家直接在feature分支上进行修复。修复后的提测上线流程与新需求加入的流程一致。

修改预发布环境Bug
release测试出现了Bug,首先要回归下develop分支是否同样存在这个问题。如果存在,修复流程与修复测试环境Bug流程一致。
如果不存在,这种可能性较少,大部分时数据兼容问题,环境配置问题等。

修改正式环境Bug
master测试出现了Bug,首先要回归下releasedevelop分支是否同样存在这个问题。
如果存在,修复流程与修复测试环境Bug流程一致。
如果不存在,这种可能性也比较少,大部分是数据兼容问题,环境配置问题等。

紧急修复正式环境Bug
需求在测试环节未测试出Bug,上线运行一段时候出现了Bug,需要紧急修复的。
可基于master创建hotfix/xxx分支,修复完毕后发布到master验证,验证完毕后,将master代码合并到develop分支,同时删除hotfix/xxx分支。

相关文章:

Git简明教程

1.Git的定位 在我们自己开发项目的过程中&#xff0c;经常会遇到这样的情况&#xff0c;为了防止代码丢失&#xff0c;或者新变更的代码影响到原有的代码功能&#xff0c;为了在失误后能恢复到原来的版本&#xff0c;不得不复制出一个副本,比如&#xff1a;“坦克大战1.0”“坦…...

数据结构顺序表(C语言版)

目录 1.实现的接口及其功能2.代码块 1.实现的接口及其功能 //初始化顺序表void initSL(SL* p); //销毁顺序表 void DestorySL(SL* p); //头插 void PushFont(SL* p, SeqListType x); //尾插 void PushBack(SL* p, SeqListType x); //头删 void PopFont(SL* p); //尾删 void Pop…...

新手如何备考学习PMP?

一、PMP学习7步走攻略 1、熟悉考试大纲&#xff1a; PMP考试大纲是备考的基础&#xff0c;考生需要详细熟悉考试大纲&#xff0c;了解各个知识领域的重点和难点。 2、制定学习计划&#xff1a; 根据考试大纲和个人情况&#xff0c;制定学习计划&#xff0c;合理分配学习时间…...

[卷积神经网络]FasterNet论文解析

一、概述 FasterNet是CVPR2023的文章&#xff0c;通过使用全新的部分卷积PConv&#xff0c;更高效的提取空间信息&#xff0c;同时削减冗余计算和内存访问&#xff0c;效果非常明显。相较于DWConv&#xff0c;PConv的速度更快且精度也非常高&#xff0c;识别精度基本等同于大型…...

知识图谱+推荐系统 文献阅读

文献阅读及整理 知识图谱推荐系统 知识图谱 1 基于知识图谱的电商领域智能问答系统研究与实现 [1]蒲海坤. 基于知识图谱的电商领域智能问答系统研究与实现[D].西京学院,2022.DOI:10.27831/d.cnki.gxjxy.2021.000079. 知识点 BIO标记策略进行人工标记,构建了电商领域商品…...

shell_39.Linux参数测试

参数测试 在 shell 脚本中使用命令行参数时要当心。如果运行脚本时没有指定所需的参数&#xff0c;则可能会出问题&#xff1a; $ ./positional1.sh ./positional1.sh: line 5: ((: number < : syntax error: operand expected (error token is "< ") The …...

3D模型格式转换工具HOOPS Exchange助力SIMCON搭建注塑项目

行业&#xff1a;设计与制造 / 注塑成型 / 模拟 挑战&#xff1a;注塑成型商面临着以高效的方式为客户生产零件的挑战。需要大量的试验才能生产出适合的零件&#xff0c;同时模具需要进行多次物理修改&#xff0c;每次修改周期最长需要四个星期&#xff0c;成本高达四到五位数…...

Linux_虚拟内存机制

虚拟内存是如何工作的 我们的程序中使用的所有地址都是虚拟地址&#xff0c;但实际数据是从磁盘空间缓存在物理内存中&#xff0c;读的还是内存中的数据&#xff0c;所以每次CPU的访存操作都会先将虚拟内存交给CPU中的MMU硬件&#xff0c;利用存在主存&#xff08;实际也可能在…...

淘宝官方开放平台API接口获得店铺的所有商品、商品id、商品标题、销量参数调用示例

在电商平台中&#xff0c;获取店铺所有商品是一个非常常见的需求。这个功能允许用户一次性获取指定店铺中的所有商品信息&#xff0c;方便用户对店铺的商品进行浏览和筛选。下面将对获取店铺所有商品接口的功能进行介绍。 获取全部商品信息&#xff1a;通过调用获取店铺所有商…...

Java Spring 通过 AOP 实现方法参数的重新赋值、修改方法参数的取值

AOP 依赖 我创建的项目项目为 SpringBoot 项目 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.3</version></parent><dependency><groupId…...

Real3D FlipBook jQuery Plugin 3.41 Crack

Real3D FlipBook 和 PDF 查看器 jQuery 插件 - CodeCanyon 待售物品 实时预览 截图 视频预览 Real3D Flipbook jQuery 插件 - 1 Real3D Flipbook jQuery 插件 - 2 Real3D Flipbook jQuery 插件 - 3 新功能 – REAL3D FLIPBOOK JQUERY 插件的 PDF 到图像转换器 一款用于将…...

Pytorch:model.train()和model.eval()用法和区别,以及model.eval()和torch.no_grad()的区别

1 model.train() 和 model.eval()用法和区别 1.1 model.train() model.train()的作用是启用 Batch Normalization 和 Dropout。 如果模型中有BN层(Batch Normalization&#xff09;和Dropout&#xff0c;需要在训练时添加model.train()。model.train()是保证BN层能够用到每一…...

Linux CentOS 8(firewalld的配置与管理)

Linux CentOS 8&#xff08;firewalld的配置与管理&#xff09; 目录 一、firewalld 简介二、firewalld 工作概念1、预定义区域&#xff08;管理员可以自定义修改&#xff09;2、预定义服务 三、firewalld 配置方法1、通过firewall-cmd配置2、通过firewall图形界面配置 四、配置…...

C复习-指针

参考&#xff1a; 里科《C和指针》 指针存储的是一个地址&#xff0c;实际就是一个值。 如果像下面一样对未初始化的指针进行赋值&#xff0c;如果a的初始值是非法地址&#xff0c;那么会报错。UNIX会提示段错误segmentation violation&#xff0c;或内存错误memory fault&…...

Runnable和Thread的区别,以及如何调用start()方法

Runnable和Thread都是Java多线程编程中的核心概念&#xff0c;它们之间存在以下主要差异&#xff1a; Runnable是一个接口&#xff0c;而Thread是一个类。这意味着我们可以通过实现Runnable接口来创建线程&#xff0c;或者直接继承Thread类并重写其方法。Runnable只包含一个ru…...

云音乐Android Cronet接入实践

背景 网易云音乐产品线终端类型广泛&#xff0c;除了移动端&#xff08;IOS/安卓&#xff09;之外&#xff0c;还有PC、MAC、Iot多终端等等。移动端由于上线时间早&#xff0c;用户基数大&#xff0c;沉淀了一些端侧相对比较稳定的网络策略和网络基础能力。然而由于各端在基础…...

Linux dup和dup2

Linux dup和dup2函数&#xff0c;他们有什么区别&#xff0c;什么场景下会用到&#xff0c;使用它们有什么注意事项 dup和dup2都是Linux系统中的系统调用&#xff0c;用于复制文件描述符。它们的主要区别在于如何指定新的文件描述符以及处理新文件描述符的方式。 dup函数 #i…...

Spring Boot实战 | 如何整合高性能数据库连接池HikariCP

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…...

Spring依赖注入

依赖注入底层原理流程图&#xff1a; https://www.processon.com/view/link/5f899fa5f346fb06e1d8f570 Spring中有两种依赖注入的方式 首先分两种&#xff1a; 手动注入自动注入 手动注入 在XML中定义Bean时&#xff0c;就是手动注入&#xff0c;因为是程序员手动给某个属…...

Linux下Jenkins自动化部署SpringBoot应用

Linux下Jenkins自动化部署SpringBoot应用 1、 Jenkins介绍 官方网址&#xff1a;https://www.jenkins.io/ 2、安装Jenkins 2.1 centos下命令行安装 访问官方&#xff0c;点击文档&#xff1a; 点击 Installing Jenkins&#xff1a; 点击 Linux&#xff1a; 选择 Red Hat/…...

vite ts 配置使用@ 允许js

1.vite.config.ts 配置 import { defineConfig } from vite import vue from vitejs/plugin-vue import { fileURLToPath, URL } from node:url import setup_extend from vite-plugin-vue-setup-extend// https://vite.dev/config/ export default defineConfig({plugins: …...

Spring Cloud Alibaba Seata安装+微服务实战

目录 介绍核心功能三层核心架构安装微服务实战创建三个业务数据库编写库存和账户两个Feign接口订单微服务 seata-order-service9701库存微服务 seata-store-service9702账户微服务 seata-account-service9703测试结果 总结 介绍 Spring Cloud Alibaba Seata 是一款开源的分布式…...

Flask与Celery 项目应用(shared_task使用)

目录 1. 项目概述主要功能技术栈 2. 项目结构3. 环境设置创建虚拟环境并安装依赖主要依赖 4. 应用配置Flask应用初始化 (__init__.py)Celery应用初始化 (make_celery.py) 5. 定义Celery任务 (tasks.py)任务说明 6. 创建API端点 (views.py)API端点说明 7. 前端界面 (index.html)…...

AI 时代下语音与视频伪造的网络安全危机

引言 在人工智能技术的推动下&#xff0c;语音合成、视频生成等技术取得了突破性进展&#xff0c;Deepfake、AI 语音克隆等工具让语音和视频伪造变得愈发简单且逼真。这些技术在娱乐、影视等领域带来便利的同时&#xff0c;也被不法分子利用&#xff0c;引发了一系列网络安全问…...

Vue 3 Teleport 实战:优雅实现模态框、通知和全局组件

Vue 3 Teleport&#xff1a;突破 DOM 层级限制的组件渲染利器 在 Vue 应用开发中&#xff0c;组件通常与其模板的 DOM 结构紧密耦合。但当处理模态框&#xff08;Modal&#xff09;、通知&#xff08;Toast&#xff09;或全局 Loading 指示器时&#xff0c;这种耦合会成为障碍…...

鼠标的拖动效果

1、变量的设置 let isDragging false; let startX; let startY&#xff1b; let endX; let endY; let box null;isDragging : 表示是否推拽startX、startY&#xff1a;表示起始坐标&#xff0c;相对于元素endX、endY&#xff1a;表示结束坐标&#xff0c;相对于元素box&…...

行为设计模式之Iterator(迭代器)

行为设计模式之Iterator&#xff08;迭代器&#xff09; 摘要&#xff1a; 迭代器模式(Iterator)是一种行为设计模式&#xff0c;它提供顺序访问聚合对象元素的方法&#xff0c;同时不暴露内部结构。该模式由迭代器接口(Iterator)、具体迭代器(ConcreteIterator)、聚合接口(Ag…...

MySql读写分离部署(一主一从,双主双从,Mycat)

参考资料: 参考视频 参考博客 视频参考资料及安装包: https://pan.baidu.com/s/1xT_WokN_xlRv0h06b6F3yg 提取码: aag3 Mysql主从复制部署指南(一主一从) NotePad++编辑Linux服务器文档 Mysql高版本(8.0及以后)Linux安装 Mysql分库分表(基于Mycat)的基本部署 …...

网络编程(TCP编程)

思维导图 1.基础流程 流程图中是TCP连接的基础步骤&#xff0c;其他操作都是在此基础上进行添加修改。 2.函数接口 2.1 创建套接字&#xff08;socket&#xff09; int socket(int domain, int type, int protocol); 头文件&#xff1a;#include <sys/types.h> …...

LLMs 系列科普文(6)

截止到目前&#xff0c;我们从模型预训练阶段的数据准备讲起&#xff0c;谈到了 Tokenizer、模型的结构、模型的训练&#xff0c;基础模型、预训练阶段、后训练阶段等&#xff0c;这里存在大量的术语或名词&#xff0c;也有一些奇奇怪怪或者说是看起来乱七八糟的内容。这期间跳…...