Как отменить git rm --cached <filename>? - PullRequest
1 голос
/ 24 октября 2019

После установки файла (отслеживаемого файла) я понял, что нужно внести некоторые изменения, поэтому для его удаления я использовал git rm --cached <filename>. Следовательно, я потерял все изменения. Есть ли способ отменить это?

Ответы [ 3 ]

2 голосов
/ 24 октября 2019

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

Вы можете добавить его снова с помощью git add <filename>.

. Более распространенный способ внесения изменений в переменную заключается в использовании git reset HEAD <filename>.

Но ... в этом нет необходимостиunstatage файл, чтобы добавить дальнейшие изменения. Вы можете просто внести дополнительные изменения и выполнить их снова, используя git add <filename>.

1 голос
/ 24 октября 2019

Вам нужно добавить еще раз. Вот примерный набор команд.

echo testmodify>> FOO //Appends "testmodify" to FOO
git add FOO // Stage FOO to commit
git rm --cached FOO // Unstage FOO
git add FOO // Stage FOO

FOO по-прежнему содержит "testmodify"

0 голосов
/ 24 октября 2019

Использование Git фразы поэтапные изменения или для внесения некоторых изменений может очень запутать.

Чтобы не запутаться, вот что вам нужно знать:

  • У Git есть вещь, которую Git вызывает по-разному: index , область подготовки или иногда - редко сейчас - кэш . Все эти три имени относятся к одной вещи. Здесь я просто назову его индексом.

  • Индекс изначально содержит копию 1 из каждого файла , который находится в коммитечто ты проверил. (Этот текущий коммит также называется HEAD.) Эти файлы в формате Git-only. Вы не можете видеть эти файлы. (Это небольшое завышение - есть некоторые специальные трюки с Git, чтобы увидеть их, но обычно они невидимы.) Файлы, которые вы можете см. в вашем рабочем дереве , в котором хранятся обычные повседневные файлы.

  • Когда вы делаете следующий коммит, Git будет использовать файлыкоторые находятся в индексе в то время. То есть, когда вы запускаете git commit -m "some message" (или после того, как git commit без -m получит от вас сообщение), Git затем упакует все файлы, которые находятся в индексе на тот момент и используйте их для создания нового коммита.

  • Следовательно, если вы изменили или заменили файл в своем рабочем дереве, вы должны сначала скопировать егообратно в индекс . В противном случае Git просто повторно использует исходный файл.

Когда вы запускаете git add <em>file</em>, Git берет копию рабочего дерева, сжимает ее в специальный формат Git-only и прочее. сжатая копия в указатель. Теперь индексная копия больше не соответствует копии HEAD, но совпадает с копией рабочего дерева.

Если вы измените копию рабочего дерева снова , теперь все три копии будутразные! В этот момент git status сообщит вам, что у вас есть «изменения, подготовленные для фиксации», а также «изменения не подготовка для фиксации».

Вы можете изменить копию рабочего дерева на что угоднов любое время. Это не влияет на индексную копию.

Вы можете удалить копию рабочего дерева, не удаляя индексную копию, используя любой инструмент на вашем компьютере, который удаляет файл. Вы также можете удалить копию index , не удаляя копию рабочего дерева, используя git rm --cached. И вы можете удалить обе копии, используя git rm. Ничто из этого не влияет на любой существующий коммит - ни один существующий коммит не может быть когда-либо изменен! Но удаление копии индекса влияет на следующий коммит, потому что когда вы запускаете git commit, Git упакует все файлы, которые есть в индексе в это время, поэтому, если файл пропал из индекса, оно не будет в следующем коммите.

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


1 Технически, индекс фактически содержит ссылки на копии. Но эффект почти такой же, как если бы индекс содержал реальные копии, по крайней мере, до тех пор, пока вы не начнете погружаться в то, как манипулировать индексом напрямую, используя git update-index.


Как "не вносить изменения"

Чтобы получить файл из текущего (HEAD) коммита обратно в индекс в том виде, в котором он находится в текущем коммите , вы можете использовать git reset -- <em>file</em>. -- здесь требуется только в том случае, если имя файла напоминает параметр git reset или имя ветви. Например, если у вас есть файл с именем master и именем ветви master, git reset master выглядит так, как будто вы хотите использовать имя ветви , поэтому вы должны написать git reset -- master чтобы сказать git, что вы имеете в виду файл master.

Итак:git reset -- <em>file</em> копирует файл из фиксации HEAD в индекс . Это верно, даже если вы удалили индексную копию: сброс просто вернет ее обратно. Также верно, если файл не в коммите HEAD. Если вы добавили файл F в индекс, а затем решили, что его в конце концов не должно быть в индексе, вы можете git reset -- F и удалит его из индекса.

(Вы также можете git rm --cached F, если хотите: это имеет тот же эффект на данный момент. Но если вы просто хотите, чтобы индексная копия соответствовала копии HEAD, используйте git reset, потому что это работает для обоих случаев: там является копией HEAD, или ее нет. *

Как вы знаете, что ставится?

Опять же, вы не можете на самом деле см. копию файла в вашем индексе. Так как же узнать, соответствует ли он какой-то другой копии? Ответ: git status говорит вам кратко и полезно.

Допустим, у вас есть три файла в вашем рабочем дереве с именами README.md, main.py иutil.py. Первые два из этих файлов вышли из коммита HEAD, и вы только что создали util.py сейчас, так что это не в коммите HEAD и не в индексе.

Команда git status выполняет два сравнения:

  • Во-первых, она сравнивает каждый файл в HEAD с каждым файломв указателе. Таким образом, это сравнивает HEAD:README.md (копия HEAD) с :README.md (индексная копия). 2 Затем сравнивается HEAD:main.py с :main.py.

    Для каждого файла, который то же самое , git status говорит ничего .

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

    Итак, если вы знаете, что было в коммите HEAD, теперь вы знаете, какие файлы одинаковы вindex: что-нибудь git status не упомянул .

  • Далее, сказав вам, что отличается или нет в HEAD против индекса, git status переходит кСравните каждый файл в индексе с каждым файлом в рабочем дереве. Итак, здесь он будет сравнивать :README.md с README.md, :main.py с main.py и обнаруживать, что есть util.py, которого нет в индексе.

    Для каждого файла, то же самое , git status говорит ничего .

    Для каждого файла, который отличается , git status сообщает об изменениях не ступенчатодля фиксации. Это верно, потому что git commit не будет использовать рабочее дерево, оно просто будет использовать индекс.

    Для файла, подобного util.py, это находится в рабочем дереве, но нет в индексе, git status сообщает об этом как неотслеживаемый файл . Вот что такое неотслеживаемый файл: файл, который находится в рабочем дереве, но отсутствует в индексе.

Обратите внимание, что если вы удалите файл изИндекс, он мгновенно не отслеживается! Если вы git add файл, чтобы он был в индексе, ну, теперь он отслеживается.


2 Этот забавный синтаксис HEAD:file и :file специфичен для Gitсам по себе, и работает только с некоторыми командами Git. Одним из них является git show: вы на самом деле можете увидеть индексную копию README.md, используя, например, git show :README.md. Поскольку git show является ориентированной на пользователя командой, вы можете сделать это с довольно хорошей безопасностью: git show HEAD:file, git show :file и git show <commit:>file - все это довольно хорошие способы увидеть конкретную копию конкретного файла, который был превращен вего внутренняя форма Git, либо сохраненная в коммите, либо готовая к коммиту.

Вы также можете просмотреть имена всех индексных копий файлов, используя git ls-files. В большом хранилище это печатает лот имен! Однако он не предназначен для обычного повседневного использования и не очень удобен для пользователя.


Commits read index;git checkout пишет в него

Чтобы сделать новый коммит, вы просто копируете нужные файлы в индекс и запускаете git commit. Индекс уже содержит всех файлов из текущего коммита, поэтому вам нужно только обновить любые файлы, которые вы хотите изменить, или добавить любые новые файлы, которые вы хотите, или удалить любыефайлы, которые вы хотите удалить. Затем вы git commit и делаете новый коммит. Этот новый коммит теперь является коммитом HEAD, а теперь коммитом HEAD и индексом совпадают.

Если коммит HEAD и индекс совпадают, и эти два соответствуют рабочему дереву, товсе "чисто", и вы можете легко переключиться на другой коммит, используя, например:

git checkout otherbranch

(или новую команду Git 2.23 git switch, которая похожа на дружественный вариант git checkout <em>branch</em>, который невсе другие инструменты Git объединены в одну команду - git checkout может выполнять где-то от трех до семи различных заданий, в зависимости от того, как вы считаете).

Эта проверка, если она успешна, 3 должен:

  1. заполнить ваш индекс всеми файлами из кончика otherbranch (и удалить все ненужные);
  2. заполнить ваше рабочее дерево всемифайлы из кончика otherbranch (и удалите все ненужные);и
  3. сделать имя HEAD ссылкой на коммит-коммит otherbranch.

Как только это будет сделано, ваш HEAD коммит, индекс и рабочее дерево сновавсе совпадения.


3 Команда git checkout может иногда успешно *, даже если индекс и рабочее дерево не являются "чистыми". Очистить - это плохо определенный термин, но чтобы узнать больше о том, когда git checkout позволит вам переключать ветви при переносе изменений, см. Извлечение другой ветви, когда в текущей ветви есть незафиксированные изменения .


Заключение

Вы не можете видеть индексные копии файлов! То, что вы можете и должны сделать, это использовать git status, который сравнивает файлы HEAD с индексными копиями. В большом проекте с сотнями, тысячами или даже миллионами файлов Git ничего не скажет почти обо всех из них. Здесь будут упомянуты только те, которые отличаются . Это гораздо полезнее.

Всякий раз, когда ваши HEAD, индекс и рабочее дерево все совпадают, git status говорит ничего . Когда git status видит некоторые вещи, которые не совпадают, он печатает имена файлов под изменениями, подготовленными для фиксации и / или под изменениями, не подготовленными для фиксации , в зависимости от того, является ли это HEAD и индексные копии, которые не согласны, или индексные и рабочие копии дерева, которые не согласны, или и то и другое.

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

git rm удаляет файлы из индекса. Без --cached он также удаляет те же файлы из рабочего дерева. С --cached он оставляет копии рабочего дерева в одиночку - что хорошо для сейчас , но позже git checkout может потребоваться удалить копии рабочего дерева!

Git будетВ общем, старайтесь изо всех сил не уничтожать файлы рабочего дерева с ценными данными. Что же "драгоценного", правда? Ну, если файл рабочего дерева util.py был добавлен и зафиксирован и соответствует HEAD:util.py и :util.py, на данном этапе util.py - это , а не драгоценен больше, потому что, если ты этого хочешь, он есть в коммите. Таким образом, вы можете git checkout старый коммит, который не имеет util.py, и Git будет чувствовать себя абсолютно безопасно, удалив util.py из вашего рабочего дерева. Просто git checkout последняя команда вернулась.

Некоторые команды Git, включая git reset --hard, , будут уничтожать файлы рабочего дерева. Теория git reset --hard заключается в том, что вы хотите сбросить как индекс , так и вашего рабочего дерева. Режим по умолчанию, git reset --mixed, сбрасывает только индексные копии. 4 Именно поэтому git reset -- file "распаковывает" файл - копирует HEAD:file в :file - но не касаетсякопия рабочего дерева file.


4 В частности, git reset --soft, git reset --mixed и git reset --hard позволяют вам делать каждый файл. Если вы хотите сделать только один файл, используя git reset -- file, он всегда использует --mixed. В других случаях вам нужно использовать один из множества альтернативных режимов git checkout. Git 2.23 вводит новую команду git restore, которая предназначена для того, чтобы сделать это менее запутанным. Время покажет, так ли это: git restore технически все еще экспериментален.

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