Git удалить файл из коммита

Обновлено: 01.07.2024

Я добавил файл с именем "file1.txt" в репозиторий Git. После этого я зафиксировал его, добавил пару каталогов с именем dir1 and dir2 и отправил их в репозиторий Git.

Теперь текущее хранилище имеет "file1.txt" , dir1 и dir2 . Как я могу удалить, "file1.txt" не влияя на других, как dir1 и dir2 ?

git rm это правильный ответ, но помните, что файл все еще будет там в истории. Если вы хотите удалить файл, потому что он содержал конфиденциальную информацию, вам нужно сделать что-то более радикальное. (Изменение истории, особенно для контента, который вы уже добавили, является радикальным действием, и его следует избегать, если это возможно.) Примечание: в GitHub вы теперь можете напрямую удалить файл из веб-интерфейса (даже не клонируя репо). Смотрите мой ответ ниже . @KeithThompson, что это может быть, если я отчаянно хочу это сделать?

Если вы хотите удалить файл из репозитория Git и файловой системы , используйте:

Но если вы хотите удалить файл только из репозитория Git и не удалять его из файловой системы, используйте:

И подтолкнуть изменения к удаленному репо

Также удобно: git rm -r directory // Удалить каталог и контент Это не собирается избавляться от этого файла в других коммитах. Обратите внимание, что файл будет удален и локально. Если вы хотите удалить его только из репозитория, выполните: git rm --cached file1.txt Стоит отметить, что если этот файл содержит конфиденциальную информацию (например, учетные данные), вы должны немедленно изменить эти учетные данные . Процитируем GitHub: «После того, как вы отправили коммит в GitHub, вы должны рассматривать любые содержащиеся в нем данные как скомпрометированные. Если вы зафиксировали пароль, измените его! Если вы зафиксировали ключ, сгенерируйте новый».

git rm file.txt удаляет файл из репозитория, но также удаляет его из локальной файловой системы .

Чтобы удалить файл из репозитория и не удалять его из локальной файловой системы, используйте:
git rm --cached file.txt

Ниже приведена точная ситуация, когда я использую git для поддержки контроля версий для веб-сайта моего бизнеса, но каталог «mickey» был папкой tmp для обмена частным контентом с разработчиком САПР. Когда он нуждался в ОГРОМНЫХ файлах, я создал личный, несвязанный каталог и установил там ftpd файлы для его загрузки через браузер. Забыв, что я сделал это, я позже выполнил git add -A из базовой директории сайта. Впоследствии git status показали новые файлы, требующие фиксации. Теперь мне нужно было удалить их из отслеживания git и контроля версий .

Ниже приведен пример того, что случилось со мной, когда я случайно удалил .003 файл. К счастью, мне все равно, что случилось с локальной копией .003 , но некоторые другие в настоящее время измененные файлы были обновлениями, которые я только что сделал на веб-сайте, и они были бы грандиозными, если их удалить в локальной файловой системе! «Локальная файловая система» = живой сайт (не очень хорошая практика, но реальность) .

Обновление: Этот ответ получает некоторый трафик, поэтому я подумал, что упомяну другой мой ответ Git, делится парой отличных ресурсов: На этой странице есть рисунок, который помогает демистифицировать Git для меня. Книга "Pro Git" онлайн и мне очень помогает.

Затем вам нужно будет зафиксировать это с помощью чего-то подобного, git commit -m "Just removing file1.txt" а затем, если у вас есть удаленный репозиторий, протолкнуть коммит с чем-то вроде git push origin master .

Во-первых, если вы используете git rm , особенно для нескольких файлов, учтите, что любой подстановочный знак будет разрешен оболочкой, а не git командой.

Но, если ваш файл уже находится на GitHub, вы можете (с июля 2013 года) напрямую удалить его из веб-интерфейса!

Просто просмотрите любой файл в вашем хранилище, щелкните значок корзины в верхней части и подтвердите удаление, как и любое другое редактирование через Интернет.

Затем " git pull " в вашем локальном репо, и это также приведет к удалению файла локально.
Что делает этот ответ (окольным) способом удаления файла из git repo?
(Не говоря уже о том, что файл на GitHub находится в «git repo»)

кнопка удаления

(фиксация будет отражать удаление этого файла):

совершить удаление

И просто так, это ушло.

Для получения справки об этих функциях обязательно прочитайте наши справочные статьи по созданию , перемещению , переименованию и удалению файлов.

Примечание. Так как это система контроля версий, Git всегда имеет вашу спину, если вам нужно восстановить файл позже.

Последнее предложение означает, что удаленный файл все еще является частью истории, и вы можете восстановить его достаточно легко (но пока не через веб-интерфейс GitHub):

Недавно устроился разработчиком, до этого в команде не работал и вот хотел узнать.

Я сделал коммит, потом сделал push в новую ветку, но оказалось, что у меня в неё попал лишний файл - package-lock.json. хотел бы от него избавиться, заново сделать коммит и пуш, как это сделать?

Нужно удалять старый коммит или как то удалить другим способом ?

Простой 4 комментария

bingo347

sergey-kuznetsov

Дмитрий Беляев, он помешал тем, что это автоматически создаваемый артефакт, который постоянно изменяется независимо от самого проекта и эти изменения придется коммитить. Зачем нам лишняя возня? Лучше его игнорировать.

SagePtr

Сергей Кузнецов, не постоянно изменяется, а только если обновить версии пакетов, используемых в проекте. Нужен для того, чтобы на другой стороне можно было установить ровно те же самые версии пакетов командой npm ci, а не самые свежие в рамках мажорной версии. Чем чревато - ну допустим, вышел в каком-то пакете минорный билд, сломавший функционал, а девелопер это проморгал, потому как у него и на проде версии не совпадают, и с его стороны все тесты прошли.

sergey-kuznetsov

Какого такого комитета? ))

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

Удалить файл из индекса, при этом не удаляя его из рабочего каталога, можно командой git rm --cache имя_файла. Затем делаем коммит, который удаляет файл из текущего состояния ветки. Ведь именно там ты не хочешь видеть этот файл? В рабочем каталоге он нам скорее всего нужен и удалять не стоит.

Иногда я бросал DVD-рип в проект веб-сайта, затем небрежно git commit -a -m . , и, зап, репо было раздутым на 2,2 гига. В следующий раз я сделал некоторые изменения, удалил видеофайл и зафиксировал все, но сжатый файл все еще находится в хранилище, в истории.

Я знаю, что могу начинать ветки с этих коммитов и перебазировать одну ветку на другую. Но что я должен сделать, чтобы объединить 2 коммита, чтобы большой файл не отображался в истории и был очищен в процессе сборки мусора?

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

Используйте BFG Repo-Cleaner , более простую и быструю альтернативу, git-filter-branch специально разработанную для удаления ненужных файлов из истории Git.

Тщательно следуйте инструкциям по использованию , основная часть просто так:

Любые файлы размером более 100 МБ (которых нет в вашем последнем коммите) будут удалены из истории вашего репозитория Git. Затем вы можете использовать git gc для очистки мертвых данных:

BFG обычно по крайней мере в 10-50 раз быстрее, чем бег git-filter-branch , и, как правило, проще в использовании.

Полное раскрытие: я являюсь автором BFG Repo-Cleaner.

@RobertoTyley Отлично, вы экономите мое время, большое спасибо. Кстати, возможно, следует поступить git push --force после ваших шагов, в противном случае удаленное репо все равно не изменилось. Я думаю, что жаргон Трампа о том, что инструмент выводит, немного.

То, что вы хотите сделать, очень разрушительно, если вы опубликовали историю другим разработчикам. См. «Восстановление из исходной версии» в git rebase документации, чтобы узнать о необходимых шагах после восстановления истории.

У вас есть как минимум два варианта: git filter-branch и интерактивная перебазировка, оба объяснены ниже.

С помощью git filter-branch

У меня была похожая проблема с объемными данными бинарных тестов из импорта Subversion и я писал об удалении данных из репозитория git .

Скажите, что ваша история с мерзавцами:

Обратите внимание, что git lola это нестандартный, но очень полезный псевдоним. С помощью --name-status переключателя мы можем видеть модификации дерева, связанные с каждым коммитом.

  • --prune-empty удаляет коммиты, которые становятся пустыми ( т.е. не меняют дерево) в результате операции фильтрации. В типичном случае эта опция производит более чистую историю.
  • -d называет временный каталог, который еще не существует, чтобы использовать для построения отфильтрованной истории. Если вы работаете в современном дистрибутиве Linux, указание дерева /dev/shm приведет к более быстрому выполнению .
  • --index-filter является основным событием и работает с индексом на каждом шаге в истории. Вы хотите удалить, oops.iso где бы он ни находился, но он присутствует не во всех коммитах. Команда git rm --cached -f --ignore-unmatch oops.iso удаляет DVD-рип, когда он присутствует, и не дает сбоя в противном случае.
  • --tag-name-filter описывает, как переписать имена тегов. Фильтр cat - это операция идентификации. Ваш репозиторий, как и в приведенном выше примере, может не содержать тегов, но я включил эту опцию для полной общности.
  • -- указывает конец опций git filter-branch
  • --all Следующее -- является сокращением для всех ссылок. Ваш репозиторий, как и в приведенном выше примере, может иметь только один ref (master), но я включил эту опцию для полной общности.

После некоторого сбивания история теперь:

Обратите внимание, что добавляется только новый коммит «Неосторожный» other.html и что коммит «Remove DVD-rip» больше не находится в основной ветке. В ветке с пометкой refs/original/refs/heads/master содержатся ваши исходные коммиты на случай, если вы допустили ошибку. Чтобы удалить его, следуйте инструкциям в «Контрольном списке для сокращения хранилища».

Для более простой альтернативы клонируйте репозиторий, чтобы отбросить ненужные биты.

Использование file:///. клона URL копирует объекты, а не только создает жесткие ссылки.

Теперь ваша история:

Интерактивная перебазировка

Запуск $ git rebase -i 5af4522 запускает редактор со следующим содержимым.

Выполняя наш план, мы изменяем его

То есть мы удаляем строку с «Удалить DVD-рип» и меняем операцию на «Неосторожно», edit а не на pick .

Позже я обнаружил, что файл был ошибочно добавлен в коммит.

Как я могу удалить файл из последнего коммита?

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

Затем сбросьте ненужные файлы, чтобы исключить их из коммита:

git reset --soft HEAD^ моя самая распространенная операция отмены @PabloFernandez, во-первых, принятый ответ мог быть тем, что искал ОП (также, он был опубликован несколькими месяцами ранее). Во-вторых, принятые ответы всегда на вершине, независимо от количества голосов. Я знал об этом много, git reset но хотел, чтобы способ повлиять на существующий коммит "на месте". Я только что узнал о git commit -C . Так что для меня то, что я хочу, это ваш точный рецепт с еще одним шагом, «новый коммит снова» прописан как git commit -C [hash of original HEAD commit from first step] .

ВНИМАНИЕ ! Если вы хотите только удалить файл из предыдущего коммита и сохранить его на диске , прочитайте ответ Джуззлина чуть выше.

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

  1. удалить файл git rm <file>
  2. совершить с изменением флага: git commit --amend

Флаг изменения указывает git выполнить коммит снова, но «объединить» (не в смысле слияния двух веток) этот коммит с последним коммитом.

Как указано в комментариях, использование git rm здесь похоже на использование самой rm команды!

Вы также можете использовать git rm --cached для хранения файлов на диске Предупреждение тем, кто просматривает этот ответ: убедитесь, что вы хотите УДАЛИТЬ файл (как ушел, ушел, ушел!), А не просто удалите его из списка фиксации. Для того, чтобы добавить к тому , что говорят другие (и сделать его легче запомнить , чтобы не делать этого , если вы действительно хотите): в команде будет делать то , что само по себе делает! rm git rm @CharlesB Можете ли вы добавить примечание из комментария Аркадия Кукаркина к своему ответу, чтобы сделать его более заметным? Обратите внимание, что файлы все еще можно восстановить, в случае, если вы передумали, фиксация ранее git commit --amend все еще существует и может быть найдена, например, с помощью git reflog . Так что это не так плохо, как предлагают другие комментарии.

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

Если вы хотите удалить ненужные файлы из старого коммита (даже отправленного) и не хотите создавать новый коммит, который не нужен из-за действия:

Найдите коммит, которому вы хотите, чтобы файл соответствовал.

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

Найдите commit_id коммита, по которому файлы были добавлены по ошибке , скажем "35c23c2" здесь

Эта команда открывает редактор в соответствии с вашими настройками. По умолчанию используется vim.

Переместите последний коммит, который должен быть «удалить ненужные файлы», на следующую строку некорректного коммита (в нашем случае «35c23c2») и установите команду как fixup :

Вы должны быть хороши после сохранения файла.

Если вы, к сожалению, получаете конфликты, вы должны решить их вручную.

Делать это с нано - это невероятно! Ctrl + K, Ctrl + U, поставить 'f', Ctrl + X, поставить 'y' и вуаля! Если вы действительно хотите удалить файлы из репозитория (а не из файловой системы), а не просто вернуть их к предыдущей версии, то вместо шага 1 сделайте git rm --cached <file(s)> . Подождите, вы можете просто перемещать коммиты по файлу Interactive-ReBase по желанию? Вы можете полностью, но вы можете (или не можете) получить конфликты. Этот процесс можно сделать немного проще, добавив --fixup=35c23c2 в git commit команду. Это автоматически настроит коммит как исправление требуемого коммита, поэтому вам не нужно будет указывать его в ребазе. Кроме того, если добавить --autosquash к git rebase команде, мерзавец будет автоматически перемещать вашу фиксацию в нужном месте, так что вам не нужно ничего делать в интерактивном перебазировании - просто сохранить результат (а это означает , что вам даже не нужно -i флаг, хотя мне все равно нравится использовать его, чтобы убедиться, что все выглядит так, как я ожидаю).

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

Команда git reset примет файл, как это было в предыдущем коммите, и поместит его в индекс. Файл в рабочем каталоге остается нетронутым.
Затем git commit будет зафиксировать и сжать индекс в текущий коммит.

По сути, это берет версию файла, которая была в предыдущем коммите, и добавляет ее к текущему коммиту. Это не приводит к чистым изменениям, и поэтому файл эффективно удаляется из коммита.

Это гораздо лучший ответ для удаления всего одного файла, без изменения всей фиксации. @ThatsAMorais действительно :-). Мне интересно, слился ли этот вопрос с другим, и поэтому я его не видел. Или, может быть, я просто слепой. В любом случае, я думаю, что я склонен оставить его, так как по результатам голосования он кажется более популярным (возможно, люди предпочитают короткий и прямой ответ). Во что бы то ни стало оставьте это! :) У нас явно была правильная идея, и цель - помочь. Я думаю, что слияние это хорошая теория.

Если вы не отправили изменения на сервер, вы можете использовать

Это сбросит все изменения и вернется к одному коммиту обратно

Если вы отправили изменения, следуйте инструкциям @CharlesB.

-1 git reset удаляет произошедшие изменения файла из области подготовки, здесь изменение было зафиксировано Хорошо, но я буду сдерживать голосование, так как это не то, чего хочет ОП :) извините хорошо, это хорошо для меня, но почему противник не хочет этого. В чем проблема? не большое дело, но потому что OP хочет удалить ненужный файл из последнего коммита, и он просто сбрасывается в состояние перед коммитом. Тем не менее, вы должны повторить коммит. @Aris используйте <git diff --cached>, чтобы увидеть изменения

Удаление файла с помощью rm удалит его!

Вы всегда добавляете коммит в git, а не удаляете, поэтому в этом случае верните файл в состояние, в котором он находился до первого коммита (это может быть действие удаления 'rm', если файл новый), а затем повторно зафиксировать, и файл будет идти.

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

или вернуть его в состояние на удаленной ГОЛОВКЕ:

затем измените коммит, и вы обнаружите, что файл исчез из списка (и не удален с вашего диска!)

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

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

Вы увидите что-то вроде следующего .

Изменения, которые необходимо зафиксировать: (используйте «git reset HEAD . » для удаления)

изменено: / путь / к / файлу

Изменения, не подготовленные для фиксации: (используйте «git add . » для обновления того, что будет зафиксировано) (используйте «git checkout - . » для отмены изменений в рабочем каталоге)

изменено: / путь / к / файлу

  • «Изменения должны быть зафиксированы» - это предыдущая версия файла перед фиксацией. Это будет выглядеть как удаление, если файл никогда не существовал. Если вы передадите это изменение, будет исправление, которое вернет изменение в файл в вашей ветви.
  • «Изменения, не подготовленные для фиксации» - это зафиксированное вами изменение и текущее состояние файла.

На этом этапе вы можете делать с файлом все, что захотите, например, сбросить версию.

Когда вы будете готовы совершить:

или (если у вас есть другие изменения, которые вы не хотите совершать, пока)

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

Я объясню вам с примером.
Пусть A, B, C - 3 последовательных коммита. Коммит B содержит файл, который не должен был быть зафиксирован.

Если конкретный файл не находится в последнем или предыдущем коммите, это самый элегантный способ. Я бы даже сказал, что это самый элегантный способ в целом. Мне нравится интерактивный перебазирование. Для одного коммита измените noop на edit [A_commit_ID] или e [A_commit_ID]

Вы можете просто попробовать.

и создать новый коммит.

Тем не менее, есть потрясающее программное обеспечение "Gitkraken". что облегчает работу с git.

И просто обратите внимание: после этого вам нужно git commit --amend будет обновить удаление файла при последнем коммите; и после этого вы можете проверить, действительно ли он был удален с помощью git log -1 --stat

оставит вам локальный файл еще. Если вам также не нужен локальный файл, вы можете пропустить параметр --cached.

Если вся работа выполняется в вашей локальной ветке, вам нужно сохранить файл в последующем коммите, и, как при наличии чистой истории, я думаю, что более простой способ сделать это может быть:

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

Использование git GUI может упростить удаление файла из предыдущего коммита.

Предполагая, что это не общая ветка, и вы не против переписать историю , запустите:

Вы можете отменить проверку файла, который был ошибочно зафиксирован, а затем нажать «Подтвердить».

введите описание изображения здесь

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

В Ubuntu вы можете установить git gui с помощью sudo apt-get install git-gui Спасибо! Я застрял с проблемой (ошибка?), Где была добавлена ​​папка с репозиторием .git, и все обычные команды удаления не работали. Это однако помогло. Это было несколько коммитов назад, я сначала использовал, git rebase -i HEAD

4 а затем выполнил вашу команду, чтобы открыть редактор. Еще одно примечание: «Unstaging» можно найти в меню «Commit».

Самое простое решение из всех. Проще всего запомнить. И гораздо менее подвержен ошибкам, чем использование git reset --soft HEAD^ (помня --soft arg), за которым следует git commit -c ORIG_HEAD (вместо --amend, который все испортил).

Выполните последовательность следующих команд:

Это означает, что состояние вашего удаленного репо изменилось, когда вы выполняли свою локальную работу. И после 'git pull' ваши локальные изменения должны быть объединены с удаленными, вот и все. Конечно, ваши изменения должны остаться. Другими словами, если вы получаете эту ошибку @Dezigo, добавьте флаг -f для принудительного обновления.

Просто хотел дополнить верхний ответ, так как мне нужно было выполнить дополнительную команду:

Что-то, что сработало для меня, но все же думаю, что должно быть лучшее решение:

Просто оставьте изменения, которые вы хотите отменить, в другом коммите, проверьте другие

git reset --soft HEAD^ откатывает ваш коммит, и когда вы печатаете git status , он говорит вам, что делать:

На самом деле, я думаю, что более быстрый и простой способ - использовать интерактивный режим git rebase.

4, как далеко ты хочешь пойти)

а затем вместо «выбрать», используйте «редактировать». Я не понимал, насколько мощным является «редактирование».

Надеюсь, вы найдете это полезным.

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

( функция / target_branch ниже содержит все мои изменения, в том числе те, которые я хотел отменить для определенного файла)

( Feature / Staging - это моя временная промежуточная ветвь, в которую я буду выталкивать все мои разыскиваемые изменения, за исключением изменения в этом одном файле).

Создайте локальную ветку из моего источника / feature / target_branch - она ​​называется feature / staging

Объединенной мой рабочий местное отделение функции / target_branch к функции / постановка филиала

Отмеченная функция / постановка, затем git reset --soft ORIG_HEAD (Теперь все изменения из функции / постановки 'будут поставлены, но не зафиксированы.)

Unstaged файл, который я ранее проверил с ненужными изменениями

Изменена ветвь вверх по течению для объекта / размещения на источник / функция / target_branch

Подтвердил остальные поэтапные изменения и отправил вверх по течению к моему удаленному источнику / feature / target_branch

Читайте также: