如何在Git仓库中移动所有提交的目录?

时间:2010-06-29 15:54:42

标签: git git-filter-branch

假设我有一个包含此目录结构的仓库:

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的一些魔法来实现这一点,但我还没弄清楚到底是怎么做到的。有什么想法吗?

3 个答案:

答案 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