如何在Git仓库中移动一个目录来进行所有的提交?

假设我有一个包含这个目录结构的repo:

repo/ blog/ _posts/ some-post.html another-file.txt 

我想将_posts移动到回购顶层,所以结构如下所示:

 repo/ _posts/ some-post.html another-file.txt 

git mv这个很简单,但是我想让历史看起来好像_posts 总是存在于repo的根目录下,我希望能够通过git log -- _posts/some-post.html来获取some-post.html的整个历史git log -- _posts/some-post.html 。 我想我可以用git filter-branch来实现这个function,但是我还没有弄清楚如何做到这一点。 有任何想法吗?

您可以使用子目录filter来实现此目的

  $ git filter-branch --subdirectory-filter blog/ -- --all 

编辑1:如果你不想有效地使_posts的根,使用树型filter,而不是:

  $ 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 

虽然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 

只需用您想要的新目录replaceNEWSUBDIR即可。 你也可以使用像dir1 / dir2 / dir3 / – 嵌套目录 – “