了解用于持续交付的 Git 分支模型
编写代码的目的是为软件提供增强功能。
引入过多处理开销的分支模型并不会有助于提高向客户获取更改的速度,开发分支模型可提供足够的填充量,而不会产生质量较差的更改。 但同时,也不会引入太多进程来降低速度。
Internet 上全是 Git 的分支策略;虽然这些策略没有对错之分,但完美的分支策略才适用于你的团队!
你将了解到始终使用功能分支和拉取请求的组合来提供随时可发布的主分支。
做好准备
我们来介绍一下我们建议的原则:
主分支:
- 主分支是将任何内容发布到生产的唯一方法。
- 主分支应始终处于随时可用状态。
- 使用分支策略保护主分支。
- 对主分支进行的任何更改都只通过拉取请求。
- 用 Git 标记来标记主分支中的所有发布。
功能分支:
- 将功能分支用于所有新功能和 bug 修复。
- 使用功能标志管理长时间运行的功能分支。
- 从功能分支到主分支的更改只通过拉请求。
- 命名功能以反映其用途。
发布分支:
- 从稳定的功能分支创建专用发布分支,以为部署做好准备。
- 确保发布分支经过彻底的测试和稳定工作。
- 在部署之前,将 bug 修复和必要的更改应用到发布分支。
- 标记发布分支中的发布,以标记重要里程碑。
分支列表:
bugfix/description features/feature-name features/feature-area/feature-name hotfix/description users/username/description users/username/workitem
拉取请求:
- 评审并合并带拉取请求的代码。
- 自动执行你在拉取请求中检查和验证的内容。
- 跟踪拉取请求完成持续时间,并设置目标以减少所花费的时间。
我们将使用在之前练习中创建的 myWebApp。 请参阅介绍如何在本地使用 Git。
在此方法中,我们将使用市场中的三个流行扩展:
- Azure CLI是 Azure 的命令行接口。
- Azure DevOps CLI:它是 Azure CLI 的扩展,可与 Azure DevOps 和 Azure DevOps Server 配合使用,旨在与 Git、CI 管道和 Agile 工具无缝集成。 使用 Azure DevOps CLI,无需离开命令行即可参与项目。 CLI 在 Windows、Linux 和 Mac 上运行。
- Git 拉取请求合并冲突:通过 Microsoft DevLabs 创建的开源扩展,你可以在 Web 上评审和解决拉取请求合并冲突。 在 Git 拉取请求完成之前,必须解决与目标分支的任何冲突。 作为拉取请求合并过程的一部分,可使用此扩展在 Web 上解决这些冲突,而不是在本地克隆中执行合并和解决冲突。
Azure DevOps CLI 支持以 JSON、JSONC、YAML、YAMLC、表、TSV 和无格式形式返回查询结果。 可使用“配置”命令来配置首选项。
如何实现
重要
你需要在第一个学习路径(描述在本地使用 Git)中创建项目。
将主分支克隆到本地存储库后,请创建新的功能分支 myFeature-1:
myWebApp
git checkout -b feature/myFeature-1
输出:
Switched to a new branch 'feature/myFeature-1'.
运行“Git 分支”命令以查看所有分支。 其中显示星号的分支是“当前已签出的”分支:
myWebApp
git branch
输出:
feature/myFeature-1
主
在 feature/myFeature-1 branch 中对 Program.cs 文件进行更改:
myWebApp
notepad Program.cs
暂存更改并在本地提交,然后将分支发布到远程:
myWebApp
git status
输出:
On branch feature/myFeature-1 Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: Program.cs.
myWebApp
git add . git commit -m "Feature 1 added to Program.cs"
输出:
[feature/myFeature-1 70f67b2] feature 1 added to program.cs 1 file changed, 1 insertion(+).
myWebApp
git push -u origin feature/myFeature-1
输出:
Delta compression using up to 8 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 348 bytes | 348.00 KiB/s, done. Total 3 (delta 2), reused 0 (delta 0) remote: Analyzing objects... (3/3) (10 ms) remote: Storing packfile... done (44 ms) remote: Storing index... done (62 ms) To https://dev.azure.com/organization/teamproject/\_git/MyWebApp * [new branch] feature/myFeature-1 -> feature/myFeature-1 Branch feature/myFeature-1 set up to track remote branch feature/myFeature-1 from origin.
远程显示更改的历史记录:
为组织和项目配置 Azure DevOps CLI。 替换组织和项目名称:
az devops configure --defaults organization=https://dev.azure.com/organization project="project name"
创建新的拉取请求(使用 Azure DevOps CLI),以评审 feature-1 分支中的更改:
az repos pr create --title "Review Feature-1 before merging to main" --work-items 38 39 ` --description "#Merge feature-1 to main" ` --source-branch feature/myFeature-1 --target-branch main ` --repository myWebApp --open
在创建拉取请求后,请在提出拉取请求时,使用 --open 开关在 Web 浏览器中打开。 在拉取请求完成后,可使用 --deletesource-branch 开关删除分支。 此外,请考虑使用 --auto-complete,使所有策略通过时自动完成,并且可将源分支合并到目标分支中。
注意
有关 az repos pr create 参数的详细信息,请参阅创建拉取请求以查看和合并代码。
团队联合评审代码更改并批准拉取请求:
主分支可随时进行发布。 团队用发布号标记主分支:
开始使用功能 2。 从主分支创建远程分支,并在本地执行签出:
myWebApp
git push origin main:refs/heads/feature/myFeature-2
输出:
Total 0 (delta 0), reused 0 (delta 0) To
https://dev.azure.com/**organization**/**teamproject**/\_git/MyWebApp
* [new branch] origin/HEAD -> refs/heads/feature/myFeature-2.myWebApp
git checkout feature/myFeature-2
输出:
Switched to a new branch 'feature/myFeature-2' Branch feature/myFeature-2 set up to track remote branch feature/myFeature-2 from origin.
通过更改在 feature-1 中更改的代码中的同一注释行来修改 Program.cs。
public class Program { // Editing the same line (file from feature-2 branch) public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build();
在本地提交更改,推送到远程存储库,然后提出拉取请求,将更改从 feature/myFeature-2 合并到主分支:
az repos pr create --title "Review Feature-2 before merging to main" --work-items 40 42 ` --description "#Merge feature-2 to main" ` --source-branch feature/myFeature-2 --target-branch main ` --repository myWebApp --open
使用拉取请求时,将根据 feature-1 的发布报告生产中的重要 bug。 若要调查此问题,需要根据当前在生产中部署的代码版本进行调试。 若要调查此问题,请使用“release_feature1”标记创建新的 fof 分支:
myWebApp
git checkout -b fof/bug-1 release_feature1
输出:
Switched to a new branch, 'fof/bug-1'.
通过更改在 feature-1 发布中更改的代码中的同一代码行来修改 Program.cs:
public class Program { // Editing the same line (file from feature-FOF branch) public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build();
在本地暂存和提交更改,然后将更改推送到远程存储库:
myWebApp
git add . git commit -m "Adding FOF changes." git push -u origin fof/bug-1
输出:
To
https://dev.azure.com/**organization**/**teamproject**/\_git/MyWebApp
* [new branch] fof/bug-1 - fof/bug-1 Branch fof/bug-1 set up to track remote branch fof/bug-1 from origin.在将更改推出到生产后,请立即将 fof\bug-1 分支标记为 release_bug-1 标记,然后提出拉取请求,将 fof/bug-1 中的更改合并回到主分支:
az repos pr create --title "Review Bug-1 before merging to main" --work-items 100 ` --description "#Merge Bug-1 to main" ` --source-branch fof/Bug-1 --target-branch main ` --repository myWebApp --open
在拉取请求过程中,将删除该分支。 不过,你仍可以使用标记来引用整个历史记录。
修复重要 bug 后,让我们回顾一下 feature-2 拉取请求。
分支页表明 feature/myFeature-2 分支在主分支前做一个更改,在主分支后做两个更改:
如果尝试批准拉取请求,则会看到一条错误消息,告知你合并冲突:
可使用 Git 拉取请求合并冲突解决扩展解决浏览器中的合并冲突。 导航到“冲突”选项卡,然后单击“Program.cs”以解决合并冲突:
通过用户界面,可以获取源、目标,添加自定义更改,然后评审并提交合并。 合并更改后,拉取请求也已完成。
此时,可以根据在fof/bug-1分支中实现的关键 bug 修复创建发布分支,并将其合并到 master 中。 使用 git checkout 命令,从主分支创建专用发布分支。
git checkout -b release/v1.1 main
此命令基于主分支新建名为 release/v1.1 的分支。
在发布过程中达到重要里程碑时,使用 Git 标记在发布分支中标记发布。 标记充当标记以表示软件的特定版本。
git tag -a v1.1 -m "Release version 1.1"
此命令创建名为 v1.1 的标记,以在发布分支中标记版本 1.1。
工作原理
我们了解了 Git 分支模型如何让你灵活地通过创建每个功能的分支来并行处理功能。
通过拉取请求工作流,你可使用分支策略评审代码更改。
Git 标记是一种记录里程碑(例如已发布的代码版本)的好方法;标记可提供从标记创建分支的方法。
我们根据以前的发布标记创建了一个分支,以修复生产中的重要 bug。
通过 Web 门户中的分支视图,可轻松在主分支前面标识分支。 此外,如果任何正在进行的拉取请求在没有解决合并冲突的情况下尝试合并到主分支,则将强制发生合并冲突。
通过精简分支模型,你可创建短期分支,并更快地将质量更改推送到生产。