Skip to content

提交更改

概述

提交(Commit)是 Git 版本控制的核心操作。每次提交都会保存项目在某一时刻的完整快照,并记录提交者、时间、提交信息等元数据。良好的提交习惯对于项目管理和团队协作至关重要。

本章将详细介绍如何创建提交、编写规范的提交信息、修改提交,以及一些高级提交技巧。

git commit 提交

基本用法

bash
# 提交暂存区的修改
git commit -m "提交信息"

# 输出示例
[main abc1234] 提交信息
 2 files changed, 10 insertions(+), 2 deletions(-)
 create mode 100644 newfile.txt

# 打开编辑器编写提交信息
git commit

# 提交所有已跟踪文件的修改(跳过暂存)
git commit -a -m "提交信息"
# 或
git commit -am "提交信息"

提交选项

bash
# 指定提交信息
git commit -m "feat: 添加用户登录功能"

# 多行提交信息
git commit -m "feat: 添加用户登录功能" -m "详细描述:
- 实现用户名密码登录
- 添加登录状态保持
- 集成第三方登录"

# 添加所有已跟踪文件的修改并提交
git commit -a -m "fix: 修复登录验证 bug"

# 修改最后一次提交
git commit --amend -m "新的提交信息"

# 修改最后一次提交但不修改提交信息
git commit --amend --no-edit

# 允许空提交
git commit --allow-empty -m "空提交"

# 指定作者
git commit --author="Name <email@example.com>" -m "提交信息"

# 指定日期
git commit --date="2024-01-15 10:00:00" -m "提交信息"

# 签名提交
git commit -S -m "签名提交"

# 模板提交
git commit -t .git/COMMIT_TEMPLATE

提交流程

bash
# 标准提交流程

# 1. 查看当前状态
git status

# 2. 添加修改到暂存区
git add .

# 3. 查看暂存内容
git diff --staged

# 4. 提交
git commit -m "feat: 添加新功能"

# 5. 查看提交历史
git log --oneline -5

# 6. 推送到远程
git push

提交信息规范

约定式提交(Conventional Commits)

bash
# 格式
<type>(<scope>): <subject>

<body>

<footer>

# 示例
feat(auth): 添加用户登录功能

- 实现用户名密码登录
- 添加登录状态保持
- 集成第三方登录

Closes #123

类型(Type)

类型说明示例
feat新功能feat(user): 添加用户注册功能
fix修复 bugfix(auth): 修复登录验证失败问题
docs文档变更docs: 更新 README 文件
style代码格式(不影响功能)style: 格式化代码缩进
refactor重构refactor(user): 重构用户验证逻辑
perf性能优化perf: 优化数据库查询性能
test测试相关test(user): 添加用户模块单元测试
build构建系统build: 更新 webpack 配置
ciCI 配置ci: 添加 GitHub Actions 配置
chore其他修改chore: 更新依赖版本
revert回滚提交revert: 回滚登录功能

范围(Scope)

bash
# 范围表示提交影响的模块或组件

# 常见范围
feat(auth): 添加登录功能
feat(user): 添加用户管理
feat(api): 添加 API 接口
feat(ui): 更新界面样式
feat(db): 优化数据库查询

# 多个范围
feat(auth,api): 统一认证接口

主题(Subject)

bash
# 主题是提交信息的简短描述

# 好的主题
feat(user): 添加用户头像上传功能
fix(login): 修复密码验证逻辑错误
docs: 更新安装文档

# 不好的主题
fix bug
update
修改文件
添加功能

# 规则:
# 1. 使用祈使句(添加、修复、更新)
# 2. 首字母小写
# 3. 不以句号结尾
# 4. 不超过 50 个字符

正文(Body)

bash
# 正文详细描述提交内容

feat(user): 添加用户头像上传功能

- 支持 JPG、PNG、GIF 格式
- 限制文件大小不超过 2MB
- 自动生成缩略图
- 支持裁剪和旋转

# 规则:
# 1. 与主题空一行
# 2. 使用祈使句
# 3. 解释做了什么、为什么做
bash
# 页脚用于关联 Issue 或标记破坏性变更

# 关联 Issue
Closes #123
Fixes #456
Refs #789

# 破坏性变更
BREAKING CHANGE: 登录接口参数格式变更

# 多个 Issue
Closes #123, #456, #789

完整示例

bash
feat(auth): 添加 OAuth2 登录支持

- 支持 Google 登录
- 支持 GitHub 登录
- 支持 GitLab 登录
- 添加登录回调处理
- 实现登录状态同步

BREAKING CHANGE: 登录接口参数格式变更
- 旧格式: { username, password }
- 新格式: { provider, token }

迁移指南:
1. 更新前端登录表单
2. 修改 API 调用方式
3. 更新测试用例

Closes #123

修改提交

修改最后一次提交信息

bash
# 方法 1:使用 --amend
git commit --amend -m "新的提交信息"

# 方法 2:打开编辑器修改
git commit --amend

# 方法 3:只修改提交,不改信息
git commit --amend --no-edit

# 示例:添加遗漏的文件
git add forgotten-file.txt
git commit --amend --no-edit

修改历史提交信息

bash
# 使用交互式 rebase 修改历史提交

# 修改最近 3 次提交
git rebase -i HEAD~3

# 编辑器中显示
pick abc1234 feat: 功能 A
pick def5678 feat: 功能 B
pick ghi9012 feat: 功能 C

# 将要修改的提交前的 pick 改为 reword
reword abc1234 feat: 功能 A
pick def5678 feat: 功能 B
pick ghi9012 feat: 功能 C

# 保存后会打开编辑器修改每个提交信息

合并多个提交

bash
# 使用交互式 rebase 合并提交

git rebase -i HEAD~3

# 编辑器中
pick abc1234 feat: 功能 A
squash def5678 feat: 功能 B
squash ghi9012 feat: 功能 C

# 保存后编辑合并后的提交信息
feat: 添加用户管理功能

- 功能 A
- 功能 B
- 功能 C

重新排序提交

bash
# 使用交互式 rebase 重新排序

git rebase -i HEAD~3

# 原始顺序
pick abc1234 feat: 功能 A
pick def5678 feat: 功能 B
pick ghi9012 feat: 功能 C

# 调整顺序
pick ghi9012 feat: 功能 C
pick abc1234 feat: 功能 A
pick def5678 feat: 功能 B

删除提交

bash
# 方法 1:使用 rebase
git rebase -i HEAD~3

# 将要删除的提交改为 drop
drop abc1234 feat: 要删除的功能
pick def5678 feat: 保留的功能

# 方法 2:使用 reset
git reset --hard HEAD~1

# 方法 3:使用 revert(推荐用于已推送的提交)
git revert abc1234

跳过暂存提交

使用 -a 参数

bash
# 提交所有已跟踪文件的修改
git commit -a -m "fix: 修复 bug"

# 简写
git commit -am "fix: 修复 bug"

# 注意:
# - 只会提交已跟踪文件的修改
# - 新文件不会被提交
# - 删除的文件会被提交

区别对比

bash
# 标准流程
git add .
git commit -m "message"

# 跳过暂存
git commit -am "message"

# 区别:
# 1. git add . 会添加所有文件(包括新文件)
# 2. git commit -a 只会提交已跟踪文件的修改

适用场景

bash
# 适合使用 -a 的场景
# 1. 小型修改
git commit -am "fix: 修复 typo"

# 2. 快速修复
git commit -am "fix: 修复紧急 bug"

# 3. 单文件修改
git commit -am "docs: 更新文档"

# 不适合使用 -a 的场景
# 1. 需要部分提交
# 2. 有新文件需要添加
# 3. 需要仔细检查暂存内容

高级提交技巧

签名提交

bash
# 配置 GPG 签名
git config --global user.signingkey ABC12345

# 签名提交
git commit -S -m "签名提交"

# 自动签名所有提交
git config --global commit.gpgsign true

# 验证签名
git log --show-signature

指定作者和日期

bash
# 指定作者
git commit --author="Name <email@example.com>" -m "message"

# 指定日期
git commit --date="2024-01-15 10:00:00 +0800" -m "message"

# 使用相对日期
git commit --date="yesterday" -m "message"
git commit --date="2 days ago" -m "message"

# 组合使用
git commit --author="Name <email>" --date="2024-01-15" -m "message"

使用提交模板

bash
# 创建提交模板
cat > ~/.git-commit-template << 'EOF'
# <type>(<scope>): <subject>
# 
# <body>
#
# <footer>

# Type: feat, fix, docs, style, refactor, test, chore
# Scope: auth, user, api, ui, db
# Subject: 简短描述(不超过50字符)
EOF

# 配置模板
git config --global commit.template ~/.git-commit-template

# 使用模板
git commit

提交钩子

bash
# pre-commit 钩子示例
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash

# 检查 PHP 语法
FILES=$(git diff --cached --name-only --diff-filter=ACM -- '*.php')
if [ -n "$FILES" ]; then
    for FILE in $FILES; do
        php -l "$FILE" > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "PHP 语法错误: $FILE"
            exit 1
        fi
    done
fi

exit 0
EOF

chmod +x .git/hooks/pre-commit

# commit-msg 钩子示例
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/bash

COMMIT_MSG=$(cat "$1")
PATTERN="^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,}"

if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
    echo "提交信息格式错误!"
    echo "正确格式: type(scope): subject"
    echo "示例: feat(user): 添加用户登录功能"
    exit 1
fi
EOF

chmod +x .git/hooks/commit-msg

空提交

bash
# 创建空提交(用于触发 CI 或标记)
git commit --allow-empty -m "chore: 触发 CI 构建"

# 用途:
# 1. 触发 CI/CD 流水线
# 2. 标记重要节点
# 3. 开始新的功能分支

修复提交

bash
# 创建修复提交
git commit --fixup=abc1234

# 自动创建 fixup! 前缀的提交
# fixup! feat: 原始提交信息

# 自动合并 fixup 提交
git rebase -i --autosquash HEAD~3

引用提交

bash
# 在提交信息中引用其他提交
git commit -m "fix: 修复 abc1234 引入的问题"

# 使用完整哈希
git commit -m "fix: 修复 abc1234567890 引入的问题"

# 使用短哈希
git commit -m "fix: 修复 abc1234 引入的问题"

提交最佳实践

提交粒度

bash
# 好的提交:小而专注
git commit -m "feat(auth): 添加登录表单验证"
git commit -m "feat(auth): 实现登录 API 接口"
git commit -m "feat(auth): 添加登录状态保持"

# 不好的提交:大而杂
git commit -m "feat: 完成整个用户系统"

# 原则:
# 1. 每个提交只做一件事
# 2. 提交应该是原子操作
# 3. 可以独立回滚

提交频率

bash
# 推荐频率:
# 1. 完成一个小功能就提交
# 2. 修复一个 bug 就提交
# 3. 重构一个模块就提交

# 不推荐:
# 1. 一天只提交一次
# 2. 积累大量修改后一次性提交
# 3. 提交未完成的代码

提交前检查

bash
# 提交前检查清单

# 1. 查看状态
git status

# 2. 查看差异
git diff --staged

# 3. 运行测试
npm test
# 或
php artisan test

# 4. 检查代码风格
npm run lint
# 或
./vendor/bin/phpcs

# 5. 确认提交内容
git status -s

# 6. 编写提交信息
git commit

常见问题

问题 1:提交信息写错了

bash
# 修改最后一次提交信息
git commit --amend -m "正确的提交信息"

# 修改历史提交信息
git rebase -i HEAD~3
# 将 pick 改为 reword

问题 2:遗漏了文件

bash
# 添加遗漏的文件
git add forgotten-file.txt

# 修改最后一次提交
git commit --amend --no-edit

问题 3:提交了错误的文件

bash
# 撤销最后一次提交(保留修改)
git reset --soft HEAD~1

# 撤销最后一次提交(丢弃修改)
git reset --hard HEAD~1

# 创建反向提交(已推送的情况)
git revert HEAD

问题 4:提交到了错误的分支

bash
# 方法 1:cherry-pick
git checkout correct-branch
git cherry-pick abc1234
git checkout wrong-branch
git reset --hard HEAD~1

# 方法 2:创建新分支
git branch correct-branch
git reset --hard HEAD~1
git checkout correct-branch

问题 5:提交历史太乱

bash
# 使用交互式 rebase 整理
git rebase -i HEAD~10

# 常用操作:
# - squash: 合并提交
# - reword: 修改信息
# - drop: 删除提交
# - edit: 编辑提交

总结

提交命令速查

bash
# 基本提交
git commit -m "message"           # 提交暂存区
git commit -am "message"          # 提交已跟踪文件

# 修改提交
git commit --amend -m "message"   # 修改最后一次提交
git commit --amend --no-edit      # 不修改信息

# 高级选项
git commit -S -m "message"        # 签名提交
git commit --allow-empty          # 空提交
git commit --fixup=abc1234        # 修复提交

提交信息规范

bash
# 格式
<type>(<scope>): <subject>

<body>

<footer>

# 示例
feat(auth): 添加用户登录功能

- 实现用户名密码登录
- 添加登录状态保持

Closes #123

下一步

掌握提交操作后,建议继续学习: