Git 对于帮助小型团队管理其软件开发流程非常有用,但有些方法可以使其更有效。我发现了一些最佳实践,这些实践对我的团队很有帮助,尤其是在新团队成员加入且 Git 专业知识水平参差不齐的情况下。
为你的团队规范 Git 约定
每个人都应该遵循分支命名、标签和编码的标准约定。每个组织都有标准或最佳实践,并且互联网上可以免费获得许多建议。重要的是尽早选择合适的约定并作为一个团队遵守它。
此外,不同的团队成员对 Git 的专业知识水平也不同。你应该创建并维护一套基本的操作指南,用于执行遵循项目约定的常见 Git 操作。
正确合并更改
每个团队成员都应该在单独的功能分支上工作。但是,即使使用单独的分支,每个人最终都会修改一些公共文件。当将更改合并回 master
分支时,合并通常不会自动完成。可能需要人工干预来协调两位作者对同一文件所做的不同更改。这就是你必须学习如何处理 Git 合并技术的地方。
现代编辑器具有帮助处理 Git 合并冲突 的功能。它们在文件的每个部分中指示合并的各种选项,例如是保留你的更改、另一个分支的更改还是两者都保留。如果你的代码编辑器不支持此类功能,那么可能是时候选择其他代码编辑器了。
经常 rebase 你的功能分支
当你继续开发你的功能分支时,经常将其 rebase 到 master
。这意味着定期执行以下步骤
git checkout master
git pull
git checkout feature-xyz # name of your hypothetical feature branch
git rebase master # may need to fix merge conflicts in feature-xyz
这些步骤 重写 你功能分支中的历史记录(这不是一件坏事)。首先,它使你的功能分支看起来像 master
,其中包含截至当时的 master
的所有更新。然后,你对功能分支的所有提交都会在顶部重放,因此它们按顺序出现在 Git 日志中。你可能会遇到合并冲突,你需要沿途解决这些冲突,这可能是一个挑战。但是,这是处理合并冲突的最佳时机,因为它只会影响你的功能分支。
在你修复任何冲突并执行回归测试后,如果你准备好将你的功能合并回 master
,请再次执行上述 rebase 步骤,然后执行合并
git checkout master
git pull
git merge feature-xyz
在此期间,如果其他人将与你的更改冲突的更改推送到 master
,则 Git 合并将再次发生冲突。你需要解决它们并重复回归测试。
还有其他合并理念(例如,不使用 rebase 而仅使用 merge 来避免重写历史记录),其中一些理念甚至可能更易于使用。但是,我发现上述方法是一种干净可靠的策略。提交历史记录堆叠起来,成为一个有意义的功能序列。
使用“纯合并”策略(不定期 rebase,如上建议),master
分支中的历史记录将与所有正在并发开发的功能的提交交错在一起。这种混杂的历史记录更难审查。确切的提交时间通常不是那么重要。最好有一个更容易审查的历史记录。
在合并之前 squash 提交
在你的功能分支上工作时,即使是微小的更改也可以添加提交。但是,如果每个功能分支产生 50 个提交,随着功能的添加,master
分支中的提交数量可能会不必要地增长。一般来说,每个功能分支应该只向 master
添加一个或几个提交。为了实现这一点,squash 将多个提交合并为一个或几个提交,并为每个提交添加更详细的消息。这通常使用如下命令完成
git rebase -i HEAD~20 # look at up to 20 commits to consider squashing
当执行此操作时,会弹出一个编辑器,其中包含你可以通过多种方式操作的提交列表,包括 pick 或 squash。Pick 提交意味着保留该提交消息。Squash 意味着将该提交的消息与前一个提交合并。使用这些和其他选项,你可以将提交消息合并为一个,并进行一些编辑和清理。这也是一个摆脱不重要的提交消息的机会(例如,关于修复拼写错误的提交消息)。
总之,保留与提交关联的所有操作,但在合并到 master
之前,合并和编辑关联的消息文本以提高清晰度。不要在 rebase 过程中意外删除提交。
在执行这样的 rebase 之后,我喜欢最后一次查看 git log
以进行最终编辑
git commit --amend
最后,由于分支的 Git 提交历史记录已被重写,因此强制更新到你的远程功能分支是必要的
git push -f
使用标签
在你完成测试并准备好从 master
分支部署软件后,或者如果你想出于任何其他原因将当前状态保留为一个重要的里程碑,请创建一个 Git 标签。虽然分支会累积与提交相对应的更改历史记录,但标签是分支在该时刻状态的快照。标签可以被认为是无历史记录的分支,也可以被认为是创建标签之前立即指向特定提交的命名指针。
配置控制是关于在各个里程碑处保留代码的状态。能够在任何里程碑处重现软件源代码,以便在必要时可以重建它是大多数项目中的一项要求。Git 标签为此类代码里程碑提供了唯一标识符。标记很简单
git tag milestone-id -m "short message saying what this milestone is about"
git push --tags # don't forget to explicitly push the tag to the remote
考虑这样一种情况:将与给定 Git 标签对应的软件分发给客户,并且客户报告了一个问题。虽然存储库中的代码可能会继续演变,但通常有必要回到与 Git 标签对应的代码状态,以精确重现客户问题,从而创建错误修复。有时较新的代码可能已经修复了该问题,但并非总是如此。通常,你会检出特定的标签并从该标签创建一个分支
git checkout milestone-id # checkout the tag that was distributed to the customer
git checkout -b new-branch-name # create new branch to reproduce the bug
除此之外,如果它们对你的项目有益,请考虑使用带注释的标签和签名标签。
使软件可执行文件打印标签
在大多数嵌入式项目中,从软件构建创建的最终二进制文件具有固定的名称。与软件二进制文件对应的 Git 标签无法从其文件名中推断出来。在构建时将“标签嵌入”到软件中很有用,以便将任何未来的问题精确地关联到给定的构建。嵌入标签可以在构建过程中自动化。通常,git describe
生成的标签字符串会在代码编译之前插入到代码中,以便生成的执行文件在启动时打印标签字符串。当客户报告问题时,可以引导他们向你发送启动输出的副本。
结论
Git 是一个复杂的工具,需要时间才能掌握。使用这些实践可以帮助团队成功地使用 Git 进行协作,无论他们的专业知识水平如何。
5 条评论