Удалить каталог из удаленного репозитория после добавления его в .gitignore


599

Я зафиксировал и отправил какой-то каталог на github. После этого я изменил .gitignoreфайл, добавив каталог, который следует игнорировать. Все работает нормально, но каталог (теперь игнорируемый) остается на github.

Как мне удалить этот каталог из github и истории репозитория?


Ответы:


1067

Правила в вашем .gitignoreфайле применяются только к неотслеживаемым файлам. Так как файлы в этом каталоге уже были зафиксированы в вашем репозитории, вы должны удалить их, создать коммит и отправить его в GitHub:

git rm -r --cached some-directory
git commit -m 'Remove the now ignored directory "some-directory"'
git push origin master

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

Кроме того, обратите внимание, что вывод из git rm -r --cached some-directoryбудет что-то вроде:

rm 'some-directory/product/cache/1/small_image/130x130/small_image.jpg'
rm 'some-directory/product/cache/1/small_image/135x/small_image.jpg'
rm 'some-directory/.htaccess'
rm 'some-directory/logo.jpg'

Это rmотзыв от git о репозитории; файлы все еще находятся в рабочем каталоге.


3
Если кто-то потянет, будут ли удаленные теперь файлы для них удалены или останутся нетронутыми?
Мартин Коничек

3
@Martin Konicek: если пользователь, который извлекает эти изменения, не имеет изменений в этих файлах, они будут удалены.
Марк Лонгэйр,

@MarkLongair Что делает -rи --cached. Спасибо.
Лабанино

13
@Labanino: -rозначает рекурсивный, необходимый, если вы делаете целые каталоги. --cachedпереопределяет обычное поведение git, удаляя их из рабочего каталога и готовя удаление к фиксации, и заставляет git работать только в области подготовки, готовой к фиксации. Это то, как вы говорите git, что хотите хранить локальные копии файлов.
enthh

2
Это хорошо работает, но я должен был сначала сделать: git reset name_of_fileдля того, что описано выше, чтобы работать
Эдвард

248

Я делаю это:

git rm --cached `git ls-files -i --exclude-from=.gitignore` 
git commit -m 'Removed all files that are in the .gitignore' 
git push origin master

Который удалит все файлы / папки, которые находятся в вашем git, игнорирует, за исключением того, что вы должны выбрать каждый вручную


Это, кажется, перестало работать для меня, теперь я делаю:

 git rm -r --cached . 
 git add .
 git commit -m 'Removed all files that are in the .gitignore' 
 git push origin master

4
Спасибо, это мне очень помогло! Если вы используете Windows PowerShell, вы можете сделать этоforeach ($i in iex 'git ls-files -i --exclude-from=.gitignore') { git rm --cached $i }
Мэтью

10
Опробовал ваш второй подход, он удалил все файлы из моего локального мерзавца!
artnikpro

2
Я думаю, что вы должны перейти в подкаталог и сделать это. Поправьте меня если я ошибаюсь.

Итак, что мы узнали сегодня, дети? "Не запускайте случайный код, который вы найдете в переполнении стека!"
Джонатан Ландрум

49

Согласно моему Ответу здесь: Как удалить каталог из репозитория git?

Чтобы удалить папку / каталог только из репозитория git, а не из локального, попробуйте 3 простых шага.


Шаги по удалению каталога

git rm -r --cached FolderName
git commit -m "Removed folder from repository"
git push origin master

Действия по игнорированию этой папки в следующих коммитах

Чтобы игнорировать эту папку из следующих коммитов, создайте в корневом каталоге один файл с именем .gitignore и поместите в него имя этой папки. Вы можете положить столько, сколько хотите

Файл .gitignore будет выглядеть так

/FolderName

удалить каталог


1
Это именно то, что я искал. Спасибо :)
Рохит Сингх

Я рад, что это помогло @Rohit Singh
eirenaios

9

Первый ответ Бланделла мне не помог. Однако это показало мне правильный путь. Я сделал то же самое, как это:

> for i in `git ls-files -i --exclude-from=.gitignore`; do git rm --cached $i; done
> git commit -m 'Removed all files that are in the .gitignore'
> git push origin master

Советую сначала проверить файлы, которые нужно удалить, выполнив следующую инструкцию:

git ls-files -i --exclude-from=.gitignore

Я использовал файл .gitignore по умолчанию для visual studio и заметил, что он удаляет все папки log и bin в проекте, что не было моим предполагаемым действием.


5

Примечание. Это решение работает только с графическим интерфейсом Github Desktop. .

С помощью Github Desktop GUI это очень просто.

  1. Переместите папку в другое место (из папки проекта) временно.

  2. Отредактируйте ваш .gitignoreфайл и удалите запись папки, которая будет удалена из главного репозитория на странице github.

  3. Зафиксируйте и синхронизируйте папку проекта.

  4. Переместить папку в папку проекта

  5. Повторно отредактируйте .gitignoreфайл.

Это все.


5

Ответ от Бланделла должен сработать, но по какой-то причудливой причине это не касается меня. Я должен был сначала передать имена файлов, выведенные первой командой, в файл, а затем перебрать этот файл и удалить этот файл один за другим.

git ls-files -i --exclude-from=.gitignore > to_remove.txt
while read line; do `git rm -r --cached "$line"`; done < to_remove.txt
rm to_remove.txt
git commit -m 'Removed all files that are in the .gitignore' 
git push origin master

4

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

Не могу использовать --exclude-from=.gitignore : / - Вот обновленный метод:

Общий совет: начните с чистого репо - все зафиксировано, ничего не ожидается в рабочем каталоге или индексе, и сделайте резервную копию !

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch
git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch
git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#optionally add anything to the index that was previously ignored but now shouldn't be:
git add *

#commit again
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.

git commit -m "re-applied modified .gitignore"

#other devs who pull after this commit is pushed will see the  newly-.gitignored files DELETED

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


0

Если вы работаете с PowerShell, попробуйте выполнить следующую команду одной командой.

PS MyRepo> git filter-branch --force --index-filter
>> "git rm --cached --ignore-unmatch -r .\\\path\\\to\\\directory"
>> --prune-empty --tag-name-filter cat -- --all

Затем, git push --force --all .

Документация: https://git-scm.com/docs/git-filter-branch


Чем использование git filter-branchотличается от использования git rm? Первоначально я думал, что я должен использовать версию, git filter-branchно большинство комментариев здесь рекомендуют использовать git rm. Из того, что я понимаю, git rmтолько удаляет его из текущей рабочей директории и индекса. Но если он добавил несколько коммитов раньше, он все равно будет в хранилище.
alpha_989

Правильно. git rmудалит файл из последней фиксации в будущем. git filter-branchдавайте удалим его из всей истории. Смотрите также: help.github.com/articles/…
Шон Люттин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.