如何重写分支,放弃对子文件夹的更改
How to rewrite a branch, discarding changes to a subfolder
我需要重写一个分支,丢弃对特定子文件夹(例如,其路径为 path/to/folder
)所做的所有更改及其在从指定的 start
修订版开始的一系列修订版之间的内容结束于 HEAD
。接受 start
修订版之前的更改。
我考虑过使用 git-filter-branch
来执行此操作,但不知道使用什么过滤器。我认为对每个提交的子文件夹使用 'git-reset' 可能有效,但是这个 post 让我质疑这种方法是否有效。
问题:如何重写上面第一段指定的分支?
将 git-filter-branch 与 --tree-filter
一起使用,可能与 --prune-empty
一起使用。整个命令序列可能是这样的:
GOOD_STATE=<some-revision>
DIR_TO_PRESERVE="relative/path/to/directory"
BRANCH_TO_REWRITE=<branch-to-rewrite>
export GOOD_STATE DIR_TO_PRESERVE BRANCH_TO_REWRITE
git filter-branch --tree-filter \
'rm -rf "${DIR_TO_PRESERVE}" && git checkout -f ${GOOD_STATE} -- "${DIR_TO_PRESERVE}"' \
--prune-empty ${BRANCH_TO_REWRITE} --not ${GOOD_STATE}
作为更快的替代方法,可以使用 --index-filter
。但是作为命令,您不应该使用 git rm...
因为这会完全删除路径。相反,您应该使用 git reset
:
重置给定文件夹的索引
git filter-branch --index-filter \
'git reset -q ${GOOD_STATE} -- "${DIR_TO_PRESERVE}"'' \
--prune-empty ${BRANCH_TO_REWRITE} --not ${GOOD_STATE}
为了加快速度,可以暂时将存储库复制到更快的文件系统(为此,我在 Linux 上使用了 tmpfs
,9007 次提交已使用 --index-filter 在 14 中重写最少 37 秒)。
最终起作用的是使用 git-filter-branch
结合 git rm
删除提交中添加的新文件和 'git checkout' 恢复状态。
git filter-branch -f --prune-empty --index-filter 'git rm -rfq -- path/to/subdir && git checkout -f <the-good-state-sha1> -- path/to/subdir' -- start..HEAD
这里 start
是起始提交,<the-good-state-sha1>
是 start
的父提交的哈希值。 注意:如图所示,path/to/subdir
需要指定两次,一次在rm
命令中,一次在checkout
命令中。
我需要重写一个分支,丢弃对特定子文件夹(例如,其路径为 path/to/folder
)所做的所有更改及其在从指定的 start
修订版开始的一系列修订版之间的内容结束于 HEAD
。接受 start
修订版之前的更改。
我考虑过使用 git-filter-branch
来执行此操作,但不知道使用什么过滤器。我认为对每个提交的子文件夹使用 'git-reset' 可能有效,但是这个 post 让我质疑这种方法是否有效。
问题:如何重写上面第一段指定的分支?
将 git-filter-branch 与 --tree-filter
一起使用,可能与 --prune-empty
一起使用。整个命令序列可能是这样的:
GOOD_STATE=<some-revision>
DIR_TO_PRESERVE="relative/path/to/directory"
BRANCH_TO_REWRITE=<branch-to-rewrite>
export GOOD_STATE DIR_TO_PRESERVE BRANCH_TO_REWRITE
git filter-branch --tree-filter \
'rm -rf "${DIR_TO_PRESERVE}" && git checkout -f ${GOOD_STATE} -- "${DIR_TO_PRESERVE}"' \
--prune-empty ${BRANCH_TO_REWRITE} --not ${GOOD_STATE}
作为更快的替代方法,可以使用 --index-filter
。但是作为命令,您不应该使用 git rm...
因为这会完全删除路径。相反,您应该使用 git reset
:
git filter-branch --index-filter \
'git reset -q ${GOOD_STATE} -- "${DIR_TO_PRESERVE}"'' \
--prune-empty ${BRANCH_TO_REWRITE} --not ${GOOD_STATE}
为了加快速度,可以暂时将存储库复制到更快的文件系统(为此,我在 Linux 上使用了 tmpfs
,9007 次提交已使用 --index-filter 在 14 中重写最少 37 秒)。
最终起作用的是使用 git-filter-branch
结合 git rm
删除提交中添加的新文件和 'git checkout' 恢复状态。
git filter-branch -f --prune-empty --index-filter 'git rm -rfq -- path/to/subdir && git checkout -f <the-good-state-sha1> -- path/to/subdir' -- start..HEAD
这里 start
是起始提交,<the-good-state-sha1>
是 start
的父提交的哈希值。 注意:如图所示,path/to/subdir
需要指定两次,一次在rm
命令中,一次在checkout
命令中。