2010-10-28 4 views
50

У меня есть проект под git. Однажды я переместил все файлы проекта из текущего каталога в foo/bar/ по проекту. Я сделал это, используя git mv. Затем я добавил еще несколько файлов и внес некоторые изменения в уже существующие файлы.Как переписать историю, чтобы все файлы, кроме тех, которые я уже переместил, находятся в подкаталоге?

В результате теперь, когда я смотрю на историю foo/bar/file.c, я могу видеть изменения, которые я сделал после того, как переместил файл.

Я попытался исправить это различными способами (filter-branch с фильтром подкаталогов и т. Д.), Но ничего не помогло, поэтому я довольно сложен здесь. Буду признателен за любую помощь, которую вы можете мне дать. Спасибо!

ответ

85

Чтобы переписать историю с файлами переехал:

Если вы хотите историю проекта, чтобы выглядеть, как будто все файлы всегда были в каталоге foo/bar, то вам необходимо сделать небольшую операцию. Используйте git filter-branch с «деревом фильтром», чтобы переписать коммиты так, чтобы в любом месте foo/bar не существует, он будет создан, и все файлы будут перемещены на него:

git filter-branch --prune-empty --tree-filter ' 
if [ ! -e foo/bar ]; then 
    mkdir -p foo/bar 
    git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar 
fi' 

Теперь история будет записана, как если бы все файлы были всегда находится в foo/bar.

Чтобы увидеть историю перемещенного файла:

Если вы просто хотите увидеть историю файла, который был перемещен или переименован в какой-то момент в прошлом, а затем просто использовать опцию --follow для git log:

git log --follow foo/bar/file.c 
+1

@ Александр: Вы можете попробовать поставить однострочный (все в одинарных кавычках) в реальном скрипте с линией bash shebang. Я думаю, что 'filter-branch', вероятно, пытается запустить это в' sh', а не 'bash'. – Cascabel

+0

Я сделал некоторый прогресс. Кажется, что двойные скобки в выражении if вызывают эту ошибку. Одиночные скобки работают лучше, но все равно не работают. Проблема в том, что до того, как я переместил все в foo/bar /, у меня был каталог с именем foo с некоторым контентом в проекте. Так что теперь он жалуется, что «не может переместить' foo »в подкаталог сам по себе,' foo/bar/foo '. –

+0

@Alexander: Вам просто нужно настроить сценарий соответственно. Что-то вроде: 'if [[! -e foo/bar]]; затем mkdir -p foo/bar; git ls-tree - имя-только $ GIT_COMMIT | grep -v^foo $ | xargs -I файлы mv файлы foo/bar; fi' Использует grep для фильтрации 'foo' из списка файлов, которые нужно переместить. Обратите внимание, что я также предполагаю, что подкаталог 'bar' никогда не существовал, пока вы не переместили все под ним. Если это не так, тогда вам также нужно будет учитывать это в скрипте. –

6

Чтобы обернуть вещи здесь краткий обзор того, что я сделал. Команда, которая работала для меня было:

if [ ! -e foo/bar ]; then mkdir -p foo/bar; git ls-tree --name-only $GIT_COMMIT | grep -v ^foo$ | xargs -I files mv files foo/bar || echo ""; fi 

эхо команды, которые я добавил в конце убедиться, что даже если мв не может вся команда будет продолжать работать. Он не перемещал содержимое foo/bar/foo, но я могу жить с этим.

Большое спасибо Dan Moulding (!!!) и Jefromi за помощью.

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

  • Нет связанных вопросов^_^