Git 高级操作命令大全

6 阅读24分钟

Git 高级操作命令大全

Git 高级操作是指超出日常 addcommitpushpull 范畴的更复杂的命令,涵盖历史重写、调试定位、分支管理、子模块、垃圾回收、补丁操作、底层对象操作等多个维度。本文基于 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 switchgit 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-rebasegit rebase 执行前
post-checkoutgit checkout 完成后
post-mergegit merge 完成后
pre-pushgit 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 -sGPG 签署标签
git notes提交附加注释
导出git archive导出代码快照
git bundle离线传输仓库

💡 最佳实践建议:在执行任何重写历史(如 rebasefilter-branch)之前,确保已经备份或仅在个人分支上操作。对于已推送到公共仓库的历史,使用 revert 而非 reset 来撤销更改,避免影响协作者。团队协作中,使用 --force-with-lease 替代 --force 进行强制推送,以防止意外覆盖他人的工作。