Как переместить каталог в репозиторий Git для всех коммитов?

Скажем, у меня есть репо, которое включает эту структуру каталогов:

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, чтобы достичь этого, но я не понял, как это сделать. Любые идеи?

Ответ 1

Вы можете использовать фильтр подкаталогов для достижения этого

 $ 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

Ответ 2

В то время как ответ Рамкумара очень полезен и заслуживает внимания, он не будет работать во многих ситуациях. Например, если вы хотите переместить каталог с другими подкаталогами в новое место.

Для этого man-страница содержит идеальную команду:

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 на нужный новый каталог. Вы также можете использовать вложенные dirs, такие как dir1/dir2/dir3/- "