Git 高级操作命令大全
Git 高级操作是指超出日常 add、commit、push、pull 范畴的更复杂的命令,涵盖历史重写、调试定位、分支管理、子模块、垃圾回收、补丁操作、底层对象操作等多个维度。本文基于 Git 官方文档和实践经验,系统梳理每一个高级命令,并附上详细示例。
一、历史重写与撤销
1.1 git commit --amend —— 修改最近一次提交
修改最近一次提交的提交信息或内容。如果暂存区有新的更改,--amend 会将它们合并到上一次提交中。
# 修改最近一次提交的说明信息
git commit --amend -m "修正后的提交说明"
# 忘记添加某个文件,将其补充到上一次提交中
git add forgotten-file.txt
git commit --amend --no-edit # --no-edit 表示不修改提交信息
# 修改作者信息
git commit --amend --author="新作者名 <email@example.com>"
1.2 git rebase -i(交互式变基)—— 灵活重写提交历史
git rebase -i 是 Git 最强大的历史重写工具,可以对一系列提交进行合并、修改、删除、重新排序等操作。
# 交互式编辑最近 3 次提交
git rebase -i HEAD~3
# 将当前分支变基到 main 分支,并进行交互式编辑
git rebase -i main
进入交互界面后,每个提交前有一个指令,常用指令包括:
| 指令 | 说明 |
|---|---|
pick | 保留该提交 |
reword | 保留提交内容,修改提交信息 |
edit | 保留提交内容,但暂停以修改内容 |
squash | 将该提交合并到前一个提交中,并合并提交信息 |
fixup | 同 squash,但丢弃该提交的提交信息 |
drop | 删除该提交 |
exec | 运行 shell 命令 |
示例:将最后 3 个提交合并为 1 个
git rebase -i HEAD~3
# 在编辑器中,将第 2、3 个提交前的 pick 改为 squash 或 fixup
# 高级示例:变基时自动执行测试命令
git rebase -i --exec "npm test" HEAD~5 # 在每个提交后运行测试
1.3 git rebase(非交互式)—— 线性化分支历史
将当前分支的提交「移植」到目标分支的最新提交之上,使历史保持线性。
# 将当前分支变基到 main 分支
git rebase main
# 将 feature 分支变基到 main,但不必先切换分支
git rebase main feature
# --onto 参数:将某段提交移植到另一个分支
# 将 feature 分支中从 origin/main 之后的部分,移植到 main 分支上
git rebase --onto main origin/main feature
⚠️ 重要提醒:永远不要对已经推送到公共仓库的提交进行变基,这会重写公共历史,导致协作者的提交记录混乱。
1.4 git reflog —— 恢复「丢失」的提交
Git 会在本地记录 HEAD 和分支的所有移动历史(默认保留 90 天)。当误删分支或执行 git reset --hard 导致提交丢失时,reflog 可以找回这些提交。
# 查看引用日志
git reflog
# 输出示例:
# HEAD@{0}: reset: moving to HEAD~1
# HEAD@{1}: commit: 添加新功能
# HEAD@{2}: checkout: moving from feature to main
# HEAD@{3}: branch: 删除 feature
场景 1:恢复因 git reset --hard 丢失的提交
git reset --hard HEAD@{1} # 回到 reset 前的状态
场景 2:恢复误删的分支
git reflog # 找到被删分支对应的提交哈希
git branch recovered-branch abc1234 # 基于哈希重建分支
场景 3:结合 git fsck 恢复已过期的提交
git fsck --lost-found # 检查仓库完整性,列出无法访问的提交对象
1.5 git reset —— 重置当前分支到指定状态
| 模式 | HEAD | 暂存区 | 工作区 |
|---|---|---|---|
--soft | 移动 | 不变 | 不变 |
--mixed(默认) | 移动 | 重置 | 不变 |
--hard | 移动 | 重置 | 重置 |
# 撤销最近一次提交,保留修改在工作区(撤回到 add 后的状态)
git reset --soft HEAD~1
# 撤销最近一次提交,取消暂存,但保留工作区修改(撤回到 add 前)
git reset HEAD~1
# 完全丢弃最近 3 次提交的所有修改
git reset --hard HEAD~3
# 取消暂存特定文件(等同于 git restore --staged <file>)
git reset HEAD path/to/file
1.6 git revert —— 安全撤销已提交的更改
与 reset 不同,revert 创建一个新的提交来撤销指定提交的更改,不会改写历史,是公共分支上撤销更改的首选方式。
# 撤销某次提交,生成一个新的撤销提交
git revert abc1234
# 撤销最近一次提交(不自动提交,方便多个撤销合并)
git revert HEAD --no-commit
git revert HEAD~1 --no-commit
git commit -m "Revert last two commits"
1.7 git restore —— 恢复工作区或暂存区文件
Git 2.23+ 引入的新命令,用于替代 git checkout 的部分文件操作功能。
# 将工作区文件恢复到暂存区的状态(丢弃工作区的修改)
git restore file.txt
# 将暂存区文件恢复到 HEAD 的状态(取消暂存)
git restore --staged file.txt
# 同时取消暂存并丢弃工作区修改
git restore --source=HEAD --staged --worktree file.txt
# 从其他分支恢复文件
git restore --source=main file.txt
1.8 git filter-branch / git filter-repo —— 大规模重写历史
⚠️ 警告:Git 官方已不推荐使用 git filter-branch,因其性能差且容易出错,建议使用 git filter-repo 替代。
# 不推荐:git filter-branch 示例(从整个历史中删除某个文件)
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
# 推荐:git filter-repo(需单独安装)
# 删除文件
git filter-repo --path passwords.txt --invert-paths
# 替换邮箱地址
git filter-repo --email-callback '
return b"newemail@example.com" if email == b"oldemail@example.com" else email
'
常用过滤器(仅用于了解 git filter-branch):
| 过滤器 | 说明 |
|---|---|
--tree-filter | 每次检出后执行 shell 命令,修改文件树 |
--index-filter | 比 --tree-filter 快得多,直接修改索引 |
--env-filter | 修改提交的环境变量(作者、提交者等) |
--msg-filter | 修改提交信息 |
--subdirectory-filter | 只保留指定子目录,将其提升为仓库根目录 |
二、调试与二分查找
2.1 git bisect —— 二分查找定位 Bug
git bisect 使用二分查找算法,在 O(log n) 次检出中精确定位引入 Bug 的提交。
# 启动二分查找会话
git bisect start
# 标记当前版本为坏版本
git bisect bad
# 标记已知的好版本(commit-id 可以是标签、提交哈希或分支名)
git bisect good v1.0
# Git 自动检出中间提交,测试后标记 good 或 bad
# 测试当前版本后
git bisect good # 当前版本无 Bug
# 或
git bisect bad # 当前版本有 Bug
# 重复直到找到引入 Bug 的提交
# 结束二分查找,回到原来的分支
git bisect reset
高级用法:使用 git bisect run 自动执行测试脚本
# 启动并指定边界
git bisect start HEAD v1.0
# 自动运行测试脚本
git bisect run npm test
# 或
git bisect run python test_bug.py
自定义术语(适用于寻找性能提升等场景):
git bisect start --term-new=fast --term-old=slow
git bisect bad # 当前性能差
git bisect good v1.0 # v1.0 性能好
2.2 git blame —— 追溯每一行代码的出处
查看文件的每一行是谁在什么时候修改的。
# 查看文件每一行的作者和提交
git blame server.py
# 显示具体的提交哈希和日期
git blame -l server.py
# 只显示指定行范围
git blame -L 50,80 server.py
# 忽略空白字符变更
git blame -w server.py
# 查看某次提交之前的内容
git blame abc1234^ -- server.py
2.3 git grep —— 在仓库中高效搜索
在 Git 跟踪的文件中搜索内容,性能优于普通 grep,且自动遵守 .gitignore。
# 基本搜索
git grep "function_name"
# 忽略大小写
git grep -i "todo"
# 显示行号
git grep -n "error"
# 显示匹配行的上下文(前后各 2 行)
git grep -B 2 -A 2 "exception"
# 使用正则表达式
git grep '^\s*#include'
# 在特定提交中搜索
git grep "TODO" v2.0
# 搜索提交历史中的提交信息(而非文件内容)
git log --grep="fix bug"
三、高级分支与提交操作
3.1 git cherry-pick —— 挑选特定提交
将其他分支的一个或多个提交应用到当前分支,是选择性合并的利器。
# 挑选单个提交
git cherry-pick abc1234
# 挑选多个提交
git cherry-pick abc1234 def5678 ghi9012
# 挑选一个范围的提交
git cherry-pick abc1234..def5678
# 挑选但不自动提交(方便合并多个挑选)
git cherry-pick -n abc1234 def5678
# 编辑提交信息后再提交
git cherry-pick -e abc1234
# 合并多个提交为一个(高级用法)
git cherry-pick -n abc1234 def5678
git commit -m "合并两个提交的更改"
# 从分支挑选,保留原始作者信息
git cherry-pick -x abc1234 # -x 会在提交信息中记录来源
处理冲突:
# 解决冲突后
git add <conflicted-files>
git cherry-pick --continue
# 跳过当前有冲突的提交
git cherry-pick --skip
# 放弃整个 cherry-pick 操作
git cherry-pick --abort
3.2 git worktree —— 同时管理多个工作目录
在同一仓库中创建多个工作目录,每个目录可以检出不同的分支,无需频繁切换或暂存更改。
# 添加新的 worktree,检出现有分支
git worktree add ../project-feature feature/login
# 创建新分支并同时创建 worktree(一步完成)
git worktree add -b hotfix-urgent ../project-hotfix main
# 列出所有 worktree
git worktree list
# 移除 worktree
git worktree remove ../project-feature
# 清理已删除 worktree 的残留记录
git worktree prune
# 移动 worktree 到新位置
git worktree move ../old-path ../new-path
输出示例:
git worktree list
# /home/user/project abc1234 [main]
# /home/user/project-feature def5678 [feature/login]
# /home/user/project-hotfix 890abcd [hotfix-urgent]
核心要点:
- 同一分支不能被两个 worktree 同时检出
- 所有 worktree 共享同一套
.git对象库,磁盘空间占用极小 git fetch在一个 worktree 中执行后,所有 worktree 都能看到更新
3.3 git stash —— 临时保存工作区更改
将未提交的修改暂存起来,切换到干净的工作区。
# 保存当前修改(包括暂存区)
git stash
# 带描述信息保存
git stash push -m "WIP: 用户认证模块"
# 保存未跟踪文件
git stash -u
# 保存包括被忽略的文件
git stash -a
# 查看 stash 列表
git stash list
# stash@{0}: On main: WIP: 用户认证模块
# stash@{1}: WIP on feature: 821817d 修复登录问题
# 应用最新的 stash(保留 stash)
git stash apply
# 应用并删除 stash
git stash pop
# 应用指定的 stash
git stash apply stash@{1}
# 创建新分支并应用 stash
git stash branch new-feature stash@{0}
# 查看 stash 的内容
git stash show -p stash@{0}
# 删除指定的 stash
git stash drop stash@{1}
# 清空所有 stash
git stash clear
3.4 git cherry —— 查找未被合并的提交
比较两个分支,找出当前分支中尚未被另一个分支包含的提交。
# 找出 feature 分支中尚未合并到 main 的提交
git cherry main feature
# 输出格式:
# + 9a8b7c6d 提交说明 # '+' 表示在 feature 中但不在 main 中
# - 1a2b3c4d 提交说明 # '-' 表示已存在
3.5 git checkout(高级用法)—— 分离头指针与文件恢复
虽然 Git 2.23+ 推荐使用 git switch 和 git restore,但 git checkout 仍被广泛使用。
# 分离头指针状态(detached HEAD):检出某个提交而非分支
git checkout abc1234
# 从当前分支中恢复某个文件到指定版本
git checkout abc1234 -- path/to/file.txt
# 创建并切换到新分支(等价于 switch -c)
git checkout -b new-branch
# 强制切换(丢弃未提交的修改)
git checkout --force main
四、远程仓库高级操作
4.1 git fetch 高级用法
# 获取远程所有分支的更新但不合并
git fetch origin
# 获取特定远程分支
git fetch origin feature/login
# 获取所有远程仓库的更新
git fetch --all
# 清理本地已不存在的远程分支引用
git fetch --prune
# 获取特定标签
git fetch origin tag v1.2.3
# 浅层获取(只获取最近的 n 次提交)
git fetch --depth=1 origin main
4.2 git push 高级用法
# 删除远程分支
git push origin --delete feature/obsolete
# 删除远程标签
git push origin --delete tag v1.0-old
# 强制推送(慎用,会覆盖远程历史)
git push --force origin main
# 更安全的强制推送(如果远程有其他人推送过则拒绝)
git push --force-with-lease origin main
# 推送所有本地分支到远程
git push --all origin
# 推送所有标签
git push --tags
# 推送指定标签
git push origin v1.2.3
# 设置上游分支
git push -u origin feature/new-feature
4.3 git remote 高级用法
# 查看远程仓库详细信息
git remote show origin
# 重命名远程仓库
git remote rename origin upstream
# 移除远程仓库
git remote remove upstream
# 添加多个远程仓库
git remote add upstream https://github.com/original/repo.git
git remote add origin https://github.com/myfork/repo.git
# 修改远程仓库 URL
git remote set-url origin https://github.com/new-url/repo.git
# 添加远程仓库但不 fetch
git remote add -f origin https://github.com/repo.git # -f 添加后立即 fetch
# 设置远程分支的推送 URL(与拉取 URL 不同)
git remote set-url --push origin git@github.com:myfork/repo.git
五、子模块与子树
5.1 git submodule —— 管理项目中的外部依赖
子模块允许将一个 Git 仓库作为另一个仓库的子目录。
# 添加子模块
git submodule add https://github.com/user/lib.git libs/lib
# 克隆包含子模块的仓库
git clone --recursive https://github.com/user/project.git
# 或分步操作
git clone https://github.com/user/project.git
cd project
git submodule init # 初始化子模块配置
git submodule update # 拉取子模块内容
# 更新所有子模块到最新提交
git submodule update --remote
# 更新时合并子模块的更改
git submodule update --remote --merge
# 查看子模块状态
git submodule status
# 遍历所有子模块执行命令
git submodule foreach 'git checkout main'
# 同步子模块 URL 变更
git submodule sync
# 移除子模块(多步操作)
git submodule deinit -f libs/lib
git rm -f libs/lib
rm -rf .git/modules/libs/lib
5.2 git subtree —— 子模块的替代方案
git subtree 将外部仓库的内容直接合并到主仓库中,不产生独立的子模块引用。
# 添加子树
git subtree add --prefix=libs/lib https://github.com/user/lib.git main --squash
# 从子树拉取更新
git subtree pull --prefix=libs/lib https://github.com/user/lib.git main --squash
# 推送本地修改回子树仓库
git subtree push --prefix=libs/lib https://github.com/user/lib.git main
六、补丁与邮件工作流
6.1 git format-patch —— 生成补丁文件
将提交转换为补丁文件(.patch),适用于代码审查或离线传输。
# 生成最近 3 次提交的补丁
git format-patch -3
# 生成从 v1.0 到 HEAD 之间所有提交的补丁
git format-patch v1.0..HEAD
# 生成单个提交的补丁
git format-patch -1 abc1234
# 指定输出目录
git format-patch -o patches/ main..feature
# 给补丁文件添加编号前缀
git format-patch --numbered main..feature
# 包含标准输出(适合管道操作)
git format-patch --stdout main..feature > all.patch
# 生成从初始提交到 HEAD 的所有补丁
git format-patch --root
6.2 git am —— 应用邮箱格式的补丁
将 git format-patch 生成的补丁应用到当前分支,同时保留作者信息和提交信息。
# 应用单个补丁文件
git am 0001-fix-bug.patch
# 应用目录下的所有补丁
git am patches/*.patch
# 应用补丁时添加签名
git am --signoff < 0001-fix-bug.patch
# 应用补丁时保留原始日期
git am --committer-date-is-author-date < patch.patch
# 冲突处理
git am --abort # 放弃应用
git am --skip # 跳过当前补丁
git am --continue # 解决冲突后继续
git am --resolved # 标记冲突已解决并继续
6.3 git send-email —— 通过邮件发送补丁
将补丁通过电子邮件发送,是 Linux 内核等开源项目的标准协作方式。
# 基本用法
git send-email --to maintainer@example.com 0001-fix.patch
# 发送多个补丁
git send-email --to list@example.com *.patch
# 指定邮件主题前缀
git send-email --subject-prefix="PATCH v2" *.patch
# 添加抄送
git send-email --cc reviewer@example.com *.patch
# 配置 SMTP 服务器
git config --global sendemail.smtpserver smtp.gmail.com
git config --global sendemail.smtpuser your@gmail.com
# 使用 Gmail 发送
git send-email --smtp-server=smtp.gmail.com --smtp-server-port=587 \
--smtp-encryption=tls *.patch
七、仓库维护与优化
7.1 git gc —— 垃圾回收与仓库优化
执行仓库维护任务:压缩文件修订版本、删除不可达对象、打包引用等。
# 执行垃圾回收
git gc
# 激进模式(更彻底的压缩,但耗时更长)
git gc --aggressive
# 自动模式(Git 会在需要时自动运行)
git gc --auto
# 保留最近 2 周的 reflog 记录,其余修剪
git gc --prune=2.weeks.ago
7.2 git fsck —— 检查仓库完整性
验证 Git 对象数据库的连接性和有效性。
# 基本检查
git fsck
# 显示所有不可达的对象
git fsck --unreachable
# 检查时包含 HEAD 和索引
git fsck --cache
# 更详细的输出
git fsck --verbose
# 不检查 reflog
git fsck --no-reflogs
# 检查后列出所有丢失的对象(用于恢复)
git fsck --lost-found
7.3 git prune —— 清理不可达对象
删除无法从任何引用访问的对象。
# 修剪不可达对象
git prune
# 模拟运行(显示将要删除的对象)
git prune --dry-run
# 修剪且显示进度
git prune --verbose
# 修剪指定时间之前的对象
git prune --expire=2.weeks.ago
7.4 git repack —— 重新打包仓库
将松散的对象打包成 .pack 文件,提高仓库性能。
# 打包松散对象
git repack
# 创建更优化的打包(分离窗口增量)
git repack -a -d --depth=250 --window=250
# 打包时保留旧包文件
git repack -a -d -l
7.5 git reflog expire —— 管理引用日志
控制 reflog 的过期和清理。
# 删除所有 90 天前的 reflog 条目
git reflog expire --expire=90.days.ago --all
# 立即过期所有 reflog 条目
git reflog expire --expire=now --all
# 删除指定分支的 reflog
git reflog expire --expire=now --expire-unreachable=now refs/heads/feature
八、底层操作与管道命令
8.1 git cat-file —— 查看 Git 对象内容
查看 Git 对象的内容、类型或大小,是底层调试的利器。
# 查看对象的类型
git cat-file -t abc1234
# 查看对象的大小
git cat-file -s abc1234
# 查看对象的内容(美化输出)
git cat-file -p abc1234
# 批量操作模式
echo "abc1234" | git cat-file --batch
8.2 git rev-parse —— 解析 Git 对象标识符
将各种引用格式转换为 SHA-1 哈希值。
# 获取 HEAD 的 SHA-1 值
git rev-parse HEAD
# 获取分支的 SHA-1 值
git rev-parse main
# 获取提交的父提交
git rev-parse HEAD^
git rev-parse HEAD~3
# 验证对象是否存在且为提交类型
git rev-parse --verify HEAD^{commit}
# 获取当前分支名
git rev-parse --abbrev-ref HEAD
# 显示 Git 目录路径
git rev-parse --git-dir
# 显示工作区顶层目录
git rev-parse --show-toplevel
8.3 git ls-tree —— 列出树对象内容
显示树对象(目录)中的内容,相当于对 Git 对象执行 ls -a。
# 列出 HEAD 的根目录内容
git ls-tree HEAD
# 递归列出所有文件
git ls-tree -r HEAD
# 仅显示文件名
git ls-tree --name-only HEAD
# 显示指定目录下的内容
git ls-tree HEAD src/
# 自定义输出格式
git ls-tree --format='%(objectname) %(path)' HEAD
# 查看提交时的目录快照
git ls-tree abc1234
8.4 git show-ref —— 显示本地引用
列出本地仓库中的所有引用(分支、标签等)及其对应的提交 ID。
# 列出所有引用
git show-ref
# 只显示 head 引用(分支)
git show-ref --heads
# 只显示标签
git show-ref --tags
# 验证引用是否存在
git show-ref --verify refs/heads/main
# 显示引用并解引用标签
git show-ref --dereference
# 按模式过滤
git show-ref feature
8.5 git diff-tree —— 比较两个树对象
比较两个树对象之间的差异,常用于底层 diff 操作。
# 比较两个提交
git diff-tree abc1234 def5678
# 显示树之间的递归差异
git diff-tree -r abc1234 def5678
# 显示变更文件的统计信息
git diff-tree --stat abc1234 def5678
# 显示文件名列表(不显示内容)
git diff-tree --name-only abc1234 def5678
# 显示合并提交相对于所有父提交的差异
git diff-tree -c abc1234
8.6 git hash-object —— 计算 Git 对象哈希
从文件内容计算 SHA-1 哈希值,并可选地将内容写入对象数据库。
# 计算文件的哈希值(不写入对象库)
git hash-object file.txt
# 将文件内容写入对象库并返回哈希
git hash-object -w file.txt
# 从标准输入读取内容
echo "Hello Git" | git hash-object --stdin
# 从标准输入写入对象库
echo "Hello Git" | git hash-object -w --stdin
8.7 git mktree —— 从 ls-tree 输出创建树对象
从 ls-tree 格式的输入创建树对象。
# 创建树对象
echo "100644 blob abc1234 file.txt" | git mktree
# 从 ls-tree 输出重建树
git ls-tree HEAD | git mktree
8.8 git update-ref —— 安全地更新引用
直接操作 Git 引用(分支、标签等)。
# 更新分支引用
git update-ref refs/heads/feature abc1234
# 创建符号引用
git update-ref --symbolic refs/heads/alias refs/heads/main
# 删除引用
git update-ref -d refs/heads/obsolete
九、高级合并与冲突处理
9.1 git merge 高级选项
# 禁用快进合并(保留分支历史)
git merge --no-ff feature/login
# 压缩合并(将 feature 的所有提交压缩为一个提交)
git merge --squash feature/login
# 仅快进合并,否则失败
git merge --ff-only feature/login
# 使用不同的合并策略
git merge -s ours feature/login # 保留当前分支,忽略对方更改
git merge -s subtree libs/lib # 子树合并策略
# 合并时忽略空白差异
git merge -Xignore-space-change feature
# 合并时使用我们的版本处理冲突
git merge -Xours feature
# 合并时使用对方的版本处理冲突
git merge -Xtheirs feature
# 提交合并前验证签名
git merge --verify-signatures feature
9.2 git mergetool —— 使用图形化工具解决冲突
调用配置的合并工具来解决合并冲突。
# 启动合并工具解决冲突
git mergetool
# 指定使用特定的工具
git mergetool --tool=vimdiff
git mergetool --tool=meld
git mergetool --tool=kdiff3
# 信任返回码,自动接受工具解决的冲突
git mergetool --trust-exit-code
# 不提示,直接启动
git mergetool --no-prompt
配置合并工具:
# 全局设置默认合并工具
git config --global merge.tool vimdiff
# 配置工具路径
git config --global mergetool.vimdiff.path /usr/bin/vimdiff
# 设置合并后保留备份文件
git config --global mergetool.keepBackup false
9.3 git rerere —— 复用冲突解决方案
记录已解决的冲突,在将来遇到相同冲突时自动应用解决方案。
# 启用 rerere
git config --global rerere.enabled true
# 记录当前冲突的解决方案
git rerere
# 查看已记录的冲突解决方案
git rerere diff
# 查看 rerere 状态
git rerere status
# 清空 rerere 缓存
git rerere forget path/to/file
# 垃圾清理(自动清理过时的解决方案)
git rerere gc
十、标签与注释
10.1 高级标签操作
# 创建带注释的标签
git tag -a v1.0.0 -m "发布版本 1.0.0"
# 对旧提交添加标签
git tag -a v0.9.0 abc1234 -m "v0.9.0 发布候选"
# 签署标签(使用 GPG)
git tag -s v1.0.0 -m "签名的版本标签"
# 查看标签信息
git show v1.0.0
# 列出匹配模式的标签
git tag -l "v1.*"
# 删除本地标签
git tag -d v1.0.0-old
# 删除远程标签
git push origin --delete v1.0.0-old
# 推送标签到远程
git push origin v1.0.0
git push --tags # 推送所有标签
# 验证签名的标签
git tag -v v1.0.0
10.2 git notes —— 为提交添加注释
在不修改提交本身的情况下,为提交添加额外的注释信息。
# 为当前提交添加注释
git notes add -m "该提交修复了安全漏洞 CVE-2024-1234"
# 为指定提交添加注释
git notes add abc1234 -m "代码审查记录:需重构此部分"
# 查看提交的注释
git notes show abc1234
# 编辑现有注释
git notes edit abc1234
# 删除注释
git notes remove abc1234
# 列出所有注释
git notes list
# 在 git log 中显示注释
git log --show-notes
# 合并他人的注释
git notes merge refs/notes/commits
十一、仓库导出与打包
11.1 git archive —— 导出代码快照
将指定提交或分支的内容打包为 tar 或 zip 文件。
# 将当前 HEAD 导出为 tar 文件
git archive --format=tar HEAD > project.tar
# 导出为 zip 文件
git archive --format=zip HEAD > project.zip
# 导出到指定输出文件
git archive --output=project.zip HEAD
# 添加路径前缀(适合解压到指定目录)
git archive --format=tar --prefix=project-1.0/ HEAD | tar -x
# 导出指定分支
git archive --format=zip --output=feature.zip feature/login
# 导出指定标签
git archive --format=tar --prefix=myapp-v1.0/ v1.0.0 | gzip > myapp-v1.0.tar.gz
# 导出指定提交
git archive --format=zip abc1234 > snapshot.zip
# 只导出指定路径
git archive HEAD:src/ | tar -t
11.2 git bundle —— 离线传输 Git 对象
将 Git 对象打包成一个文件,用于无网络环境下的仓库传输。
# 创建完整仓库的 bundle
git bundle create repo.bundle --all
# 创建从 v1.0 到 master 的增量 bundle
git bundle create updates.bundle v1.0..master
# 创建指定分支的 bundle
git bundle create feature.bundle feature/login
# 验证 bundle 文件
git bundle verify updates.bundle
# 查看 bundle 中包含的引用
git bundle list-heads updates.bundle
# 从 bundle 克隆仓库
git clone updates.bundle new-repo
# 从 bundle 中 fetch
git fetch updates.bundle main:temp-branch
# 创建包含多个引用的 bundle
git bundle create mybundle.bundle main feature/login --tags
十二、配置与别名
12.1 git config 高级配置
# 查看所有配置
git config --list
git config --list --show-origin # 显示配置来源文件
# 查看特定配置
git config user.name
git config core.editor
# 设置配置作用域
git config --global core.editor "vim" # 全局
git config --system core.autocrlf true # 系统级
git config --local core.ignorecase false # 当前仓库
# 删除配置
git config --global --unset user.name
# 编辑配置文件
git config --global --edit # 编辑全局配置
git config --edit # 编辑当前仓库配置
# 设置别名(简化常用命令)
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all"
# 设置合并工具
git config --global merge.tool vimdiff
# 设置差异工具
git config --global diff.tool meld
# 设置提交模板
git config --global commit.template ~/.gitmessage.txt
12.2 实用别名示例
# 美化日志
git config --global alias.tree "log --graph --pretty=oneline --abbrev-commit --all"
# 查看最近一次提交
git config --global alias.last "log -1 HEAD"
# 查看所有分支的提交图
git config --global alias.graph "log --graph --all --oneline --decorate"
# 暂存所有变更并提交
git config --global alias.save "!git add -A && git commit -m 'WIP'"
# 撤销最后一次提交(保留更改)
git config --global alias.undo "reset --soft HEAD^"
# 查看未推送的提交
git config --global alias.unpushed "log origin/main..HEAD --oneline"
12.3 钩子(Hooks)
Git 钩子是在特定事件发生时自动执行的脚本,存放在 .git/hooks/ 目录下。
| 钩子名称 | 触发时机 |
|---|---|
pre-commit | 执行 git commit 前 |
prepare-commit-msg | 提交信息编辑器启动前 |
commit-msg | 提交信息已输入后 |
post-commit | 提交完成后 |
pre-rebase | git rebase 执行前 |
post-checkout | git checkout 完成后 |
post-merge | git merge 完成后 |
pre-push | git push 执行前 |
pre-receive | 服务端接收推送前 |
update | 服务端更新分支时 |
post-receive | 服务端接收推送后 |
# 启用示例钩子
cd .git/hooks/
cp pre-commit.sample pre-commit
# 编写 pre-commit 钩子(例如:检查代码格式)
# 内容示例:
#!/bin/sh
npm run lint
if [ $? -ne 0 ]; then
echo "代码格式检查失败,请修复后再提交"
exit 1
fi
十三、跨平台与兼容性
13.1 换行符处理
# 配置自动换行符转换
git config --global core.autocrlf true # Windows
git config --global core.autocrlf input # Mac/Linux
git config --global core.autocrlf false # 关闭自动转换
# 配置特定文件类型的换行符(通过 .gitattributes)
*.txt text=auto
*.js text eol=lf
*.bat text eol=crlf
*.png binary
13.2 大文件处理(Git LFS)
# 安装 Git LFS
git lfs install
# 跟踪大文件类型
git lfs track "*.psd"
git lfs track "*.zip"
# 查看跟踪的文件类型
git lfs track
# 查看 LFS 文件列表
git lfs ls-files
# 迁移现有仓库中的大文件到 LFS
git lfs migrate import --include="*.psd,*.zip"
# 推送 LFS 文件
git push origin main
速查表
| 分类 | 命令 | 核心功能 |
|---|---|---|
| 历史重写 | git commit --amend | 修改最近提交 |
git rebase -i | 交互式重写历史 | |
git reflog | 恢复丢失提交 | |
git reset --hard/--soft | 重置分支状态 | |
git revert | 安全撤销提交 | |
git filter-repo | 大规模历史重写 | |
| 调试 | git bisect | 二分查找 Bug |
git blame | 逐行追溯代码 | |
git grep | 仓库内容搜索 | |
| 分支操作 | git cherry-pick | 挑选提交 |
git worktree | 多工作目录并行开发 | |
git stash | 临时保存工作 | |
| 远程协作 | git push --force-with-lease | 安全强制推送 |
git fetch --prune | 清理远程引用 | |
| 子模块 | git submodule | 管理外部依赖 |
git subtree | 子树合并依赖 | |
| 补丁 | git format-patch | 生成补丁文件 |
git am | 应用邮箱格式补丁 | |
git send-email | 邮件发送补丁 | |
| 维护 | git gc | 垃圾回收与优化 |
git fsck | 检查仓库完整性 | |
git prune | 清理不可达对象 | |
| 底层 | git cat-file | 查看 Git 对象 |
git rev-parse | 解析引用标识符 | |
git ls-tree | 列出树对象内容 | |
git show-ref | 显示本地引用 | |
| 合并 | git mergetool | 图形化解冲突 |
git rerere | 复用冲突解决方案 | |
| 标签与注释 | git tag -s | GPG 签署标签 |
git notes | 提交附加注释 | |
| 导出 | git archive | 导出代码快照 |
git bundle | 离线传输仓库 |
💡 最佳实践建议:在执行任何重写历史(如
rebase、filter-branch)之前,确保已经备份或仅在个人分支上操作。对于已推送到公共仓库的历史,使用revert而非reset来撤销更改,避免影响协作者。团队协作中,使用--force-with-lease替代--force进行强制推送,以防止意外覆盖他人的工作。