Git学习(二)远程操作:理解分布式版本控制系统、远程操作【远程仓库、新建远程仓库、克隆远程仓库、向远程仓库推送、拉取远程仓库、配置Git】、标签管理、多人协作场景、企业级开发模型、企业级项目管理实战

 接上次博客:Git学习(一)基于本地操作:Git初识、Git安装(Linux-ubuntu)、Git 基本操作、分支管理-CSDN博客

目录

远程操作

理解分布式版本控制系统

远程仓库

新建远程仓库

克隆远程仓库

向远程仓库推送

拉取远程仓库

配置 Git

忽略特殊文件

​编辑给命令配置别名

标签管理

理解标签

创建标签

操作标签

多人协作

多人协作一

多人协作二

远程分支删除后,本地 git branch -a 依然能看到的解决办法

企业级开发模型

系统开发环境

Git 分支设计规范

企业级项目管理实战

开发场景-基于git flow模型的实践

新需求加入

修复测试环境 Bug

修改预发布环境 Bug

修改正式环境 Bug

紧急修复正式环境 Bug

拓展阅读

其他DevOps研发平台

拓展实践


远程操作

理解分布式版本控制系统

我上一篇博客中所说的所有内容(工作区,暂存区,版本库等等)都是在本地!也就是在我们的笔记本或者计算机上。

而且我之前只把 Git 的完整定义说了一半。

我们的 Git 其实是分布式版本控制系统。

理解 Git 作为分布式版本控制系统的重要性是理解整个工作流程的关键。在传统的集中式版本控制系统(如SVN)中,所有的文件和版本都存储在中央服务器上。开发者需要不断地与中央服务器通信,才能进行版本控制操作。

然而,在分布式版本控制系统中,每个开发者都拥有一个完整的版本库,其中包含了项目的完整历史记录。这意味着,即使没有网络连接,开发者也可以进行版本控制操作,因为他们的本地仓库已经包含了项目的全部历史记录和文件变更记录。Git作为分布式版本控制系统,使得每个人都具有独立的版本库,而不是依赖于中央服务器。这种方式使得开发者在工作时更加自主和独立,不必担心中央服务器的可用性或者网络连接的问题。每个开发者都可以在本地进行版本控制操作,并在需要时与其他开发者进行协作,而不受网络限制的影响。

当多个人共同参与一个项目时,他们可以在各自的本地仓库中进行修改和提交。每个人都可以在本地进行开发,而不会影响到其他人的工作。当需要分享自己的修改或者获取他人的修改时,可以通过推送(push)和拉取(pull)操作来实现。

例如,如果你和你的同事分别修改了同一个文件A,你们可以将自己的修改推送给对方,然后合并彼此的修改,这样就实现了协作开发。

分布式版本控制系统的安全性确实比集中式版本控制系统要高得多。这是因为每个人的电脑上都有完整的版本库,即使某个人的电脑发生了故障,也可以轻松地从其他人那里复制一个版本库进行恢复。

在实际使用分布式版本控制系统时,很少会在两个人之间的电脑上直接进行版本库的推送。这是因为通常情况下,两台电脑可能不在同一个局域网络内,无法直接互相访问。即使在同一个局域网络内,也可能由于网络配置或安全策略的原因而导致无法直接通信。

另外,即使两台电脑在同一个网络下,也可能出现某一方的电脑由于各种原因无法访问或者关闭。例如,可能因为电脑故障、网络故障、电源故障、软件问题或者其他不可预测的情况而导致无法访问或关闭。因此,在这种情况下,直接在两个人之间的电脑上进行版本库的推送并不可行。

为了解决这个问题,通常会有一台电脑充当“中央服务器”的角色,该服务器保持运行状态,并且处于在线状态。其他人可以从这个服务器克隆一个版本库到自己的电脑上,并将自己的修改推送到服务器上。这样,即使某一方的电脑出现问题,也不会影响其他人的工作。但是这个服务器的作用仅仅是为了方便大家交换修改,没有它大家同样可以继续工作,只是交换修改会稍显不便而已。

我们也可以将自己的修改内容推送到中央服务器,这样其他人就可以从中央服务器拉取我们的代码更新。这种方式实现了团队成员之间的协作和代码共享。当我们在本地完成了一些修改并且希望团队其他成员能够看到这些变更时,我们可以将这些修改推送(push)到中央服务器上的共享仓库。其他团队成员可以随时从中央服务器上拉取(pull)最新的代码更新到他们的本地仓库中,这样整个团队都可以保持同步,共同参与项目的开发和维护。

总之,有了这个“中央服务器”的电脑,就不用担心本地出现故障了。即使出现了诸如硬件故障、数据丢失等问题,Git的所有内容都可以从中央服务器进行恢复。这种设计使得分布式版本控制系统更加稳健和安全,减少了单点故障带来的风险。

远程仓库

Git是一种分布式版本控制系统,这意味着同一个Git仓库可以分布到不同的机器上。但是,如何实现这种分布呢?

最初,可能只有一台机器上有一个原始版本库。然后,其他机器可以通过“克隆”这个原始版本库来获取它的副本,而每台机器上的版本库都是一样的,没有主次之分。

或许你会问,至少需要两台机器才能玩远程库,但是我只有一台电脑,怎么办呢?实际上,一台电脑上也可以克隆多个版本库,只要它们不在同一个目录下。不过,在现实生活中,没有人会愚蠢到在一台电脑上搞几个远程库,因为这样做完全没有意义。而且,如果硬盘损坏了,所有库都会受到影响。所以,我也不会告诉你如何在一台电脑上克隆多个仓库。

实际情况往往是这样,找一台电脑充当服务器的角色,每天24小时开机。其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自将自己的提交推送到服务器仓库中,也从服务器仓库中拉取别人的提交。

当然,你完全可以自己搭建一台运行Git的服务器,不过在目前阶段,为了学习Git,先搭建一个服务器可能有点小题大作。幸运的是,有一个叫做GitHub的神奇网站。从名称就可以看出,这个网站提供Git仓库托管服务。所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库。

但是,GitHub 是国外的网站,速度比较慢,我们就采用码云来托管代码。

接下来,我们从零开始,使用一下码云远程仓库。

新建远程仓库

新建远程项目仓库:

填写基本信息:

 

创建成功:

 刚创建的仓库有且只有一个默认的master分支:

首先一眼就能看到的是一些介绍文件,分英文中文两种,它已经把相关模板提供给你了,你可以自定义:

然后我们点进:

你会看到里面有两个文件:

我们先打开第一个文件: 

 这个时候我们先跳转到issues,新建一个issue:

你会发现里面的格式和文件里面一模一样,所以这个文件其实是提供给用户,向仓库的管理员提出问题、进行交流的地方。

再回到刚刚的第二个文件:

这个时候点开:

 

可以看出来这其实是一个给管理员看的合并申请单,任何合并操作都需要管理员同意才可以。

我们之前一直是直接从master上和并相关分支的,但是这其实是一个非常危险的操作。

正确的做法是,如果需要进行分支的合并操作,合并操作必须经过管理员的同意才能执行,通常的做法是通过代码审查(Code Review)来进行。

  1. 创建合并请求(Merge Request)或拉取请求(Pull Request): 开发者将他们的分支提交到主分支或其他需要合并的分支时,会创建一个合并请求。这个请求包含了要合并的代码的详细信息,以及开发者希望将其合并到的目标分支。

  2. 进行代码审查: 管理员或其他团队成员会对合并请求中的代码进行审查。他们会检查代码的质量、可读性、安全性等方面,并提出建议或修改。

  3. 管理员同意合并: 如果审查人员认为代码符合要求,他们会在合并请求上给出批准。这表示管理员同意将该代码合并到目标分支中。

  4. 执行合并操作: 一旦管理员批准了合并请求,开发者可以执行合并操作。这会将分支的更改合并到目标分支中。

这种方式可以确保在进行合并操作之前,经过了代码审查和管理员的同意,从而提高了代码质量和项目的稳定性。

另外,还可以点击跳转到管理页面中的仓库成员管理,码云官方给出了详细的介绍。

仓库成员权限说明 - Gitee.com

我们对码云的简单介绍就暂时停留在这里,如果有不明白的地方可以上网搜搜,或者问一下官方客服。

克隆远程仓库

要将远程仓库克隆或下载到本地,需要使用git clone命令,后跟着远程仓库的链接。远程仓库的链接通常可以在仓库中找到,选择“克隆/下载”获取远程仓库链接:

码云提供给我们几种网络传输协议:

远程仓库的链接通常有两种形式:SSH 协议和 HTTPS 协议。

我们也主要了解这两种形式。

  1. SSH 协议: SSH(Secure Shell)协议是 Git 最常用的数据传输协议之一。它采用了公钥加密和公钥登录机制,这使得它具有很高的实用性和安全性。在使用 SSH 协议时,我们需要将我们的公钥放在远程 Git 服务器上,并由服务器进行管理。这样,我们就可以使用 SSH 协议来安全地传输数据和进行版本控制操作。

  2. HTTPS 协议: HTTPS(Hypertext Transfer Protocol Secure)协议是另一种常用的数据传输协议。与 SSH 协议不同,HTTPS 协议在使用时没有太多的要求。我们可以直接使用 HTTPS 协议来克隆或下载远程仓库的代码。HTTPS 协议提供了简单的访问方式,适用于各种开发环境和需求。

此处我们就先使用HTTPS协议做演示:

在执行Git命令之前,确保我们已经切换回到主目录。这一步非常重要。特别要注意的是,我们绝对不能在任何一个本地仓库目录下执行git clone命令。

git clone命令用于克隆远程仓库到本地,它会创建一个新的目录,并将远程仓库的所有内容复制到该目录中。如果我们在一个已经存在的本地仓库目录下执行git clone命令,Git会尝试将远程仓库克隆到当前目录中,这可能会导致意外覆盖或修改已有的仓库内容,造成不可挽回的损失。

因此,在执行git clone命令之前,务必确认我们已经回到了主目录,这样可以确保我们在一个干净的环境下进行克隆操作,避免意外的文件冲突或数据丢失。

新生成的这个remote-gitcode就是我们的远程仓库。

git remote 命令用于显示远程仓库的信息。这个命令有两种常见的形式:

  1. git remote: 这条命令会列出我们当前仓库中的所有远程仓库的名称。
  2. git remote -v: 这条命令会列出我们当前仓库中的所有远程仓库的名称以及对应的 URL,其中 -v 选项表示 "verbose"(详细)。

  • origin: 这是远程仓库的名称。在 Git 中,通常会给默认的远程仓库一个名字叫做 origin。
  • https://gitee.com/xxx/remote-gitcode.git: 这是远程仓库的 URL。它指定了远程仓库的位置。
  • (fetch): 这是 origin 远程仓库的拉取 URL。当我们使用 git fetch 命令时,Git 会从这个 URL 拉取远程仓库的数据。
  • (push): 这是 origin 远程仓库的推送 URL。当我们使用 git push 命令时,Git 会将本地提交推送到这个 URL 对应的远程仓库中。

接下来我们使用 SSH 的方式:

我们尝试使用 SSH 方式克隆仓库时,由于我们的公钥没有添加到远端库中,服务器拒绝了我们的 clone 链接。

要看我们有没有设置SSH公钥:

为了解决这个问题,我们需要进行以下设置:

首先,我们需要创建 SSH Key。我们可以在用户主目录下查看是否存在 .ssh 目录,如果已经存在并且包含 id_rsa 和 id_rsa.pub 这两个文件,那么我们可以直接进入下一步。如果不存在,我们需要创建 SSH Key。

虽然有这个目录,但是目录下没有包含我们需要的两个文件。所以我们手动创建:

ssh-keygen -t rsa -C "your email adress"

注意这里的邮箱地址需要和码云上保持一致:

同理,可以在设置里面找到邮箱管理查看:

如果你还没有进行配置,就现在立刻马上设置一个。

然后我们一路回车即可,不需要填写任何东西。

此时就相当于把我们的公钥和私钥都创建好了。

成功创建后,我们可以在用户主目录下找到 .ssh 目录,里面包含了 id_rsa 和 id_rsa.pub 这两个文件。其中,id_rsa 是私钥,不能泄露出去;id_rsa.pub 是公钥,可以安全地分享给他人。

然后我们需要拿到公钥,配置到码云平台上:

这些内容一字不落的复制下来,粘贴到远程仓库中。我们可以点击远程仓库的 SSH 公钥选项,并进行相应设置。

确认设置后,我们需要进行身份验证,输入账号密码即可完成认证。

最后,我们再重新克隆一下即可:

向远程仓库推送

推送是软件开发中将本地仓库的提交内容同步到远程仓库的重要操作。在开发过程中,我们通常在本地进行代码修改、添加新功能等工作,这些修改会在本地的工作区中进行。一旦完成了某个功能的开发或对代码进行了修改,我们会将这些修改添加到暂存区,然后使用 git commit 命令将其提交到本地仓库的相应分支,通常是 master 分支。

然而,这时候远程仓库并不会自动更新,其他开发者也无法看到我们的修改。为了将本地仓库的修改同步到远程仓库,我们需要进行一次推送操作。推送操作的目的是将本地仓库中的提交内容推送到远程仓库的相应分支,使得其他开发者能够获取并查看我们的修改。

需要注意的是,推送操作是在分支和分支之间进行的。也就是说,我们可以将本地的某个分支(例如 master 分支)的提交内容推送到远程仓库中的对应分支。这样其他开发者就可以获取并使用我们的最新代码了。

提交代码时需要注意确保本地 Git 的全局配置中的用户名和邮箱与 Gitee 上配置的用户名和邮箱一致。如果之前已经设置过全局的用户名和邮箱,那么这两项配置必须与 Gitee 上的配置相匹配,否则会导致提交错误。如果你之前从未设置过全局的用户名和邮箱,那么在首次提交时也会遇到错误。

用户名对应着码云上个人主页中@部分后面的内容:

邮箱还是从刚刚的设置里面看。

git config --global user.name "Your Name"
git config --global user.email "your_email@example.com"

本地已经 clone 成功远程仓库后,我们便可以向仓库中提交内容:

到这里我们已经将内容提交至本地仓库中,如何将本地仓库的内容推送⾄远程仓库呢?
使用 git push 命令可以将本地仓库的内容推送到远程仓库。其命令格式如下:

git push <远程主机名> <本地分支名>:<远程分支名>

如果本地分支名与远程分支名相同,则可以省略冒号,简化为:

git push <远程主机名> <本地分支名>

在这里,我们想要将本地的 master 分支推送到 origin 主机的 master 分支,可以执行以下命令:

git push origin master:master
# 或者简化为:
git push origin master

注意,这个地方,如果你使用的是 HTTPS 协议,那么在执行 git push 命令时通常需要输入用户名和密码。这是因为 HTTPS 协议下的通信是通过用户名和密码进行身份验证的。

相反,如果你使用的是 SSH 协议,通常不需要输入用户名和密码。这是因为 SSH 协议使用公钥和私钥进行身份验证,而不需要密码。因此,当你使用 SSH 协议时,Git 会自动使用你的 SSH 密钥进行认证,从而避免了输入用户名和密码的步骤。

推送成功!

 那么我们为什么可以push成功呢?

推送成功的原因通常有以下几点:

  1. Push 权限: 我们之前看到过,我们是有 push 权限的,这意味着我们有权限将本地的更改推送到远程仓库。如果没有正确的权限,那么即使我们尝试推送更改,也会被拒绝。

  2. SSH 认证: 如果使用的是 SSH 协议,Git 会使用的 SSH 密钥进行身份验证。只有拥有正确的 SSH 密钥,才能够推送更改。

  3. HTTP输入用户名和密码进行验证。

  4. 克隆时的链接建立: 在克隆远程仓库时,Git 会记录远程仓库的 URL,以及我们的身份验证方式(例如 HTTPS 或 SSH)。另外,如果我们使用 SSH 克隆了远程仓库,并且已经正确配置了 SSH 密钥,那么在推送更改时,Git 会自动使用 SSH 密钥进行身份验证,从而避免了需要输入用户名和密码的情况。

总的来说,推送成功的关键是拥有正确的权限和身份验证方式,并且在克隆远程仓库时建立了正确的链接。

拉取远程仓库

此处为了演示方便,我们不使用两个服务器,而是直接在 gitee 上点击 file.txt 文件并在线修改它:

但是现实生活里面,可千万不要在远程仓库进行修改!!!

此时,远程仓库已经领先于本地仓库一个版本。为了确保本地仓库与远程仓库保持同步,我们需要更新本地代码并合并远程仓库的最新版本。为此,Git 提供了 git pull 命令,这个命令的作用是从远程仓库获取最新的代码并将其合并到本地仓库中。其格式如下:

git pull <远程主机名> <远程分支名>:<本地分支名>
# 或者如果远程分支与当前分支同名,可以简写为:
git pull <远程主机名> <远程分支名>

git pull 命令实际上是将 git fetch 和 git merge 两个命令合并在一起的组合操作。首先,它会从远程仓库获取最新的提交信息,这一步使用了 git fetch 命令,它会将远程仓库的最新提交下载到本地,但不会自动合并到当前分支。然后,git pull 会自动调用 git merge 命令,将从远程仓库获取的提交信息合并到当前所在的分支上。这样,git pull 实现了一次从远程仓库获取最新代码并将其合并到本地分支的操作。

配置 Git

忽略特殊文件

在日常开发中,我们经常会遇到一些文件,比如配置文件、日志文件等,它们包含了一些敏感信息或者是临时性的文件,我们不希望将它们提交到远程仓库中。这时,我们就可以使用 Git 的 .gitignore 文件来告诉 Git 哪些文件应该被忽略掉。

.gitignore 文件是一个普通的文本文件,通常位于 Git 仓库的根目录下。在这个文件中,我们可以列出需要忽略的文件或者文件夹的名称、路径或者匹配规则。当我们执行 git add 命令将文件添加到暂存区时,Git 会检查 .gitignore 文件中列出的文件,并自动忽略它们。

在Gitee上创建仓库时,系统会为我们生成一个.gitignore文件,但这需要我们在创建仓库时主动勾选相应选项。通常,在创建新仓库的页面中,会有一个选项来选择是否生成.gitignore文件。如果我们希望在仓库中使用.gitignore文件,只需勾选该选项即可。

生成的.gitignore文件会包含一些常见的忽略规则,例如操作系统自动生成的临时文件、编译生成的文件、日志文件等。这样可以帮助我们避免将不必要的文件提交到版本控制中,保持代码仓库的整洁和可维护性。

当然,我们也可以根据实际需求对.gitignore文件进行修改和定制,添加或删除特定的忽略规则,以满足项目的具体需求。通过合理使用.gitignore文件,可以使版本控制系统更加高效地管理项目文件,提升开发效率。

即使在创建仓库时我们没有勾选自动生成.gitignore文件的选项,我们仍然可以在工作区手动创建一个.gitignore文件。通过在工作区的根目录下创建.gitignore文件,并在其中添加需要忽略的文件名或模式,我们也能实现对特定文件的忽略。

无论是通过自动生成还是手动创建.gitignore文件,最终目的都是为了让Git在进行版本控制时忽略某些文件或目录,从而保持代码仓库的整洁和可维护性。因此,无论选择哪种方式,最终都可以得到一个完整的.gitignore文件来管理项目中的忽略规则。

我们已经将.gitignore文件添加到了Git的暂存区,并且还添加了一个名为b.ini的配置文件。

但是现在,我们需要确保b.ini文件不会被意外提交,因为它本应该被.gitignore文件忽略。

git add -f b.ini命令将b.ini文件强制添加到Git的暂存区,即使它在.gitignore文件中被设置为忽略。通常情况下,Git会忽略.gitignore中列出的文件,但使用-f选项可以覆盖这个行为,强制将文件添加到暂存区。

这种做法应该谨慎使用,因为它会导致忽略规则失效,可能会意外地将不应该提交的文件添加到版本控制中。

如果我们希望保持.gitignore规则的完整性,同时又需要将某些文件纳入版本控制,可以添加例外规则。在.gitignore文件中,我们可以使用感叹号(!)来添加例外规则,以排除特定文件。

另外,还有一个命令——git check-ignore命令。

git check-ignore命令用于检查文件是否被.gitignore规则忽略。当我们想要确定某个文件是否受.gitignore规则的影响时,可以使用这个命令来检查。

git check-ignore [options] <path>

其中,<path>表示要检查的文件路径。

该命令会检查指定路径的文件是否被.gitignore文件中的规则所忽略,如果文件被忽略,则会输出忽略规则所在的文件路径和行号。如果文件没有被忽略,则不会输出任何内容。

这个命令可以帮助我们确认.gitignore规则是否正确生效,以及某个文件是否被正确地排除在版本控制之外。

给命令配置别名

在我们使用 Git 期间,有些命令敲的时候着实让人心累,幸运的是,git支持对命令进行简化!

Git 提供了一些简化命令的方式,使得在使用过程中更加方便快捷。其中一种方式是使用 Git 的命令别名。

通过设置 Git 的命令别名,我们可以将繁长的命令转换为更简洁的形式,提高命令输入的效率。比如,我们可以将常用的命令设置为简短的别名,从而减少输入量和记忆负担。

例如,将 git status 命令简化为 git st,将 git commit 命令简化为 git ci,将 git branch 命令简化为 git br,等等。这样,当我们需要执行这些操作时,只需要输入简短的别名即可完成。

设置的 Git 命令别名可以随时删除或修改。如果要删除一个名为 ci 的别名,可以使用以下命令:

git config --unset alias.ci

当然,我们也可以选择手动编辑 Git 配置文件,找到相应的别名并删除它。

需要注意的是,删除别名后,我们之前设置的简化命令将不再生效,会恢复到默认的 Git 命令行形式。

标签管理

理解标签

标签(tag)在 Git 中相当于给某次提交(commit)打上一个易于记忆和有意义的标识,类似于为该提交起了一个别名。通常情况下,标签被用来标记项目的重要节点,比如版本发布或者里程碑。与使用提交的哈希值作为引用不同,标签提供了更加人性化和易于理解的方式来引用和识别特定的提交。

标签的引入使得开发者可以通过使用易于记忆的名称来快速定位到特定的提交,而不必记住对应的哈希值。这对于项目的版本控制和管理来说尤为重要,特别是在需要频繁地回溯到历史版本或者发布新版本时。

例如,在项目发布某个版本的时候,我们可以给最后一次提交打上一个标签,比如 v1.0,用来标识里程碑的意义。这样做的好处是,相较于难以记忆的提交 ID,标签提供了一种更加直观、易于理解和记忆的方式来标识特定的版本。

整理一下,标签的使用有以下几个优点和作用:

  1. 易于记忆和定位: 标签提供了一个容易记住的名称,让开发人员能够更轻松地回溯到特定的版本。使用标签命名版本号或发布号,可以更方便地定位到项目的重要里程碑。

  2. 版本控制和发布管理: 标签在软件开发中常用于版本控制和发布管理。通过为发布版本打上标签,可以清晰地标识出每个版本的内容和变化,便于团队协作和版本追踪。

  3. 稳定性和可靠性: 标签通常用于标识稳定版本或重要的里程碑版本,这些版本经过了充分测试和验证,具有较高的稳定性和可靠性。开发人员可以通过使用标签来选择性地回退到这些稳定版本,从而保证项目的稳定性和可靠性。

总之,标签在 Git 中扮演着重要的角色,通过为特定的提交打上有意义的标识,可以提高项目的版本控制效率,简化开发人员的工作流程,同时也为团队协作和项目管理提供了便利。

创建标签

在 Git 中打标签非常简单。首先,我们需要切换到需要打标签的分支上。这可以通过使用 git checkout 命令完成,确保我们位于正确的分支上进行标记操作。

接着,我们可以使用 git tag [name] 命令来创建一个新的标签。这个命令会在当前的 HEAD 提交上创建一个标签,用于标识当前的状态或者版本。

如果想要查看所有已经创建的标签,我们可以使用 git tag 命令。这会列出所有已经存在的标签,供我们参考和管理。

需要注意的是,标签并不是按照时间顺序列出的,而是按照字母顺序排列的,这一点需要特别注意。

通过tree命令也可以看到相应的标签:

通过上述信息,我们可以得到以下结论:

  1. 在 .git/refs/tags 目录下存储了所有的标签信息。
  2. 每个标签对应着一个唯一的标识符,这个标识符是该标签所指向的提交的哈希值。
  3. 我们可以通过查看标签文件的内容,获取到该标签所指向的提交的哈希值。
  4. 标签通常用于标识项目的重要版本或里程碑,方便开发者追溯历史和管理版本。
  5. 标签可以与特定的提交关联,也可以独立存在。
  6. 在 git log 输出中,标签通常会显示在提交信息的一行,以及在提交的哈希值之前的位置,方便快速识别。

如果我们想在指定的提交上打标签,可以先找到该提交的 commit ID,然后使用 git tag 命令来创建标签。这样就能够确保标签被打在我们希望的提交上。

此外,我们还可以创建带有说明的标签。通过使用 -a 选项来指定标签名,并使用 -m 选项来指定标签的说明文字。这样可以为标签提供更加详细的信息,方便他人理解和管理。

如果是对最近的一次提交打标签的话,写完说明文字直接回车即可。如果需要指定某次提交,就需要加上对应的commit ID。

可以使用 git show [tagname] 命令来查看特定标签的信息。这个命令将显示与指定标签相关联的提交信息,包括作者、提交时间、提交内容等。此外,它还会显示标签指向的提交的详细变更内容。通过这个命令,我们可以快速了解特定标签所代表的版本的详细信息。

最后,在打完标签之后,我们可以使用 tree .git/ 命令来查看本地库的变化情况。这会显示出 Git 存储库中目录和文件的结构,帮助我们更好地理解和掌握整个项目的状态。

操作标签

如果标签打错了,也可以删除:

当我们在本地创建标签时,它们只存在于本地存储库中,不会自动同步到远程存储库。因此,如果我们不小心创建了错误的标签,可以安全地在本地删除。

如果要将某个标签推送到远程仓库,可以使用命令 git push origin <tagname>。这会将指定的标签推送到远程仓库。

此时,我们可以前往远程仓库(如码云)查看,确认标签已经成功更新,这样就可以确保同步了标签的变更。

当然,如果我们本地有很多标签需要一次性全部推送到远程仓库,也可以使用相应的命令完成。

 

如果标签已经推送到远程仓库,要删除远程标签就稍微麻烦一点。

首先,我们需要从本地仓库中删除标签,然后再从远程仓库中删除。删除远程标签的命令格式如下:

在完成删除操作后,我们可以再次前往码云等远程仓库查看,以确认标签已经成功删除。

其实也可以使用码云提供的功能,你可以看到右方有删除的按钮:

多人协作

目前,我们已经完成了以下工作:

  • 掌握了 Git 的基本操作,包括创建仓库、提交更改、创建分支、版本回退、解决冲突等。
  • 成功申请了码云账号,并将远程仓库的信息克隆到本地,学会了推送和拉取代码。

现在,我们要着手进行最重要的一项任务:实现多人协作开发!为了做好这件事情,我们需要进行一些准备工作。

多人协作一

首先,我们需要确保已经将项目克隆到了指定的目录(这一步之前已经完成了)。

其次,我们需要明确一点。这次多人协作开发项目并不是在master分支上进行开发,因为我们需要保证master分支的稳定性,所以我们必须新建一个分支。这个分支在远程创建或是在本地创建其实都可以,此处我们就选择远程创建:

 

此时我们可以查看一下远程有哪些分支:

当我们在本地使用 git branch 命令查看分支时,只会显示本地仓库中的分支情况,而当我们使用 git branch -r 命令时,会显示远程仓库中的分支情况。

在我们的输出中:

  • git branch 显示只有一个分支 master,这是本地仓库中的分支。
  • git branch -r 显示了两个分支:
    • origin/HEAD -> origin/master:这表示远程仓库的默认分支是 master。
    • origin/master:这是远程仓库中的 master 分支。

在 Git 中,origin 是默认的远程仓库的名称,用于指代远程仓库。origin/HEAD 实际上是一个指向 origin/master 的符号引用(symbolic reference),它指示了远程仓库的默认分支是 master。

因此,尽管显示了两个 master,但实际上它们都是指向远程仓库的同一个分支 master。一个是远程仓库中的 master 分支,另一个是远程仓库的默认分支 master。而本地仓库中只有一个 master 分支。

而这个时候在我们的本地,不论是使用 git branch 查看本地分支,还是使用 git branch -r 查看远程分支,都是看不到有一个dev分支的。

成功创建的远程分支可以通过 Git 拉取到本地来,以实现完成本地开发工作。

此时进行pull拉取操作:

git branch -a 命令代表既显示远程分支,又显示本地分支。 

拉取后可以看到远程的 dev 分支,然后切换到 dev 分支供我们进行本地开发。需要说明的是,我们切换到的是本地的 dev 分支,根据示例中的操作,会将本地分支与远程分支进行关联。 

你可能会有点疑惑:我们之前push的时候可是这样写的:git push origin master。

指定了具体的分支。但是为什么这里我们可以直接简简单单写一个“git pull”?

  • 建立连接的标准:在Git中,建立连接指的是与远程仓库进行通信的能力。当我们克隆一个仓库或者添加一个远程仓库时,Git会自动为本地仓库与远程仓库建立连接。
  • 何时需要指定分支名称:通常情况下,当我们执行git push或git pull命令时,Git会根据当前所在的分支自动确定要操作的远程分支。但是,如果我们想要推送或拉取的分支与当前分支不同,或者我们想要操作的分支与远程分支名称不同,那么我们就需要显式地指定分支名称。
  • 为什么有时候可以直接只写git pull:当我们在本地仓库中执行git pull命令时,Git会首先确定我们当前所在的分支。然后,它会自动查找与当前分支关联的远程分支,并从该远程分支获取更新。因此,在这种情况下,我们不需要显式指定远程分支名称,Git会根据当前分支自动找到对应的远程分支。

也就是说,Git会尽可能地根据上下文自动推断我们的意图,以简化操作。但如果我们想要操作的分支与当前分支不同,或者我们想要操作的远程分支与默认分支不同,那么我们就需要显式地指定分支名称。

我们需要在 Windows 环境下,再次克隆同一个项目仓库,以模拟另一个小伙伴和我们一起协作开发:

SHIFT+右键:

克隆成功!

需要注意的是,我们在这里模拟了两个用户,实际开发中,每个用户都应该拥有自己的码云/GitHub账号。如果要进行多人协同开发,必须将用户添加为开发者,以便他们有权限提交代码。

在邀请用户后,三种添加方式仍选其一即可:

到此,我们实际上得到了两个用户,分别在 Linux 和 Windows 上对同一项目进行协作开发,我们的准备工作到此为止。

目前,我们的仓库中只有一个 master 主分支。然而,在实际项目开发中,直接在 master 分支上修改代码是不允许的,这样做是为了保证主分支的稳定性。因此,在开发新功能时,常常会新建其他分支进行开发和迭代。

接下来,让我们在码云上新建一个 dev 远程分支供我们使用:

  • git checkout -b dev origin/dev: 这个命令创建了一个名为 dev 的新分支,并将其设置为跟踪远程仓库的 dev 分支。
  • Branch 'dev' set up to track remote branch 'dev' from 'origin'.: 这个消息表示成功将本地的 dev 分支设置为跟踪远程仓库的 dev 分支。
  • git branch -vv: 这个命令显示了本地分支的详细信息,包括每个分支所对应的最新的 commit,以及它们与远程分支的关联情况。 

现在,让我们和另一个开发者都拉取一次远程仓库,并观察结果:

对于我们要操作的用户:

让我们来查看码云上当前仓库的状态:

到此,我们已经将代码成功推送到码云。但如果你的小伙伴也要和你协同开发,并且也要对 file.txt 文件作修改,然后试图推送,例如: 

对于另一个开发者要操作的用户:

现在,另一个小伙伴可以在 dev 分支上完成开发。

首先,在 dev 分支上进行一次开发,并将其推送到远程。例如:

此时由于checkout命令后面没有指定相关分支名称,也就没有建立连接。

 Git 提示说当前分支没有跟踪信息,需要手动设置。

  • git branch --set-upstream-to=origin/dev dev: 这个命令设置了当前的 dev 分支跟踪远程的 dev 分支,意味着在执行 git pull 或者 git push 时,Git 会知道从哪个远程分支拉取或推送更改。
  • git branch -vv: 这个命令再次显示了所有本地分支的详细信息,现在可以看到 dev 分支已经与远程的 dev 分支关联,并且标记为 behind 1,表示本地分支落后于远程分支一个提交。

我们直接使用记事本进行相关修改:

 

 

然而,推送失败了,因为远程分支拒绝了推送。

  • 错误消息说明了拒绝的原因:当前分支落后于远程分支,存在冲突。推送被拒绝是为了防止远程仓库的历史记录被不正确地修改。
  • 错误提示说明了解决这个问题的方法:首先需要将本地分支与远程分支合并,然后再次尝试推送。具体来说,推荐先执行 git pull 命令,拉取远程分支的更新到本地,并解决可能产生的冲突,然后再执行 git push 命令。
  • 错误提示还提到了关于 fast-forward 的说明:这是一个 Git 推送时常见的概念,指的是将本地的提交应用到远程分支时,远程分支可以直接快进到本地分支所在的提交,而不需要额外的合并操作。由于本地分支落后于远程分支,因此这次推送无法进行 fast-forward,需要先合并更新。

所以这个问题其实是因为我们的小伙伴的最新提交和我们推送的提交有冲突导致端。

解决办法很简单,Git已经提醒我们,先用 git pull 将最新提交从 origin/dev 抓下来,然后,在本地进行合并并解决冲突,再推送。操作如下:

解决冲突后,重新推送:

这时,我们可以在码云上看到我们的新提交了!

现在,两名开发者已经可以开始进行协同开发了,不断地进行 git pull/add/commit/push 操作,遇到冲突时,使用我们之前讲过的冲突处理方法解决冲突。

对于我们,也就是开发者一来说,要想查看同事的代码,只需要拉取一下即可:

最后,不要忘记,虽然我们是在分支上进行多人协作开发,但最终的目的是将开发后的代码合并到 master 分支上,让我们的项目运行最新的代码。

我们之前说过,对于merge操作有两种选择,第一种是对于本地而言,使用本地master分支merge一下dev分支,然后再将本地的master分支push到远端;第二种方式是提一个PR合并申请单,管理员同意后即可进行merge操作,这样就可以直接在远程将dev分支merge进master分支。

我们这里先看看第二种方式,这其实是最推荐的做法:

接下来创建 Pull Request 即可,审查员通过之后我们的合并操作就完成了。

我们再使用第一种方式,多熟悉一下命令操作:

我们选择开发者一作为主要操作人员:

  1. git pull:在团队协作中,不同的成员可能在同一代码库上进行工作。为了确保我们的工作基于最新的代码版本,我们需要从远程仓库拉取最新的更改。这可以通过git pull命令完成。它将从远程仓库获取最新的代码并将其合并到我们当前的工作分支中,使我们能够基于最新的代码进行工作。
  2. git checkout master:在大多数工作流程中,master分支被视为稳定的主分支,用于部署到生产环境。通过切换到master分支,我们确保了我们将基于最新的稳定代码进行工作。这有助于确保我们的更改是基于已经通过测试和审核的代码,以减少潜在的错误和问题。
  3. git pull (on master branch):在切换到master分支后,其他团队成员可能已经推送了新的更改。为了确保我们的master分支是最新的,我们再次运行git pull命令。这会从远程仓库获取任何可能的新更改并将其合并到我们的master分支中,以保持我们的本地分支与远程分支同步。
  4. git checkout dev:开发新功能通常在专门的开发分支(比如dev分支)上进行。在这个分支上,开发人员可以自由地进行实验、添加新功能和修改代码,而不会直接影响到主要的生产环境。通过切换到dev分支,我们可以专注于开发和测试新功能,而不必担心影响到主分支的稳定性。
  5. git merge master (on dev branch):由于master分支可能包含了其他团队成员的新更改,为了确保dev分支也包含了最新的稳定更改,我们需要将master分支上的任何新更改合并到dev分支中,以保持两个分支之间的同步。
  6. git checkout master:在将我们的更改合并到master分支之前,我们需要切换回master分支,因为合并操作必须在目标分支上进行。
  7. git merge dev (on master branch):一旦切换到master分支,我们将dev分支上的更改合并到master分支中。这样做是为了将新功能或修复的代码整合到主分支中,以便将来部署到生产环境。
  8. git push:最后,一旦我们在本地完成了合并并确认没有问题,我们可以将我们的更改推送到远程仓库。这样其他团队成员就可以获取我们的更改,并确保所有人都在同一个代码基础上工作。

至于先 dev : merge master,然后再 master: merge dev 的理由我们之前已经详细解答过了,这里再做一次解说:

在将开发分支合并到主分支之前,可能需要进行代码审查和测试以避免冲突。在dev分支上合并master分支,然后再将dev分支合并回master分支,可以确保在将新功能或修复的代码部署到生产环境之前,已经经过了充分的审查和测试。将master分支合并到dev分支并解决任何可能出现的冲突后,dev分支将会保持最新且干净。这样做可以减少在dev分支上开发时可能出现的问题,因为dev分支已经包含了最新的稳定更改。 

在整个过程中,每一步都是为了确保团队成员能够在最新的代码基础上工作,并最终将他们的工作整合到主分支中。同时,通过在本地解决潜在的冲突,可以保证代码的稳定性和一致性。

此时,查看远程仓库,master 已经是最新代码了:

此时,dev 分支对于我们来说就没用了,那么 dev 分支就可以被删除掉。

 

总结:在同一分支下进行多人协作的工作模式通常如下:

  1. 尝试推送修改: 首先,我们可以尝试使用 git push origin branch-name 命令将我们的修改推送到远程仓库的指定分支上。
  2. 拉取远程更新: 如果推送失败,那是因为远程分支比我们的本地分支更新,此时需要先使用 git pull 命令尝试合并远程仓库的更新到我们的本地分支上。
  3. 解决合并冲突: 如果合并过程中出现了冲突,需要先解决冲突并在本地提交。解决冲突后,可以继续下一步操作。
  4. 重新推送修改: 在没有冲突或者解决掉冲突后,再次使用 git push origin branch-name 命令推送我们的修改。这时应该能够成功地将我们的修改推送到远程仓库。
  5. 合并分支: 当功能开发完毕后,可以将当前分支合并到主分支(通常是 master 分支)。这可以通过使用 git merge 命令来完成。
  6. 删除分支: 最后,当分支的工作完成后,可以安全地删除该分支。这可以通过使用 git branch -d branch-name 命令来删除本地分支,并使用 git push origin --delete branch-name 命令删除远程分支。

多人协作二

当团队需要同时开发多个需求时,通常会采用分支策略来管理代码。这意味着每个需求或功能点都会在独立的分支上进行开发,而不是直接在主分支上进行修改。这样可以有效地隔离不同的功能开发,降低代码冲突和错误的风险。

也就是说,通常情况下,如果有多个需求需要多人同时进行开发,团队不会在一个分支上进行多人开发,而是会为每个需求或功能点创建一个独立的 feature 分支。

假设我们和我们的小伙伴同时有两个需求需要开发,为了遵循这种分支管理策略,我们会为每个需求创建一个独立的 feature 分支。

在前面的部分,我们已经了解到可以从码云上直接创建远程分支,但其实我们也可以通过推送的方式将本地创建的分支发送到远程仓库。

在接下来的部分,我们将使用这种方式来进行操作。

通过这种方式,每个开发者都能在独立的分支上进行工作,避免了直接在主分支上进行修改可能引发的冲突和混乱。同时,团队其他成员也可以在远程仓库上查看每个功能的开发进度,并在需要时协作或审查代码。

这种分支管理策略有助于提高团队的代码质量和开发效率,确保不同功能之间的独立性和稳定性。

我们(开发者1)可以进行以下操作:

创建新的功能分支(feature-1分支):我们创建了一个新的功能分支,用于开发我们自己的需求或功能点。

①远程创建分支:

②本地创建分支:

注意,这种方式创建分支,一定要确保本地的master分支是最新的,先进行pull操作。

在功能分支上进行开发:我们在这个功能分支上进行开发工作,添加新的代码文件和修改现有的文件。

推送功能分支到远程仓库:我们将本地的 feature-1分支推送到远程仓库,以便团队其他成员能够看到我们的工作。

对于小伙伴(开发者2)来说,可以进行以下操作:

先确保master分支是目前最新最全的版本:

创建新的功能分支(feature-2分支):小伙伴也在本地创建了一个新的功能分支,用于开发自己的需求或功能点。

在功能分支上进行开发:小伙伴在这个功能分支上进行开发工作,添加新的代码文件和修改现有的文件。

推送功能分支到远程仓库:小伙伴将本地的feature-2分支推送到远程仓库,以便团队其他成员能够看到他的工作。

此时,在本地,我们看不见小伙伴新建的文件,他也看不见我们新建的文件。并且推送各自的分支时,并没有任何冲突,开发者之间是互不影响的,这样用起来很舒服!

此时再次确认远端码云上此时的状态:

  • 对于我们的feature-1分支:我们的功能分支在远程仓库上,包含了我们开发的所有内容。
  • 对于小伙伴的feature-2分支:小伙伴的功能分支在远程仓库上,包含了他开发的所有内容。

正常情况下,我们两个就可以在自己的分支上进行专业的开发了!

但天有不测风云,小伙伴突然生病了,但需求还没开发完,需要我们帮他继续开发,于是他便把feature-2分支名告诉我们了。这时我们就需要在自己的机器上切换到feature-2分支帮忙继续开发,要做的操作如下:

此时我们肯定看不到小伙伴的分支:

但是远程上确实是有的,那么我们就拉取一下:

 

此时你肯定会想,我们又没有建立连接,为啥可以拉取到feature-2?

git pull 操作其实有两个用法:

1、拉取分支内的内容;

2、拉取仓库的内容。

此时我们拉取的就是仓库中的内容,不需要建立分支的连接。

当然,此时本地是没有feature-2分支的:

此时我们就需要在本地建立一个feauture-2分支,然后和远程的feauture-2分支建立联系。

然后切换到小伙伴的功能分支(feature-2分支):我们在本地切换到小伙伴的功能分支上,以便继续他的开发工作。切换成功后,便可以看见feature-2分支中的function2文件了,接着就可以帮小伙伴进行开发。


查看远程状态,推送成功了:我们查看远程状态,确保推送到远程仓库的操作成功。

这时,小伙伴已经修养的差不多,可以继续进行自己的开发工作,那么他首先要获取到我们帮他开发的内容,然后接着我们的代码继续开发。或者我们已经帮他开发完了,那他也需要在自己的电脑上看看我们帮他写的代码。

Pull 无效的原因是小伙伴没有指定本地feature-2分支与远程origin/feature-2分支的链接,根据提示,设置feature-2和origin/feature-2的链接即可。

目前,小伙伴的本地代码和远端保持严格一致。我们和我们的小伙伴可以继续在不同的分支下进行协同开发了。

 

 

各自功能开发完毕后,不要忘记我们需要将代码合并到master中才算真正意义上的开发完毕。

由于小伙伴率先开发完毕,于是开始 merge:

此时,审查人员审查:

此时远程仓库的状态:

当小伙伴将其代码merge到master后,这个时候我们也开发完成了,也需要进行merge到master操作。

思考:此时我们也使用PR申请单来合并,可以吗?

答案是可以的。

此处之所以可以,是因为我们的两个提交不是对同一个文件进行修改,所以没有产生冲突。

但是怕就怕这两个提交有冲突,此时,我们必须解决冲突。

确保master最新: 

 

此处表示提交没有任何冲突,此时Ctrl + X 直接退出即可:

现在冲突解决,我们再次使用PR:

 

此时远程仓库的状态:

此时,feature-1和feature-2分支对于我们来说就没用了,那么我们可以直接在远程仓库中将dev分支删除掉。

这就是多人协作的工作模式,一旦熟悉了,就非常简单。

远程分支删除后,本地 git branch -a 依然能看到的解决办法

当前我们已经删除了远程的几个分支。我们使用 git branch -a 命令可以查看所有本地分支和远程分支,但发现很多在远程仓库已经删除的分支在本地依然可以看到。

为了了解本地分支与远程仓库的关系,我们使用命令 git remote show origin。这个命令会显示远程地址、远程分支以及本地分支与之相对应的关系等信息。

通过这个命令,我们可以清楚地看到哪些远程仓库已经不存在的分支。根据提示,我们执行 git remote prune origin 命令。

这样就删除了那些远程仓库不存在的分支。

至于本地仓库的删除,可以根据需要自行操作:

企业级开发模型

当我们考虑软件开发过程时,通常会将其划分为几个主要阶段:规划、编码、构建、测试、发布、部署和维护。

最初,在软件项目的早期阶段,项目通常比较简单,开发工作量也相对较小。在这种情况下,一个程序员可能能够独自完成所有阶段的工作。他可以负责规划项目的需求和功能,编写代码实现这些功能,构建应用程序并进行测试,最终发布、部署和维护软件。

然而,随着软件产业的不断发展壮大,以及软件的应用范围和复杂性的不断增加,一个人已经无法满足所有工作的需求。软件的复杂度不断攀升,需要更多的专业知识和技能来处理。于是,开始出现了精细化分工的趋势。

在精细化分工的模式下,不同的开发人员或团队专注于软件开发过程中的不同阶段。例如,有些人可能负责规划和设计阶段,制定项目的整体架构和需求规格;其他人可能专注于编码,负责将规划好的需求转化为实际的代码;还有人可能专注于测试,确保软件在发布之前具有高质量和稳定性。

通过精细化分工,每个人都可以专注于自己擅长的领域,提高工作效率和质量。同时,团队协作也变得更加紧密,不同阶段的工作可以更好地协调和配合,从而加快软件开发周期,提高项目的成功率。

在传统的 IT 组织下,开发团队(Dev)和运维团队(Ops)之间存在着不同的诉求和利益冲突。开发团队,尤其是敏捷团队,通常追求变化,他们希望能够快速响应需求,不断进行软件功能和特性的更新和改进。而运维团队则更注重系统的稳定性和可靠性,他们追求保持线上服务的高可用性,因此更倾向于谨慎地控制变更,以防止不必要的风险和故障发生。

这种双方诉求的不同往往导致了利益的冲突。例如,敏捷团队和精益团队希望实现持续交付,以快速地向用户交付新功能和改进,而运维团队则更关注系统的稳定性和可维护性,因此更倾向于减少变更,以降低潜在的风险。

这种开发团队和运维团队之间的利益冲突导致了他们之间的分隔和矛盾,甚至形成了“部门墙”,阻碍了他们之间的合作和沟通。这不利于最大化 IT 价值的实现。

为了弥合开发和运维之间的鸿沟,需要在文化、工具和实践方面进行一系列变革,DevOps 正式登上舞台。

DevOps是Development和Operations的组合词,是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。它通过自动化“软件交付”和“架构变更”的流程,使得构建、测试、发布软件能够更加地快捷、频繁和可靠。在DevOps的软件开发过程中包含了多个阶段,包括计划、编码、构建、测试、预发布、发布、运维和监控。这表明了DevOps的综合性和强大性,它涵盖了整个软件开发生命周期,并强调了持续交付和持续改进的理念。通过DevOps,开发团队和运维团队可以更紧密地合作,加速软件交付,提高系统稳定性和可靠性,从而实现业务目标的最大化。

这个故事和我们课程的主题 Git 有着密切的关系。

举一个简单的例子就能说明这一点。在软件的迭代开发过程中,对代码的管理至关重要。每次迭代都意味着对代码的修改、更新和优化,而这些变化需要进行有效的管理和跟踪。而 Git(分布式版本控制系统)正是我们开发人员用来管理代码变更的利器!通过 Git,我们可以轻松地追踪代码的修改历史,查看每一次提交的详细内容,进行代码的分支和合并操作,以及协作开发等。因此,可以说 Git 对于我们开发人员来说是至关重要的工具,它帮助我们有效地管理和控制代码的变化,提高了团队的协作效率,保障了软件开发过程的顺利进行。

系统开发环境

环境隔离是软件开发和部署中的一种重要概念,旨在将不同阶段的工作流程、资源和配置隔离开来,以确保系统的稳定性、安全性和可靠性。这种隔离通常涉及将软件开发、测试和生产环境分开,每个环境都有自己独立的设置和资源。

对于开发人员来说,在系统开发过程中需要了解并熟悉的几个环境包括:

  1. 开发环境:开发环境是程序员们日常开发工作的主要场所。在开发环境中,通常会配置各种开发工具和调试设施,以便开发人员能够方便地编写、调试和测试代码。开发环境的特点是打开全部错误报告和测试工具,以便及时发现和解决问题。

  2. 测试环境:测试环境是用来进行软件功能和性能测试的环境。如果软件在测试环境中运行不正常,那么就不能将其发布到生产环境中。测试环境起到了开发环境和生产环境之间的过渡作用,它是确保软件质量的重要环节。

  3. 预发布环境:预发布环境是为了避免因测试环境和生产环境之间的差异导致的缺陷漏测而设置的环境。预发布环境的配置通常与生产环境一致,目的是为了在将软件部署到正式生产环境之前,提供一个更接近生产环境的测试环境,以便更好地保证软件质量。预发布环境是产品质量的最后一道防线,在项目上线前起到了至关重要的作用。

  4. 生产环境:生产环境是指正式提供对外服务的线上环境,用户可以在移动端或PC端访问到的应用程序都是部署在生产环境中运行的。在生产环境中,软件需要保证高可用性、高稳定性和高性能,因此对于开发人员来说,确保在生产环境中的软件运行良好至关重要。

这几个环境也代表了系统开发的三个重要阶段:开发、测试和上线。了解和熟悉这些环境对于开发人员来说是至关重要的,因为在不同的环境中部署和测试软件可能会有不同的需求和挑战。

对于规模稍微大一点的公司来说,可不仅仅局限于上述几个环境。例如,项目正式上线前可能还会存在仿真/灰度环境,以及多套测试环境,以满足不同版本上线前测试的需要。这些额外的环境能够更好地保障软件质量,提高上线成功率。

一个项目的开始是从设计阶段开始的,而项目的成功则从测试阶段开始。一个完善的测试体系可以在系统上线之前解决绝大部分致命 Bug。测试系统的完善和成熟是衡量一个软件企业整体水平的重要指标之一。测试往往被忽视,因为它的效益不够直接,但是它却是软件质量的最终保障,甚至是项目能否成功的重要因素!因此,公司在软件开发过程中应该重视测试环节,建立健全的测试体系,以确保软件质量和项目成功。

在软件开发的生命周期中,仿真/灰度环境是一个非常重要的阶段,通常位于测试环境和预发布环境之间。在正式将软件产品部署到生产环境之前,团队经常会将其部署到仿真/灰度环境中进行最后的测试和验证。

仿真/灰度环境是一个模拟生产环境的环境,但与生产环境不同的是,在此阶段可能只有部分真实用户或测试用户可以访问。这样可以让团队在真实的环境中测试应用程序的性能、稳定性和可靠性,同时也能够收集用户的反馈。

在仿真/灰度环境中进行测试的主要目的是确保软件产品在真实的使用环境中表现良好,避免在正式上线后出现意外的问题或故障。团队可能会在此阶段进行一些压力测试、性能测试、安全性测试等,以验证软件的各个方面是否符合预期。

此外,仿真/灰度环境还可以用于测试新功能的可用性和用户体验,以便在正式发布之前做出必要的调整和改进。通过在仿真/灰度环境中进行全面的测试和验证,团队可以最大程度地降低上线后出现问题的风险,确保用户能够获得稳定、高质量的产品体验。

Git 分支设计规范

环境有了概念后,对于开发人员来说,针对不同的环境来设计分支是一个常见的做法。这样做可以帮助开发团队更好地管理代码,并确保在不同环境中的部署和测试能够顺利进行。通常情况下,会有以下几种分支设计:

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

以上表格中的分支和环境的搭配仅是常用的一种,可视情况而定不同的策略。

master 分支

  • 用途:master 分支是主分支,也是唯一的只读分支。它用于部署到生产环境,即正式发布给最终用户使用的代码版本。通常,master 分支是由合并 release 分支得到的,release 分支是用于预发布和测试的分支。

  • 稳定性:master 分支被视为稳定的唯一代码库。因此,在任何情况下,都不允许直接在 master 分支上进行代码修改。这样可以确保生产环境中的代码始终保持稳定和可靠。

  • 发布功能:当产品的所有功能都已经实现并经过测试后,就可以将其发布到 master 分支。此外,所有对 master 分支的推送应该被打上标签(tag),以便后续追溯和版本管理。

  • 不可删除性:由于 master 分支承载了生产环境的代码,因此它具有不可删除的重要性。删除 master 分支可能会导致生产环境的代码丢失,因此通常情况下是不允许删除 master 分支的。

release 分支

  • 用途:release 分支是预发布分支,通常是基于 develop 分支创建的。它包含了本次上线的所有功能,在所有 feature 分支合并到 develop 分支后创建。release 分支可以部署到测试或预发布环境进行测试。

  • 命名规则:release 分支的命名以 release/ 开头,建议的命名规则是 release/version_publishtime。这样的命名规范可以帮助团队更好地识别和管理不同版本的发布。

  • 测试阶段:release 分支主要用于提交给测试人员进行功能测试。在发布提测阶段,测试团队将以 release 分支的代码为基准进行测试,以确保功能的正确性和稳定性。

  • 回归验证:如果在 release 分支测试过程中发现了问题,需要对这些问题进行回归验证,即确认在 develop 分支中是否存在相同的问题。这有助于识别问题的根本原因并进行修复。

  • 临时性质:release 分支通常是临时性的,即在产品上线后可以选择性地删除。一旦该版本的功能经过测试并成功上线,就可以将 release 分支合并回 develop 分支,并可选地删除 release 分支。

develop 分支

  • 用途:develop 分支是开发分支,通常是基于 master 分支创建的。它是一个只读且唯一的分支,用于保持最新完成以及 bug 修复后的代码。develop 分支的代码始终保持在一个可部署到开发环境对应集群的状态。

  • 创建方式:develop 分支通常是从 master 分支创建的。它作为一个中间分支,用于开发团队在开发新功能和修复 bug 时的工作基础。

  • 特性合并:在 develop 分支上,开发人员可以根据需求的大小程度确定是通过合并 feature 分支,还是直接在 develop 分支上进行开发。一般情况下,较大的功能或新特性会首先在 feature 分支上开发,然后再合并到 develop 分支中,而较小的修复或调整可以直接在 develop 分支上进行(非常不建议!)。

  • 开发环境部署:develop 分支的代码可以部署到开发环境对应的集群中进行测试和开发。这有助于开发团队在一个独立的环境中进行功能开发和测试,以确保代码的正确性和稳定性。

feature 分支

  • 用途:feature 分支通常用于新功能或新特性的开发。它是基于 develop 分支创建的,为开发团队提供了一个独立的工作空间,用于开发和测试新的功能或特性。

  • 创建方式:通常情况下,feature 分支是基于 develop 分支创建的。每个 feature 分支通常都专注于开发一个特定的功能或特性,以便更好地组织和管理代码。

  • 命名规则:feature 分支的命名通常以 feature/ 开头,建议的命名规则是使用用户或团队名称、创建时间和功能的简要描述。这样的命名规则可以帮助团队更好地识别和理解各个 feature 分支的内容。

  • 特性开发:在 feature 分支上进行新特性或新功能的开发。开发人员可以在该分支上自由地进行代码编写、测试和调试,以实现特定的功能要求。

  • 合并到 develop 分支:一旦新特性或新功能开发完成,开发人员需要将其合并到 develop 分支中。这样可以确保新开发的功能与主要代码库保持同步,并能够在后续的开发和测试中进行验证和使用。

  • 删除分支:一旦特性被成功地发布上线并合并到 develop 分支后,通常会将相应的 feature 分支删除。这样可以保持代码库的整洁性,避免不必要的分支堆积,同时也减少了后续维护和管理的复杂性。

hotfix 分支

  • 用途:hotfix 分支主要用于线上 bug 修复,也称为补丁分支。当线上出现紧急问题需要立即修复时,需要创建一个基于 master 分支的 hotfix 分支来进行修复工作。

  • 创建方式:hotfix 分支通常是基于 master 分支创建的。由于修复的问题是紧急的,因此必须基于最稳定的主分支进行修复,以确保修复的代码能够及时地被部署到生产环境中。

  • 命名规则:hotfix 分支的命名通常以 hotfix/ 开头,建议的命名规则是使用用户或团队名称、创建时间和修复内容的简要描述。这样的命名规则可以帮助团队更好地识别和理解各个 hotfix 分支的内容。

  • 问题修复:在 hotfix 分支上进行线上 bug 的修复工作。开发人员需要快速定位和修复线上出现的紧急问题,并确保修复的代码质量和稳定性。

  • 合并到主分支和 develop 分支:修复完成后,需要将 hotfix 分支合并到 master 分支和 develop 分支中。这样可以保持主分支和开发分支的同步,并确保修复的代码被包含在下一个发布版本中。

  • 推送远程和删除分支:修复完成并合并到主分支和 develop 分支后,需要将相应的 hotfix 分支推送到远程仓库。一旦修复上线并且代码被成功部署到生产环境中,通常会将 hotfix 分支删除,以保持代码库的整洁性和可维护性。

其实,以上所述的是企业级常用的一种Git分支设计规范,即Git Flow模型。然而,需要指出的是,该模型并非适用于所有团队、环境和文化。如果采用持续交付策略,我们可能会希望有一些能够尽可能简化交付过程的方法。有些人偏爱基于主干的开发模式,喜欢使用特性标志。然而,从测试的角度来看,这些方法可能会引发一些问题。

关键在于站在我们的团队或项目的角度进行思考:这种分支模型能解决哪些问题?它可能会带来哪些问题?这种模式更适合哪种开发?我们是否希望鼓励这种行为?选择的分支模型最终都是为了让人们更容易进行软件协作开发。因此,分支模型需要考虑到使用者的需求,而不是盲目听信某些所谓的“成功的分支模型”。

因此,对于不同公司而言,规范可能会有些许差异,但是基本目标始终是为了提高效率和稳定性。

企业级项目管理实战

DevOps研发平台

Gitee 企业版 - 企业级 DevOps 研发效能平台

企业名称可随意填写一个测试名称,只要能通过即可。注意,多人协作开发,需要将多人账号拉入一个企业下才行。

新建项目:

 此处关联仓库可以先不填写,等项目创建完毕之后修改即可:

新建代码仓库:

 

创建的仓库可以关联到某个项目中被管理。

添加成员:

添加企业成员:

申请后需要负责人审批通过。 

添加项目成员: 

添加仓库开发人员: 

开发场景-基于git flow模型的实践

新需求加入

现有一个订单管理的新需求需要开发,⾸先可以基于 develop 分支创建一个:

 

这是因为我们之前选择分支模型的时候选择了开发/发布/缺陷分离模型,已经包含了相关分支,不可以再创建一个同名分支: 

所以其实我们选择生产/开发模型即可,已经可以满足我们的需求了:

所以我们删除一下,重新创建一个仓库:

 

新分支就创建好了:

 

现在我们就可以切换到这个分支上,然后把这个分支拉取到本地进行开发,开发完之后再把本地修改push到远程仓库中。

简单起见,我们这里就直接在远程上修改一下:

 

提交之后刷新当前分支:

写完feature分支,接下来就是把它合并到develop分支上,develop分支又可以被部署到开发环境中进行自测和验证。

此时就到了测试人员测试和审查人员审查的阶段:

 

此时develop分支里面就有了相应的修改:

至于部署的环节:

但是这是一个付费功能……只有200分钟的体验时长。感兴趣的话你也可以点开页面提供的官方文档查看。

总之,开发人员进行自测通过之后,就可以把代码交给测试人员进行测试了。测试人员拿到的是release分支。

测试人员需要把release分支部署到测试环境里面,然后在测试环境里面进行测试,模拟预发布环境。

测试人员测试通过之后,我们就需要将release分支合并到master分支上。

 

可以看到合并完成之后确实删除了release分支:

master分支上也确实有了相关的代码:

最后我们再把已经没有用的feature删除:

修复测试环境 Bug

当在 develop 分支上进行测试时发现 Bug,通常建议直接在 feature 分支上进行修复。这种做法有助于保持代码的整洁性和可追溯性,并且可以避免在 develop 分支上引入不必要的更改。

修复测试环境 Bug 的流程如下:

  1. 确认 Bug 的具体情况和影响范围。
  2. 在 feature 分支上切出一个新的修复分支,命名方式可以是 fix/bug-description 或者其他符合团队约定的命名规范。
  3. 在修复分支上进行 Bug 修复工作,确保修复后的代码通过单元测试和集成测试。
  4. 提交修复分支,并进行必要的 code review。
  5. 如果修复分支上的更改需要在 develop 分支上进行验证,可以将修复分支合并到 develop 分支进行测试。
  6. 如果 Bug 修复通过了测试,可以继续按照正常的提测上线流程进行后续操作。

需要注意的是,修复测试环境 Bug 的流程和新需求加入的流程应该保持一致,包括代码审查、测试验证以及上线发布等步骤。这样可以确保团队在处理 Bug 修复时能够保持高效和规范的工作流程,同时也能够及时解决测试环境中的问题,保证项目进度和质量。

修改预发布环境 Bug

在 release 测试过程中发现 Bug 后,首先需要确认是否在 develop 分支上也存在相同的问题。如果在 develop 分支上也存在该 Bug,则修复流程与修复测试环境 Bug 的流程一致。

修复预发布环境 Bug 的流程如下:

  1. 确认 Bug 的具体情况和影响范围。
  2. 回归检查 develop 分支是否存在相同的 Bug。
  3. 如果 develop 分支也存在相同的 Bug,则在 feature 分支上创建一个新的修复分支,命名方式可以是 fix/bug-description 或其他符合团队约定的命名规范。
  4. 在修复分支上进行 Bug 修复工作,确保修复后的代码通过单元测试和集成测试。
  5. 提交修复分支,并进行必要的代码审查。
  6. 如果修复通过了测试,可以将修复分支合并到 develop 分支上继续测试验证。
  7. 如果修复通过了 develop 分支上的测试,再合并到 release 分支上继续测试验证。
  8. 如果修复通过了 release 分支上的测试,就可以按照正常的流程继续进行预发布环境的部署和测试。

如果在 develop 分支上不存在相同的 Bug,这种可能性较少,可能是由于数据兼容性问题、环境配置问题等引起的。在这种情况下,可以针对预发布环境进行修复,并在修复后再次进行测试验证,确保 Bug 已被解决。

修改正式环境 Bug

在 master 分支测试过程中发现 Bug 后,首先需要确认是否在 release 分支和 develop 分支上也存在相同的问题。

修复正式环境 Bug 的流程如下:

  1. 确认 Bug 的具体情况和影响范围。
  2. 回归检查 release 分支和 develop 分支是否存在相同的 Bug。
  3. 如果 release 分支或 develop 分支上存在相同的 Bug,则需要创建一个新的修复分支,命名方式可以是 fix/bug-description 或其他符合团队约定的命名规范。
  4. 在修复分支上进行 Bug 修复工作,确保修复后的代码通过单元测试和集成测试。
  5. 提交修复分支,并进行必要的代码审查。
  6. 如果修复通过了测试,可以将修复分支合并到相关的分支上进行测试验证。
  7. 如果修复通过了所有分支上的测试,可以按照正常的流程继续进行正式环境的部署和测试。整体流程其实和之前我们演示的一样。

如果在 release 分支和 develop 分支上均不存在相同的 Bug,这种可能性较少,可能是由于数据兼容性问题、环境配置问题等引起的。在这种情况下,可以针对正式环境进行修复,并在修复后再次进行测试验证,确保 Bug 已被解决。

紧急修复正式环境 Bug

在正式环境运行一段时间后出现了紧急 Bug 需要修复。虽然需求在测试环节未出现 Bug,但为了保证修复后的代码稳定性,建议进行紧急修复前的验证。

紧急修复正式环境 Bug 的流程如下:

  1. 首先,基于 master 分支创建一个新的修复分支,命名方式可以是 hotfix/xxx 或其他符合团队约定的命名规范。
  2. 在修复分支上进行 Bug 修复工作,并确保修复后的代码通过单元测试和集成测试。
  3. 提交修复分支,并进行必要的代码审查。
  4. 将修复分支发布到预发布环境进行验证。尽管有的企业可能不进行测试环境的验证,但仍建议至少验证一下预发布环境,以确保修复的代码与现有环境的兼容性。
  5. 验证通过后,将修复分支合并到 master 分支,并在 master 分支上进行进一步的测试验证。
  6. 如果修复通过了 master 分支上的测试,可以将 master 分支的代码合并到 develop 分支,同时删除 hotfix/xxx 分支。

这样,通过以上流程,可以确保紧急修复的 Bug 被及时修复,并且保证修复后的代码稳定可靠。

拓展阅读

其他DevOps研发平台

DevOps_DevOps 解决方案_一站式 DevOps_开发者工具 | 腾讯云 CODING DevOps

阿里云云效_云效_云原生时代新DevOps平台-阿里云 (aliyun.com)

拓展实践

对于阿里云效平台,我们也可以使用阿里飞流flow分支模型进行项目版本管理实践:

项目版本管理的最佳实践:飞流Flow(阿里AoneFlow)篇-CSDN博客

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值