提交更改 — 在 Git 版本控制系统中固定更改的操作,在项目历史中创建保存点。每个提交包含哈希、作者、日期和更改描述。根据 GitHub Octoverse 2024 数据,全球每天创建超过 5000 万个提交。Commit — 版本控制工作的基本单元,没有它就无法想象现代软件开发。
要点
Git 中的提交是一个对象,用于存储项目文件在特定时间点的状态。每个提交包含所有跟踪文件的快照、对父提交的引用和元数据。与其他版本控制系统不同,Git 使用内容可寻址存储——每个对象通过其内容的 SHA-1 哈希进行标识。
当开发人员提交更改时,Git 会创建一个提交对象,其中包含:树对象(文件结构)、父提交哈希、作者、提交者、日期和消息。此对象是不可变的——创建后,无法在不更改其哈希的情况下修改提交。正是这种不可变性保证了项目历史的完整性。
# 暂存更改并提交
git add index.html style.css
git commit -m "Fix responsive layout on mobile devices"
# 查看提交详情
git log --oneline -3
git show HEAD
# 暂存所有更改并一步提交
git commit -a -m "Update dependencies to latest versions"
提交形成有向无环图(DAG),其中每个新提交引用前一个提交。这允许在历史中导航、撤销更改以及分析代码库的演变。理解Git DAG结构是高级提交操作的基础。
Git 中的提交流程包括两个阶段:将更改添加到暂存区(索引)和创建提交。暂存区允许开发人员选择哪些更改将进入提交,即使工作目录中有许多文件被修改。
原子性规则——良好提交的关键原则。每次提交应包含一个逻辑更改。如果开发人员修复错误并重构代码——这是两个不同的提交。原子提交简化了代码审查、更改撤销和历史分析。
在提交之前值得检查:代码中是否保留了调试输出、注释块或意外更改。为此使用 git diff --cached 命令,它显示将进入提交的内容。通过git status进行额外检查可显示暂存区中的文件列表。
提交消息是供将来开发人员使用的更改文档。好的消息回答以下问题:更改了什么以及为什么。Conventional Commits约定(Angular 团队,2016)已成为许多项目的标准,并定义了格式:类型(范围):描述。
| 类型 | 用途 | 示例 |
|---|---|---|
| feat | 新功能 | feat(api): add user registration endpoint |
| fix | 错误修复 | fix(auth): resolve token refresh issue |
| refactor | 重构(不改变行为) | refactor(core): extract payment validator |
| docs | 文档 | docs(readme): update installation guide |
| test | 添加测试 | test(cart): add unit tests for checkout |
好的提交消息由标题(最多 50 个字符)和正文(可选,每行最多 72 个字符)组成。标题用祈使句编写:“Add”而不是“Added”或“Adds”。标题末尾不使用大写字母和句点——这是 Git 的国际约定。
糟糕的消息:“fix things”或“update”——不包含信息。一个月后,开发人员将无法理解更改了什么以及为什么。好的消息:“fix(payment): handle timeout in stripe callback”——立即清楚在哪里修复了什么。
开发人员,尤其是初学者,经常在提交时犯典型错误。最常见的——过大的提交,混杂了数十个更改。这样的提交无法部分撤销,代码审查也变得痛苦。
第二个最常见的错误——糟糕的提交消息。“fix”、“update”、“changes”或“wip”类型的消息不会给未来的开发人员提供上下文。半年后没有人会记得具体修复了什么。规则很简单:想象一年后你在查看历史记录并试图找到特定的更改。
第三个错误——提交未编译或无法工作的代码。提交后代码至少应该能编译。不损坏的构建——对推送到公共分支的每个提交的基本要求。为此,在提交前运行构建和测试。
第四个错误——提交包含机密数据。API 密钥、密码和令牌不应进入 Git 历史。如果秘密已经提交,仅在新提交中删除是不够的——需要从整个历史中通过 git filter-branch 或 BFG Repo-Cleaner 删除。
Git 提供了管理提交历史的工具。最有用的是git commit --amend,它允许用新更改补充最后一次提交或修复消息。如果开发人员忘记包含文件或在消息中出错,这很方便。
# 修复最后一条提交消息
git commit --amend -m "fix(auth): correct token validation logic"
# 将遗漏的文件添加到最后一次提交
git add missed-file.txt
git commit --amend --no-edit
# 对最后 3 次提交进行交互式变基
git rebase -i HEAD~3
Interactive rebase——用于重写历史记录的有力工具。允许合并提交(squash)、更改消息(reword)、更改顺序(reorder)和删除提交(drop)。但是 rebase 会改变历史记录,因此仅应用于尚未推送到远程仓库的本地提交。
撤销提交有两种方法。git revert创建一个新的提交来撤销前一个提交的更改——保留历史记录的安全方式。git reset 从历史记录中删除提交——如果提交已推送则很危险。在团队开发中,只使用 git revert 来撤销已发布的提交。
常见问题
提交意味着在 Git 中创建更改的保存点。提交记录项目历史中文件的当前状态,描述更改了什么以及为什么。每个提交都有唯一标识符(SHA-1 哈希),并且是不可分割的更改链的一部分。
建议在每个逻辑上完成的更改之后提交,即使是小的更改。最佳频率——每个任务或修复 1 次提交。不必每 5 分钟提交一次,但也不应该将更改积累好几天而不提交一次。
原子提交包含一个逻辑更改——一个任务、一个错误修复或一个新功能。它不会在单个提交中混合不同的更改。原子提交的优点:易于撤销、历史清晰和轻松的代码审查。
要撤销已发布的提交,使用 git revert
可以,在推送到远程仓库之前。使用 git commit --amend 更改最后一次提交,或使用 git rebase -i 更改多个提交。推送后不建议更改历史——这可能导致其他开发人员出现问题,如果他们已推送了他们的更改。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。