Как я могу переместить каталог в репозитории 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 чтобы сделать это, но я не выяснил, как именно это сделать. Есть идеи?

4 ответа

Решение

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

 $ 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

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

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

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/-"

Создан общий скрипт для произвольных ходов / переименований: 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 во всех коммитах текущей ветки

мерзавец filter-branchобескуражен. Вы можете использовать гит filter-repoгораздо удобнее:

      git filter-repo --path-rename blog/_posts:_posts`

Смотрите здесь.

Также обратите внимание, что установка каким -то образом нарушена, и вам нужно установить из pip и добавить git-filter-repoк $PATH

Другие вопросы по тегам