views:

69

answers:

1

Let's say I have a repo that includes this directory structure:

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

I want to move _posts to the top level of the repo, so the structure will look like this:

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

This is simple enough with git mv, but I want to make the history look as though _posts always existed at the root of the repo, and I want to be able to get the entire history of some-post.html via git log -- _posts/some-post.html. I imagine I can use some magic with git filter-branch to accomplish this, but I haven't figured out exactly how to do that. Any ideas?

+2  A: 

Hi,

You can use the subdirectory filter to achieve this

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

EDIT: If you don't want to effectively make _posts the root, use a tree-filter instead:

 $ git filter-branch --tree-filter 'mv blog/_posts .' HEAD

EDIT 2: If blog/_posts did not exist in some of the commits, the above will fail. Use this instead:

 $ git filter-branch --tree-filter 'test -d blog/_posts && mv blog/_posts . || echo "Nothing to do"' HEAD

EDIT 3: Feel free to replace --tree-filter with --index-filter everywhere. Thanks to Jefromi for pointing out that it's faster.

Ramkumar Ramachandra
I should note that I don't want to effectively make `_posts` the root, as I have other files in the root that I want to keep around. I updated my question to address this.
mipadi
Okay, use a tree filter then. I've updated the answer accordingly.
Ramkumar Ramachandra
That yields the following error: `Rewrite 99d2541b8796c307b2c30436ad78b429133c8d76 (1/380)mv: rename blog/_posts to ./_posts: No such file or directory`.
mipadi
Ah, your very first commit doesn't contain blog/_posts then. Will update the answer accordingly.
Ramkumar Ramachandra
It's also *much* faster to use `--index-filter`, since it doesn't have to check out the tree.
Jefromi