Как удалить все файлы в репозитории Git, которых нет в рабочем каталоге? - PullRequest
13 голосов
/ 07 сентября 2011

Я нахожусь в процессе разделения старого набора приложений, который изначально находился в одном хранилище Subversion.

Я преобразовал его в Git-репозиторий и удалил то, что мне не нужно, но я хотел бы уменьшить репозиторий, избавившись от исторических данных, связанных с удаленными файлами (исходный репозиторий будет поддерживается для справочных целей, поэтому в новой не требуется).

В идеале я хотел бы пройти через весь репозиторий и удалить все файлы или папки, отсутствующие в рабочем каталоге, а также любую историю, связанную с ними. Это оставило бы меня с содержимым HEAD и историей коммитов, влияющих на эти файлы. Однако я не нашел способа сделать это (сирота HEAD не помогает, поскольку не сохраняет историю).

Возможно ли это? Я знаю, как удалить один файл или папку из всей истории с помощью git-filter-branch, но слишком много файлов и папок, чтобы это было практическим подходом ... если только не существует способа фильтрации всех файлов, отсутствующих в HEAD

Ответы [ 3 ]

7 голосов
/ 13 сентября 2011

Вот как вы можете использовать git filter-branch, чтобы избавиться от всех файлов, которые вам не нужны:

  1. Получить список имен файлов, которые вы не хотитеВ истории появляются как старые имена, так и новые имена в случае переименования.Например, поместите их в файл с именем toberemoved.txt

  2. Запустите git filter-branch следующим образом:

    $ git filter-branch --tree-filter "rm -f `cat toberemoved.txt`" branch1 branch2 ...
    

Вот соответствующий человекстраница из git filter-branch:

   --tree-filter <command>
       This is the filter for rewriting the tree and its contents. The
       argument is evaluated in shell with the working directory set to
       the root of the checked out tree. The new tree is then used as-is
       (new files are auto-added, disappeared files are auto-removed -
       neither .gitignore files nor any other ignore rules HAVE ANY
       EFFECT!).

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

Обновление:

Чтобы получить список файлов, которые присутствовали в прошлом, но отсутствовали в текущем рабочем каталоге, вы можете запустить следующее.Обратите внимание, что вам придется приложить дополнительные усилия, чтобы сохранить «историю перед переименованием» переименованных файлов:

$ git log --raw |awk '/^:/ { if (! printed[$6]) { print $6; printed[$6] = 1 }}'|while read f;do if [ ! -f $f ]; then echo Deleted: $f;fi;done

То, что $ 6 - это имя файла, на который повлиял коммит, показано в --raw mode of log.

См. параметр --diff-filter для git log, если вы хотите знать, что произошло ([D] eleted, [R] enamed, [M] odified и т. д.), чтобыкаждый файл для каждого коммита.

Может быть, другие могут подсказать, как узнать предыдущее имя отслеживаемого файла в случае переименования.

3 голосов
/ 19 августа 2015

Подсказка ко второму ответу: "Возможно, другие могут подсказать, как узнать предыдущее имя отслеживаемого файла в случае переименования."

Это вернет файлыв вашем проекте и файлы, из которых они переименованы.

for file in `git ls-files`; do git log --follow --name-only --pretty=format: $file | sort -n -b | uniq | sed '/^\s*$/d'; done

Вы можете использовать их, чтобы исключить из списка.

Целое решение:

for file in `git ls-files`; do git log --follow --name-only --pretty=format: $file | sort -n -b | uniq | sed '/^\s*$/d'; done > current.txt

git log --raw |awk '/^:/ { if (! printed[$6]) { print $6; printed[$6] = 1 }}'|while read f;do if [ ! -f $f ]; then echo $f;fi;done | sort > hist.txt

diff --new-line-format="" --unchanged-line-format="" hist.txt current.txt > for_remove.txt

3 голосов
/ 07 сентября 2011

Я делал это пару раз - извлекал коммиты для одного файла и создавал из них новый репозиторий.Это выглядит примерно так:

$ c=10; for commit in $(git log --format=%h -- path/to/file|tac); do
      c=$((c+1))
      git format-patch -1 --stdout $commit > $c.patch
  done

Это создает файлы исправлений 11.patch, 12.patch и так далее.Затем я редактирую эти патчи (используя vim или perl, в зависимости от того, что лучше для работы), удаляя целые фрагменты для файлов, которые мне не интересны, и, возможно, исправляю имена в случае переименований в заголовке diff hunk.

Я бы использовал git am для исправлений в новом хранилище git.Если что-то не получается, тогда я запускаю новый репозиторий git, снова редактирую патчи и повторяю git am.

Причина, по которой я начинаю считать с 10, состоит в том, что я ленивый, чтобы добавить ведущийк последовательности патчей и для коммитов больше 99 я просто начинаю с 99.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...