How can I move a directory in a Git repo for all commits?

You can use the subdirectory filter to achieve this

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

EDIT 1: 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

While Ramkumar's answer is very helpful and worthwile, it will not work in many situations. For example, when you want to move a directory with other subdirectories to a new location.

For this, the man page contains the perfect command:

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

Just replace NEWSUBDIR with your desired new directory. You can also use nested dirs like dir1/dir2/dir3/-"