2012-01-05 2 views
85

У меня есть фиксация с id 56f06019 (например). В этом деле я случайно совершил большой файл (50 Мб). В другой фиксации я добавляю тот же файл, но в нужный размер (маленький). Теперь мой репо, когда я клонировать слишком тяжелый :(Как удалить этот большой файл из истории репо, чтобы уменьшить размер моего репоGit: Как удалить файл из исторической фиксации?

+0

в моем случае, его не большой файл, но файл конфигурации, содержащий кредитов базы данных. Я изучал git, в то время я не знал о .gitignore. – Rashi

+0

Возможный дубликат [Как удалить/удалить большой файл из истории фиксации в репозитории Git?] (Http: // stackoverflow.com/questions/2100907/how-to-remove-delete-a-large-file-from-commit-history-in-git-repository) –

ответ

123

В главе 9 книги Pro Git имеется раздел о Removing Objects.

Позвольте мне изложить шаги, кратко:

git filter-branch --index-filter \ 
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \ 
    --tag-name-filter cat -- --all 

Как перебазирования вариант описанной выше, filter-branch переписывает операцию. Если вы опубликовали историю, вам нужно будет --force нажать новые ссылки.

filter-branch подход является значительно более мощным, чем rebase подход, так как он

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

filter-branch сохраняет резервные копии тоже отмечает, поэтому размер репо не уменьшится сразу, если вы не истекают в reflogs и мусор собирать:

rm -Rf .git/refs/original  # careful 
git gc --aggressive --prune=now # danger 
+1

Стоит отметить, что это не работает под windows cmd.exe. Тем не менее, кажется, что работать под киргинским штрафом. –

+1

Я получил вышеприведенную ветвь git filter-branch, используя двойные кавычки вместо одиночных кавычек (в Windows Server 2012 cmd.exe) – JCii

+0

Для меня работала эта строка командной строки фильтра. 'git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' - fbf28b005^..' Затем 'rm --recursive - -force .git/ссылки/original' и 'гт --recursive --force .git/logs' Тогда я использовал' мерзавец чернослив --expire now' и 'мерзавец дс --aggressive' Это работало лучше для меня, чем ваши точные шаги, перечисленные выше. Благодарим вас за включение ссылки на книгу Git Pro, поскольку это было бесценно. –

1

Вам нужно будет git rebase в интерактивном режиме посмотреть пример здесь: How can I remove a commit on GitHub? и how to remove old commits.

Если ваша фиксация находится в ГОЛОВЕ минус 10 фиксаций:

$ git rebase -i HEAD~10 

После издания истории, вам нужно нажать на «новую» историю, вам нужно добавить + заставить (см refspec в push options):

$ git push origin +master 

Если другие люди уже клонировали ваш репозиторий, вы должны сообщить об этом, потому что вы только что изменили историю.

+3

Это делает ** не ** удалять большой файл из истории. Кроме того, канонический способ принудительного нажатия - это «git push -force» или «git push -f» (который не требует, чтобы люди знали цель push-перехода) – sehe

+0

На основании вопроса новый файл точно такой же как старый файл, то есть тот же путь. Вот почему вы не можете напрямую использовать 'git rm' на пути. –

+2

@sehe, если вы делаете rebase, устраняя фиксацию с огромным файлом, она ушла навсегда. – vonbrand

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