2010-06-29 5 views
53

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

ответ

68

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

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

EDIT 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 
+3

Это также * намного * быстрее использовать' --index-filter', так как он не должен проверять дерево. – Cascabel

+6

Да, индекс -filter работает быстрее, но это не сработает, потому что показанные команды не влияют на индекс. Вам нужно делать манипуляции с индексами, только если вы хотите использовать индексный фильтр (например, 'git rm --cached' вместо' rm') – sehe

+0

Можно ли хранить теги тоже? Похоже, они ушли в моем случае. – Michael

31

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

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

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

+9

И так как это не сразу видно из рассмотрения этой команды или результирующих ошибок, \ t не работает k по версии ss os x. Существует много способов обойти это, но, возможно, самое быстрое удаление \ t и замена его на литеральную вкладку, набрав ctrl-v, . –

+2

Как вы определяете исходную папку, или это просто перемещает всю ветвь? Когда я пытаюсь запустить это из папки, которую я хотел бы переместить, я получаю «Вам нужно запустить эту команду из верхнего уровня рабочего дерева» – joshcomley

+1

Что делает команда 'sed'? Я пробую это в Windows и нуждаюсь в альтернативе. – Lucius

Смежные вопросы