超强命令:filter-branch
如果你需要以某种脚本化的方式重写大量提交(例如,全面修改你的电子邮件地址或从所有提交中删除某个文件),就需要filter-branch
,它能够大面积修改你的历史记录。
从所有提交中删除某个文件
filter-branch
是一个可以用来清洗整个历史记录的工具,要想从整个历史记录中删除名为passwords.txt的文件,可以使用filter-branch
的--tree-filter
选项,例如:
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
--tree-filter
选项会在每次检出项目后执行指定的命令,然后重新提交结果。要想在所有分支上执行filter-branch
,可以传入--all
选项。
将子目录设置为新的根目录
如果你从其他源代码导入,获得了一些没什么用的子目录(trunk、tags等)。如果想让trunk子目录成为新目录每次提交的根目录,如下可以做到:
git filter-branch --subdirectory-filter trunk HEAD
现在项目的根目录为trunk子目录,Git会自动删除所有与该子目录无关的提交。
全面修改邮箱地址
在开始工作之前忘记执行git config
设置自己的姓名和邮箱地址,或者在开源项目前需要将所工作电子邮件地址改成个人邮件地址,可以使用filter-branch
批处理修改多个提交中的电子邮件地址。
git filter-branch --commit-filter ' if [ "$GIT_AUTHOR_EMAIL" = "dewitt@localhost" ]; then GIT_AUTHOR_NAME="Dewitt"; GIT_AUTHOR_EMAIL="dewitt@example.com"; git commit-tree "$@"; else git commit-tree "$@"; fi' HEAD
这个命令会修改历史记录中所有提交的SHA-1,不仅仅是包含指定电子邮件地址的提交。
重置
三棵树
关于重置的操作,先用较简单的理解方法将Git视为三棵树的内容管理器。
- HEAD 最近提交的快照,下次提交的父提交
- 索引 预计的下一次提交的快照(暂存区)
- 工作目录 沙盒,在提交到索引并写入历史之前,可以随意修改
重置的步骤
- 移动HEAD指针的指向(如果指定了
--soft
,则在此停止) - 更新索引,取消暂存所有的东西
- 如果指定了
--hard
,更新工作目录。合并的高级用法
忽略空白字符
某些情况下,冲突与空白字符有关,因为每一行在一边被删除,而在另一边又被添加回来。默认情况下,Git将所有的这些行视为改动过的,因此它无法合并文件。如果你发现合并中出现了大量与空白字符有关的问题,你可以中止合并,然后加上-Xignore-all-space
或-Xignore-space-change
再重新进行合并。第一个选项完全忽略空白字符,第二个选项将单个或多个空白字符序列视为等同。rerere
rerere(reuse recorded resolution),使用该功能可以让Git记住一个块冲突的解决方案,如果下次再碰到相同类型的冲突,Git就可以自动解决。如果选用了一个已合并的分支,修复了一堆冲突后决定对其进行变基操作,这就不必再去解决同样的冲突了。运行如下命令启用:git config --global rerere.enabled true
如果需要大量的合并操作,或者经常变基,可以启用rerere功能减轻负担。