假设我有一个包含此目录结构的仓库:
repo/
blog/
_posts/
some-post.html
another-file.txt
我想将_posts
移到回购的顶层,因此结构将如下所示:
repo/
_posts/
some-post.html
another-file.txt
使用git mv
这很简单,但我想让历史记录看起来好像_posts
总是存在于回购的根目录中,我希望成为能够通过some-post.html
获取git log -- _posts/some-post.html
的完整历史记录。我想我可以使用git filter-branch
的一些魔法来实现这一点,但我还没弄清楚到底是怎么做到的。有什么想法吗?
答案 0 :(得分:90)
您可以使用子目录过滤器来实现此目的
$ git filter-branch --subdirectory-filter blog/ -- --all
编辑1:如果您不想有效地创建_posts
根,请使用树过滤器:
$ git filter-branch --tree-filter 'mv blog/_posts .' HEAD
编辑2:如果某些提交中不存在blog/_posts
,则上述操作将失败。请改用:
$ git filter-branch --tree-filter 'test -d blog/_posts && mv blog/_posts . || echo "Nothing to do"' HEAD
答案 1 :(得分:33)
虽然Ramkumar的答案非常有用且值得,但它在许多情况下都不起作用。 例如,当您要将包含其他子目录的目录移动到新位置时。
为此,手册页包含完美的命令:
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&NEWSUBDIR/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
只需将NEWSUBDIR替换为您想要的新目录即可。 您也可以使用嵌套目录,如dir1 / dir2 / dir3 / - “
答案 2 :(得分:1)
为任意移动/重命名创建了通用脚本:https://gist.github.com/xkr47/f766f4082112c086af63ef8d378c4304
示例:
git filter-mv 's!^!subdir/!'
➜在当前分支的所有提交中将所有文件移动到子目录“ subdir /”
git filter-mv 's!^foo/bar.txt!foo/barbar.txt!'
➜在当前分支的所有提交中将foo / bar.txt重命名为foo / barbar.txt