Git 不仅仅是一个版本控制工具,还提供了强大的高级操作功能,如历史重写、提交检索、数据块存储和恢复丢失的提交等。本章将深入探讨 git filter-branch
、git rev-list
、Git 交互式存储 以及 恢复丢失的提交。
20.1 使用 git filter-branch
git filter-branch
是 Git 提供的一个历史重写工具,允许批量修改 Git 提交历史,例如:
- 从历史记录中移除敏感信息(如 API Key、密码)。
- 规范化提交历史,例如修改作者信息。
- 重写文件路径,迁移项目到新的结构。
20.1.1 使用 git filter-branch
的例子
示例 1:从历史记录中移除某个文件
如果不小心提交了一个敏感文件 config.json
,可以使用以下命令从所有提交中移除该文件:
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch config.json" \
--prune-empty --tag-name-filter cat -- --all
然后强制推送更新到远程仓库(⚠️ 注意,这会改变历史,不建议用于已共享的分支):
git push --force --all
示例 2:批量修改提交作者信息
如果需要修改所有提交的作者信息:
git filter-branch --env-filter '
if [ "$GIT_AUTHOR_EMAIL" = "old@example.com" ]; then
export GIT_AUTHOR_NAME="New Name"
export GIT_AUTHOR_EMAIL="new@example.com"
fi
' --tag-name-filter cat -- --all
20.1.2 filter-branch
的滥用
⚠️ git filter-branch
会重写 Git 历史,不建议在多人协作的仓库中随意使用,否则可能导致分支混乱。
Git 官方推荐使用 git filter-repo
(更快、更安全):
git filter-repo --path config.json --invert-paths
20.2 我如何学会喜欢上 git rev-list
git rev-list
是 Git 提供的一个强大工具,可用于检索提交历史。它主要用于:
- 按日期、文件、提交范围查找特定提交。
- 统计提交数量,分析贡献度。
- 找到某个文件的最早提交版本。
20.2.1 基于日期的检出
查看最近 7 天的提交:
git rev-list --since="7 days ago" --all
查看 2023 年 1 月 1 日之后的所有提交:
git rev-list --after="2023-01-01" --all
查看 2022 年 12 月 31 日之前的所有提交:
git rev-list --before="2022-12-31" --all
20.2.2 获取文件的旧版本
如果想要找到某个文件的第一个提交,可以使用:
git rev-list --max-parents=0 HEAD -- file.txt
如果需要恢复某个文件的旧版本:
git checkout $(git rev-list -n 1 HEAD -- file.txt) -- file.txt
20.3 数据块的交互式暂存
Git 允许交互式暂存(Interactive Staging),使开发者可以选择性地提交代码块,而不是整个文件。
20.3.1 交互式暂存的基本操作
运行 git add -p
进入交互模式:
git add -p
Git 会逐块显示文件变更,并提供以下选项:
y
:暂存该部分n
:跳过该部分s
:分割当前块e
:编辑该块
示例:
$ git add -p
diff --git a/main.py b/main.py
@@ -1,5 +1,6 @@
def main():
print("Hello, world!")
+ print("New feature added")
Stage this hunk [y,n,q,a,d,s,e,?]?
如果不想提交 print("New feature added")
,可以按 n
跳过该块。
20.3.2 git stash
结合数据块暂存
如果需要暂存部分更改,但不想提交,可以结合 git stash
:
git stash push -p
然后可以随时恢复:
git stash pop
20.4 恢复丢失的提交
有时候,我们可能会误用 git reset --hard
,导致提交丢失。Git 提供了几种方法来恢复这些提交。
20.4.1 git fsck
命令
git fsck
用于检查 Git 数据库的完整性,同时可以列出丢失的提交:
git fsck --lost-found
20.4.2 重新连接丢失的提交
如果 fsck
显示了丢失的提交哈希,例如 a1b2c3d
,可以使用 git reflog
查找更详细的历史记录:
git reflog
然后使用 git checkout
恢复提交:
git checkout -b recovery-branch a1b2c3d
如果 git reflog
无法找到丢失的提交,可以尝试 git log
搜索 dangling commit:
git log --all --graph --decorate
如果找到了丢失的提交哈希,可以使用:
git cherry-pick <commit-hash>
结论
本章介绍了 Git 的高级操作,包括:
git filter-branch
(重写历史)git rev-list
(检索提交)- 数据块交互式暂存(
git add -p
) - 恢复丢失的提交(
git reflog
、git fsck
)
这些功能适用于 Git 高级用户,能够帮助开发者更高效地管理代码历史,并在紧急情况下恢复重要数据。