2012/08/09

git命令之git filter-branch

今天说说git里一个很重量级的命令——git filter-branch。
git filter-branch [--env-filter ] [--tree-filter ]
               [--index-filter ] [--parent-filter ]
               [--msg-filter ] [--commit-filter ]
               [--tag-name-filter ] [--subdirectory-filter ]
               [--prune-empty]
               [--original ] [-d ] [-f | --force]
               [--] [...]
这个命令会按照指定的方式(一系列过滤器,filter)修改给定的commit,几乎可以针对历史commit执行你想要的任何操作。比如,从历史中删除某个文件,修改commit message等。

如果你没有指定任何filter,那么git filter-branch则会原封不动的将所有历史重新commit一次。

改写历史后,所有的object都会有新的object name。因此,你将不能轻易的将改写后的branch推送到server端(non-fastforward issue)。请不要轻易使用该命令,除非你很清楚该命令对git repo的影响。

每次执行git filter-branch操作后,务必检查改写后的历史是否正确。为了避免因操作错误造repo损坏,git会在filter-branch操作实际改写历史时,自动将原refs备份到refs/original/下。

目前,git filter-branch支持以下filter
--env-filter
--tree-filter
--index-filter
--parent-filter
--msg-filter
--commit-filter
--tag-name-filter
--subdirectory-filter
当同时指定多个filter时,会按照上述列表中列出的先后顺序执行相应filter。在执行由filter设置的操作时,git会自动设置以下系统变量:
$GIT_COMMIT
$GIT_AUTHOR_NAME
$GIT_AUTHOR_EMAIL
$GIT_AUTHOR_DATE
$GIT_COMMITTER_NAME
$GIT_COMMITTER_EMAIL
$GIT_COMMITTER_DATE
这些变量包含了改写操作执行前当前commit的相关信息。

下面介绍几个git filter-branch的参数
--original  
使用此参数指定改写历史操作生成的历史备份的存放位置,默认位置为refs/original。 

-d 使用此参数指定要使用的临时目录的路径。默认使用.git-rewrite/。 
-f, --force 默认情况下,如果当前repo已有以refs/original/开头的refs,或者临时目录已经存在,则git filter-branch会拒绝执行。使用此参数以强制执行改写操作。 

示例 
以下两个命令都可以将filename指定的文件从历史中永久删除。
git filter-branch --tree-filter 'rm filename' HEAD
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

没有评论:

发表评论