LabHub
学习 学习路径 课程

Git 实战

分支策略实操

在 LabHub 中继续学习

目标

从零开始创建一个仓库,直观确认三种集成方式(no-ff 合并、快进、cherry-pick)会在历史中留下怎样不同的结果,并通过统计这些结果编写策略对照表。

为什么重要

分支策略之争通常最终会沦为偏好之争。但真正需要回答的决策问题只有一个:发生故障时,计划如何在这个仓库中找到致因 commit。--no-ff 合并会保留“这一组变更何时被集成”的记录;快进能提供线性历史,但会抹去集成时间点;squash 合并则把二分查找的分辨率固定为 PR 大小,并且从 Git 的角度看,该分支从未被合并过。这些差异不能只靠阅读说明来掌握,必须亲自用 git rev-list --min-parents=2 统计,才能真正理解。

步骤

此镜像未配置全局 git 身份。在每个新建仓库中,必须本地配置 git config user.email / git config user.name,否则 commit 会失败。

  1. /root/gitx1/repo 创建仓库。当前分支必须是 main;仓库中必须已设置本地 user.emailuser.name;并且至少要有 1 个包含 README.md 的 commit。
  2. 创建 feature/login 分支并堆叠 2 个 commit。commit 标题必须准确为 login: formlogin: validation,分支中必须存在 login.txt 文件。以 login: 开头的 commit 必须恰好为 2 个
  3. 切换到 main,合并 feature/login,并确保保留 merge commit(即拥有两个父节点的 commit)。合并后,main 中必须存在 login.txt
  4. main 创建 feature/quick 分支,生成一个添加 quick.txt 的 commit。标题必须准确为 quick: typo。随后在 main 上执行仅快进合并。该 commit 必须只有 1 个父节点,并且 main 的 merge commit 数量必须仍是第 3 步创建的 1 个
  5. main 当前位置创建附注标签 v1.0.0。标签消息不得为空。
  6. v1.0.0 所在位置创建 release/1.0 分支,并生成一个添加 hotfix.txt 的 commit。标题必须准确为 hotfix: null guard。然后将同一变更也应用到 main。条件:两个分支中的 hotfix.txt 内容相同;两边都拥有 hotfix: null guard commit;但两个 commit 的哈希必须不同
  7. 整理分支。删除 feature/quick,保留 feature/login,再创建新的 feature/wip 分支,并堆叠至少 1 个 main 中不存在的 commit(必须仍处于尚未合并的状态)。
  8. 编写 /root/gitx1/strategy.md。必须包含:
    • merge_commits=main 的 merge commit 数量
    • branches= — 此仓库的本地分支数量
    • tags= — 标签数量
    • 对 Git Flow / GitHub Flow / Trunk-Based 三种策略的说明
    • 判断此仓库更接近哪种策略(必须包含“此仓库”“我们”或“当前”中的一种表述)

参考

创建仓库并设置身份

/root/gitx1/repo 创建仓库。当前分支必须是 main;仓库中必须已设置本地 user.emailuser.name;并且至少要有 1 个包含 README.md 的 commit。

在 /root/gitx1/repo 中执行 git init,并将默认分支名称设为 main。此镜像没有全局 git 身份;如果不直接为这个仓库设置 user.email 和 user.name,commit 本身就会失败。

在功能分支上堆叠 2 个 commit

创建 feature/login 分支并堆叠 2 个 commit。commit 标题必须准确为 login: formlogin: validation,分支中必须存在 login.txt 文件。以 login: 开头的 commit 必须恰好为 2 个

创建 feature/login 分支,将对 login.txt 的修改分两次提交。commit 标题必须与指定字符串完全一致,并确保以 login: 开头的 commit 恰好有 2 个。

禁止快进地完成合并

切换到 main,合并 feature/login,并确保保留 merge commit(即拥有两个父节点的 commit)。合并后,main 中必须存在 login.txt

切换到 main 并合并 feature/login,同时确保留下拥有两个父节点的 commit。如果直接 merge,可能会快进,从而丢失集成记录。

通过快进合入小型修正

main 创建 feature/quick 分支,生成一个添加 quick.txt 的 commit。标题必须准确为 quick: typo。随后在 main 上执行仅快进合并。该 commit 必须只有 1 个父节点,并且 main 的 merge commit 数量必须仍是第 3 步创建的 1 个

创建 feature/quick,提交 quick.txt,然后在 main 上仅以快进方式合并。如果生成 merge commit,此步骤就会失败。使用 --ff-only 可在条件不满足时直接拒绝操作。

添加发布标签

main 当前位置创建附注标签 v1.0.0。标签消息不得为空。

在 main 上添加 v1.0.0 标签。轻量标签只是一个指针,不会保留作者和消息;请使用会创建标签对象的选项。

将发布分支的 hotfix 带到 main

v1.0.0 所在位置创建 release/1.0 分支,并生成一个添加 hotfix.txt 的 commit。标题必须准确为 hotfix: null guard。然后将同一变更也应用到 main。条件:两个分支中的 hotfix.txt 内容相同;两边都拥有 hotfix: null guard commit;但两个 commit 的哈希必须不同

从 v1.0.0 创建 release/1.0 并提交 hotfix.txt,然后将同一变更也应用到 main。不要合并整个分支,只取回这一个 commit。

cherry-pick 会重新应用变更并创建新的 commit,而不是移动 commit。不过,本实验中 release/1.0 是从 main 尾部直接创建的,因此两个 commit 的父节点相同。请使用 git cherry-pick -x。这样会在消息中附加一行 (cherry picked from commit ...),从而在历史中保留其来源,并确保两个 commit 对象确实不同。这正是实际工作中将 hotfix 应用到多个分支时推荐的方式。

只清理已合并的分支

整理分支。删除 feature/quick,保留 feature/login,再创建新的 feature/wip 分支,并堆叠至少 1 个 main 中不存在的 commit(必须仍处于尚未合并的状态)。

删除已经完成合并的分支,保留尚未合并的分支。先用 git branch --merged main 确认哪些分支可以安全删除。使用 -d 而不是 -D,可以防止误删未合并分支。

统计仓库状态并编写策略对照表

编写 /root/gitx1/strategy.md。必须包含:

在 /root/gitx1/strategy.md 中,根据实际仓库统计值填写 merge_commits= / branches= / tags= 三行;比较三种分支策略,然后判断此仓库更接近哪一种。请使用 git 命令统计数值。