Git жалуется, потому что файлы не отслеживаются.
Я знаю, что вы сказали:
[] файлы отслеживаются
, но это не так: вы также сказали:
Они ... окончательно удалены в последующем коммите.
Когда вы находитесь в точке, где происходит сбой, файлы были удалены из индекса, но не из рабочего дерева. Это определение неотслеживаемого файла: это файл, который находится в рабочем дереве, но не в индексе.
В частности, это:
error: could not detach HEAD
сообщает вам (или мне, во всяком случае), что файлы в настоящий момент не отслеживаются в коммите tip, который вы извлекли прямо сейчас, при вводе команды:
git rebase -i <start-point>
но фиксация идентифицировано здесь есть их в этом. Git потребуется git checkout
для этого коммита, но при проверке этого коммита он будет перезаписывать неотслеживаемые файлы отслеживаемыми файлами.
Если этот последний бит дал вам запись-царапина / WTF шум в вашей голове ? не волнуйтесь: это действительно сбивает с толку.
Индекс, в Git, является важным маленьким зверем ie, который часто не объяснил должным образом. Чтобы понять это, вы должны понимать, что Git всегда имеет три - ну, до 3 - копии каждого файла, над которым вы работаете / с которым , Одна копия замораживается на все время, в коммите: коммит, который вы извлекли прямо сейчас. Вторая копия 1 находится в index . Это то, что делает файл отслеженным . Третья копия - единственная, которую вы можете увидеть ... но Git даже не использует ее , так как это ваша копия в вашей работе. tree.
Индекс, который Git также вызывает область подготовки , содержит копию (снова см. сноску 1) каждого файла, который go перейдет в следующий коммит вы делаете . Таким образом, он изначально копирует из коммита, который вы git checkout
, когда вы выбираете коммит для работы. Git затем копирует индексную копию в специальном формате Git из вашего рабочего дерева 1062 *, куда Git помещает все файлы снимков, чтобы вы могли с ними работать и работать.
Как только Git скопировал их, это в основном делается с ними. Вы вносите изменения в свою копию рабочего дерева, а затем запускаете git add
, чтобы сообщить Git: скопировать копию рабочего дерева обратно в / поверх верхней части индексной копии . (Опять же, см. Сноску 1.) Причины этого немного сложны, но, если хотите, подумайте об этом следующим образом:
- Копии в коммитах предназначены только для чтения, заморожены на все времена , Чтобы сэкономить много места, Git хранит их в специальном Git -сжатом формате, который может использовать только Git.
- Это имеет смысл для архивирования, но бесполезно для получения работа выполнена, поэтому Git должен развернуть файл в его обычную форму. Это рабочее дерево копия.
- Чтобы сделать вещи go быстрыми и удобными для Git, Git сохраняет замороженную копию (но больше не замороженную) в индекс. Вы можете заменить оптовую копию индекса, указав
git add
из рабочего дерева: Git переведет ее в формат , высушенный вымораживанием, готовый к фиксации в индексе (но это там можно заменить).
Вы можете делать с копией рабочего дерева все, что захотите, потому что это обычный файл. Пока существует файл рабочего дерева, он просто существует как файл.
Вы можете удалить или заменить копию индекса в любое время. Чтобы заменить его, используйте git add
, чтобы скопировать файл рабочего дерева поверх того, что находится в индексе, под этим именем. Чтобы полностью удалить его, используйте git rm <em>file</em>
.
. При запуске git commit
, Git упаковывает все файлы, которые находятся в индексе , чтобы сделать снимок нового коммита. Все, что находится в индексе - в какой бы форме оно не находилось в индексе - входит в новый коммит. Git вообще не использует ваше рабочее дерево для этого. Вот почему вы должны постоянно git-add
файлы: Git не смотрит на копию рабочего дерева. 2
Если файл рабочего дерева существует и индексная копия исчезла , файл не отслежен . Но если файл находится в каком-либо более раннем коммите , и вы извлекаете этот коммит, копия из более раннего коммита возвращается обратно в индекс, и файл снова отслеживается. И когда копия из более ранней фиксации попадает в индекс, Git также перезаписывает копию в рабочем дереве - если только это не будет sh, потому что она нигде не сохраняется, и в этом случае Git говорит что это в пути.
(Если он отслеживается, Git знает, безопасно ли он сохранен в коммите. Если это так, Git может перезаписать его.)
Итак, что Теперь об этом должно быть очевидно: если данные важны, переместите файлы в другое место. Сделайте свой ребаз. Когда вы закончите, файлы будут исчезли , потому что последний коммит удаляет их. Теперь вы можете переместить файлы обратно, и они снова не будут отслежены. Коммиты, которые имели файлы ранее, все еще имеют файлы теперь; если ваша перебазировка скопировала эти коммиты в новые и улучшенные коммиты, эти новые и улучшенные коммиты все еще содержат файлы.
Концепция ключа: , является ли файл отслеженным или без отслеживания зависит от того, есть ли копия в индексе. Индексная копия в основном невидима, 3 , но это жизненно важно! Индекс является временной областью. В основном он содержит следующий коммит, который вы сделаете; Git должен заполнить его в из коммита, когда вы git checkout
делаете коммит.
Следовательно, отслеживаемое / неотслеживаемое состояние некоторого файла может внезапно измениться. Когда Git заполняет индекс из коммита, при необходимости он создает файл в индексе и создает его в рабочем дереве в это время; или удалит файл из рабочего дерева, если необходимо - если он не входит в коммит, на который вы перемещаетесь - и в это время он удалит файл из тоже рабочего дерева.
1 Технически, индекс содержит ссылку на объект blob, для каждого файла быть преданным. Объект BLOB-объектов заморожен на все времена, и коммиты ссылаются на него, как и индекс. Когда вы git add
файл, Git сжимает и хэширует содержимое, и если с этими данными уже есть большой двоичный объект, Git может повторно использовать существующий большой двоичный объект. В противном случае Git создает новый, и этот BL ха sh входит в индекс.
Иногда это создает блоб, который никогда не используется, потому что вы пишете одну версию, а затем понимаете, что в ней есть ошибка и напишите еще один. Это нормально: Git создает объекты мусора все время, самостоятельно. Git имеет сборщик мусора , который он запускает, когда это кажется разумным, для очистки неиспользуемых объектов.
2 Если вы используете git commit -a
, это создает секунда , но временный индекс, git add
- все файлы во временный индекс и фиксируются из временного индекса. Если все это работает, временный индекс становится новым; в случае неудачи Git просто удаляет временный индекс, и все возвращается к тому, что было до запуска git commit -a
. TL; DR - то, что Git все еще фиксирует из индекса. Это всего лишь секунда, дополнительный индекс для бита.
3 Команда git status
сравнивает индекс с коммитом HEAD
и сообщает вам, что такое разные . Поэтому, если файл «пропал без вести», вы увидите удаление как , подготовленное для фиксации . Затем отдельно он сравнивает индекс с рабочим деревом и сообщает вам, что отличается . Таким образом, если файл находится в индексе, но отсутствует в рабочем дереве, вы увидите удаление как , не подготовленное для фиксации .
Если файл существует в HEAD
, но ушел из индекса, а затем назад в рабочем дереве, вы увидите поэтапное удаление и неотслеживаемый файл с одинаковым именем.