Как я могу навсегда сохранить файл git rm --cached? - PullRequest
0 голосов
/ 28 февраля 2019

У меня нет проблем, когда я делаю git rm - кэшированное имя файла над моим файлом, чтобы исключить его изменения из области git staging и repository, но в следующий раз, когда я делаю коммит, мне нужно сделать тот же самый git rm --cached имя файла в другой раз, чтобы избежать изменений.

Как я могу навсегда исключить изменения с помощью файла git rm --cached?

Спасибо

1 Ответ

0 голосов
/ 01 марта 2019

Короткий ответ: ты не можешь.Все, что git rm --cached делает, это удаляет запись (или несколько записей) из вашего индекса.Что-то еще всегда может вернуть такую ​​запись.

Это TL; DR, и вы можете остановиться здесь, если хотите.Но если вы хотите знать, что вы должны делать с этими файлами, читайте дальше ...

Это, однако, не очень хороший способ сформулировать эффект удаления записи изindex:

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

(выделено мной), потому что индекс не хранит изменения .Здесь есть несколько важных терминологических вопросов, которые, если вы не очень точны, могут привести к некоторой степени страдания в будущем.Итак, давайте проясним ситуацию здесь, поскольку Git уже ужасно запутан (я работаю с ним уже более десяти лет, и у него все еще есть темные углы).

Об индексе

Итак, давайте поговорим об индексе.Эта вещь - этот индекс - очень важна в Git, потому что именно так вы делаете следующий коммит.По этой причине некоторые части Git называют это областью подготовки .Некоторые части Git, такие как git rm --cached, называют его cache .Это всего лишь три термина для одной и той же вещи: для структуры данных, которую Git переносит, слабо привязанной к вашему рабочему дереву, которую Git будет использовать при создании new commit.

Сам индекс представляет собой сложного маленького зверя и играет расширенную роль во время слияний, но в основном он удерживает копий файлов .Чтобы понять, как работает эта часть, полезно взглянуть на commitits и work-tree (или рабочее дерево, или рабочий каталог, или любое количество похожих терминов).Под коммитом или, точнее, подразумевается полный снимок всех файлов .Здесь нет изменений , есть только файлы.Если файл main.py находится в коммите, в коммите есть полная копия из main.py с содержимым, которое было у вас, когда вы - или кто-либо еще - запускали git commit.

.файлы внутри коммитов преднамеренно замораживаются и сжимаются - иногда очень сильно сжаты - и Git-ified в форму, которую действительно может использовать только Git.Это отлично подходит для архивации коммитов навсегда, но не подходит для выполнения какой-либо работы.Чтобы завершить работу, Git должен разморозить, распаковать и де-Git-ify ваши файлы в форму, которую вы обычно используете.Так вот откуда исходит ваше дерево работы: это место, где вы можете выполнять свою работу.

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

Вместо этого, когда вы извлекаете коммит, используя, например, git checkout <em>branch</em>, Git копирует замороженный, Git-ifiedфайлы из коммита в индекс.Здесь файлы все еще Git-ified и готовы заморозить в следующий коммит.Но они на самом деле не заморожены сейчас. Теперь вы можете перезаписать их.Они по-прежнему Git-only!

Итак, скопировав файлы в указатель, Git теперь продолжает распаковывать и де-Git-ify файлы и помещатьнормальные файлы в вашем рабочем дереве.Это означает, что когда вы делаете и делаете следующий коммит, Git может - и делает - игнорировать ваше рабочее дерево.Он просто берет все, что есть в вашем индексе прямо сейчас , полные копии всех файлов, и замораживает их в новом коммите.

Вот почему выВы должны продолжать работать git add, даже если у вас был git add -данный файл ранее.git add копирует файл work-tree в копию index .Если раньше в индексе была копия, ну, теперь она перезаписывается новой (и недавно Git-ified) версией.Если нет, то теперь это в индексе.В любом случае, теперь он готов перейти к следующему коммиту.

Наличие файла в индекса - это именно то, что определяет файл как отслеживаемый .Если он в индексе, он отслеживается.Если нет, то это не так.

Так что git rm --cached somefile удаляет Git-ified копию somefile из индекса.Без --cached это также приведет к удалению обычного формата somefile из рабочего дерева.С --cached он оставляет файл рабочего дерева позади:

$ git checkout master
... bunch of files exist ...

$ git rm --cached main.py     # main.py is now untracked

$ git add main.py             # main.py is now tracked

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

Если мы не допустим файл вне индекса (снова git rm --cached), а затем git commit. новый коммит, который мы делаем, теперь не имеет файла в нем.(Новый коммит также становится верхним коммитом ветви.) Так что если мы git checkout этот новый коммит позже, этот файл не будет в коммите, поэтому он не в индексе.Если в рабочем дереве есть неотслеживаемый файл с таким именем, этот неотслеживаемый файл не будет поврежден.

Но как только мы проверяем любой более старый коммит, который имеет , этот файл, хорошо, он находится в коммите, поэтому Git копирует его в индекс, а затем и в рабочее дерево.Теперь он снова отслеживается, потому что теперь он в индексе.Если мы закончили с просмотром старого коммита, и у нас git checkout нового, у которого нет файла, Git:

  1. увидит, что файлв коммите и индексе и рабочем дереве
  2. видит, что файл не в новом коммите, чтобы перейти к
  3. , удаляет файл из индекса и рабочийдерево при переключении на новый коммит

О .gitignore файлах

При перечислении имени файла или шаблона, соответствующего имени файла, в файле .gitignore не сообщаетсяGit для игнорировать файл, точно.Он воздействует на неотслеживаемых файлов.

Не отслеживаемый файл - это, как мы уже отмечали, файл, который находится в рабочем дереве, но не в индексе.Неважно, входит ли он в какой-либо конкретный коммит или нет, важно то, находится ли он в индексе прямо сейчас .Если вы добавляете файл в индекс, используя git add, чтобы скопировать его (и сжать и Git-ify) из рабочего дерева в индекс, ну, теперь он там и, следовательно, отслеживается.Если вы git rm --cached файл из индекса, ну, теперь он не там и, следовательно, не отслеживается.Меняйте местами столько, сколько хотите!Ничего действительно важного пока не происходит: вы просто вводите файл в индекс или удаляете его из индекса.

Отсутствие отслеживания имеет два основных эффекта:

  • Он не входит в следующий коммит, если и когда вы запустите git commit.Это потому, что Git создает новые коммиты из того, что есть в индексе.
  • И это заставляет Git скулить на вас: Эй, файл somefile не отслежен, разве вы не хотите, чтобы он был в ваших коммитах?

Перечисление имени файла в .gitignore заставляет Git замолчать из-за отсутствия отслеживания, и делает git add --all или git add . not скопировать этот файл в индекс, если его там еще нет.Таким образом, мы могли бы сказать, что вместо .gitignore этот файл должен называться .git-stop-whining-about-these-files-and-do-not-automatically-add-them-with-mass-add-operations.

Это не очень приятное имя, поэтому Git использует .gitignore.

* 118.7 * Впрочем, при перечислении файла в .gitignore есть нежелательный побочный эффект.Git обычно очень осторожен с неотслеживаемыми файлами.Предположим, что файл не отслежен, и какая-то операция приведет к его засорению.Например, предположим, что somefile сейчас не отслеживается и не входит в текущий коммит .Но это в коммите tip ветки dev, и вы говорите Git: git checkout dev или git merge dev.(Случай слияния более сложен, но имеет те же проблемы.)

Поскольку файл равен в коммите в конце dev, Git потребуется скопировать somefile от этого коммита до индекса и рабочего дерева.Это будет перезаписать somefile.Git скажет вам: Нет, я не буду задевать ваш файл somefile.Это не отслеживается и мешает.Пожалуйста, зафиксируйте его или уберите с пути.

Но если вы укажете somefile в своем .gitignore, Git будет не стесняться его затушевывать после всех ,по крайней мере, в некоторых случаях (включая git checkout dev один).Итак, этот .gitignore файл должен иметь имя .git-stop-whining-about-these-files-and-do-not-automatically-add-them-with-mass-add-operations-but-do-feel-free-to-clobber-them-in-some-cases.

Вывод: идеального ответа не существует

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

Или вы можете git rm --cached файл и выбрать, включать его или нет в .gitignore.Если это что-то, что безопасно для клобера, перечисление этого здесь - вероятно путь.Таким образом, файл не будет в вашем индексе в new коммитах, которые вы делаете отсюда.Конечно, если вы вернетесь к старым коммитам и будете использовать их - используйте то, что вставлено в ваш индекс - для создания новых коммитов, забыв снова git rm --cached, это не поможет, потому что когда файл равен в вашем индексе вы фактически должны удалить его, либо переключившись обратно на коммит, у которого его нет, либо запустив на нем git rm --cached.Но git add . не будет добавлять его случайно.Вы просто должны быть осторожны, чтобы не clobber файл выйти из вашего рабочего дерева, когда возвращаетесь к более старым коммитам, которые его имеют.

Или, конечно, вы можетеgit rm --cached файл и мириться с любым нытьем.

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