2012-04-09 3 views
168

Я работал над репозиторием на моей учетной записи GitHub, и это проблема, на которую я наткнулся.Удалить папку и ее содержимое из истории git/GitHub

  • Node.js проект с папкой с несколькими НПХ установленных пакетами
  • пакетов были в node_modules папке
  • Добавлены эта папка мерзавца хранилище и протолкнул код GitHub (не думая о NPM части в то время)
  • Понял, что вы на самом деле не нужно, что папка, чтобы быть частью кода
  • Удаляется эта папка, отодвинул его

В этом случае размер общей репликации git был около 6MB, где фактический код (кроме этой папки) составлял только около 300 KB.

Теперь, что я ищу в конце, это способ избавиться от деталей этой папки пакета из истории git, поэтому, если кто-то ее клонирует, им не нужно загружать историю с размером в 6 Мб, где только реальные файлы они будут получать от последней фиксации будет 300 КБ.

Я посмотрел возможные решения для этого и пытались эти 2 метода

сутью казалось, он работал, где после выполнения сценария, его показал, что он избавился от этой папки, и после этого он показал, что было изменено 50 различных коммитов. Но это не позволило мне нажать этот код. Когда я попытался нажать, он сказал Branch up to date, но показал, что 50 коммитов были изменены на git status. Другие 2 метода тоже не помогли.

Теперь, хотя он показал, что он избавился от истории этой папки, когда я проверил размер этого репо на моем локальном хосте, он все еще находился около 6 МБ. (Я также удалил папку refs/original, но не увидел изменения размера репо).

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

Допустим, решение представлено для этого и применяется на моем локальном хосте, но не может быть воспроизведено в этом репо GitHub, можно ли клонировать это репо, откат к первому фиксатору выполнить трюк и нажать его (или делает это означает, что git будет по-прежнему иметь историю всех этих коммитов? - иначе 6MB).

Моя конечная цель заключается в том, чтобы в основном найти лучший способ избавиться от содержимого папки от git, чтобы пользователю не приходилось загружать вещи на 6 МБ и, возможно, иметь другие коммиты, которые никогда не касались модулей (в основном это все) в истории git.

Как я могу это сделать?

+0

Если какой-либо из нижеприведенных ответов решает вашу проблему, возможно, вам стоит подумать о принятии в качестве ответа на ваш вопрос. https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – starbeamrainbowlabs

ответ

320

Если вы здесь, чтобы скопировать и вставить код:

Это пример, который удаляет node_modules из истории

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 
echo node_modules/ >> .gitignore 
git add .gitignore 
git commit -m 'Removing node_modules from git history' 
git gc 
git push origin master --force 
+13

Я также должен запустить 'git gc' после запуска ваших команд, чтобы освободить все пространство, используемое удаленными ссылками , – pagliuca

+12

Стоит отметить, что если вам нужно нажать этот вверх по течению, вам, вероятно, потребуется принудительное обновление без перемотки вперед, используя 'git push origin master -force' – DaveStephens

+10

Это должен быть принятый ответ! – prakharsingh95

5

Полная копия & паста рецепт, просто добавляя команды в комментариях (для копипаст раствор), после их тестирования:

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
echo node_modules/ >> .gitignore 
git add .gitignore 
git commit -m 'Removing node_modules from git history' 
git gc 
git push origin master --force 

после этого, вы можете удалить строку «node_modules /» от .gitignor e

106

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

Вот метод я использую, чтобы полностью удалить каталог из истории мерзавца, используя --index-filter вариант, который работает гораздо быстрее:

# Make a fresh clone of YOUR_REPO 
git clone YOUR_REPO 
cd YOUR_REPO 

# Create tracking branches of all branches 
for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done 

# Remove DIRECTORY_NAME from all commits, then remove the refs to the old commits 
# (repeat these two commands for as many directories that you want to remove) 
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch DIRECTORY_NAME/' --prune-empty --tag-name-filter cat -- --all 
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 

# Ensure all old refs are fully removed 
rm -Rf .git/logs .git/refs/original 

# Perform a garbage collection to remove commits with no refs 
git gc --prune=all --aggressive 

# Force push all branches to overwrite their history 
# (use with caution!) 
git push origin --all --force 
git push origin --tags --force 

Вы можете проверить размер хранилища до и после gc с :

git count-objects -vH 
+2

вы могли бы объяснить, почему это происходит намного быстрее? – knocte

+6

@knocte: из документов (https://git-scm.com/docs/git-filter-branch). «-index-filter: ... похож на фильтр дерева, но не проверяет дерево, что делает его намного быстрее» –

+9

Почему это не принятый ответ? Это настолько основательно. –

18

в дополнении к популярному ответу above я хотел бы добавить несколько заметок для Windows, -систем. Команда

git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
  • работает отлично без каких-либо изменений! Поэтому вы не должны использовать Remove-Item, del или что-нибудь еще вместо rm -rf.

  • Если вам необходимо указать путь к использованию файла или каталога слэши как ./path/to/node_modules

+1

Это идеальная и простая команда также в Linux. – peterh

+0

Это не будет работать в Windows, если каталог содержит. (точка) в названии. –

+2

И я нашел решение. Используйте двойные инвертированные запятые для команды rm следующим образом: «rm -rf node.modules». –

7

Лучший и самый точный метод, который я нашел в том, чтобы загрузить файл bfg.jar: https://rtyley.github.io/bfg-repo-cleaner/

Затем выполните команды:

git clone --bare https://project/repository project-repository 
cd project-repository 
java -jar bfg.jar --delete-folders node_modules 
git reflog expire --expire=now --all && git gc --prune=now --aggressive 
git push --mirror https://project/new-repository 

Если вы хотите удалить файлы, то используйте опцию Delete-файлы вместо:

java -jar bfg.jar --delete-files *.pyc 
+1

очень просто :) Если вы хотите сделать так, чтобы удалить только конкретную папку, это поможет: https://stackoverflow.com/questions/21142986/remove-filenames-from-specific-path – emjay

0

Я снял ведро и OBJ папки из старых проектов C# с использованием Git на окнах. Будьте осторожны с

git filter-branch --tree-filter "rm -rf bin" --prune-empty HEAD 

Он разрушает целостность установки мерзавца, удалив папку USR/бен в мерзавце папки установки.

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