git rm --cached x vs git reset head --​ x?

GitRef.org — базовый:

git rm удалит записи из промежуточной области. Это немного отличается от git reset HEAD, который "деактивирует" файлы. Под «неустановленным» я подразумеваю, что он возвращает промежуточную область к тому состоянию, которое было до того, как мы начали что-то изменять. git rm, с другой стороны, просто полностью удаляет файл со сцены, чтобы он не был включен в следующий моментальный снимок коммита, тем самым фактически удаляя его.

По умолчанию git rm file полностью удалит файл из промежуточной области, а также с вашего диска> (рабочий каталог). Чтобы оставить файл в рабочем каталоге, вы можете использовать git rm --cached.

Но в чем именно разница между git rm --cached asd и git reset head -- asd?


person Pacerier    schedule 27.04.2011    source источник


Ответы (3)


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

Когда вы делаете что-то вроде git add file, вы добавляете его в индекс. И когда вы его фиксируете, вы также добавляете его в дерево.

Вероятно, это поможет вам узнать еще три общих флага в git reset:

git reset [--<mode>] [<commit>]

Эта форма сбрасывает текущий заголовок ветки на <commit> и, возможно, обновляет индекс (сбрасывая его на дерево <commit>) и рабочее дерево в зависимости от <mode>, которое должно быть одним из следующих:
--soft< /сильный>

Не трогает ни индексный файл, ни рабочее дерево (но сбрасывает голову на <commit>, как и все моды). Это оставляет все ваши измененные файлы. Изменения должны быть зафиксированы, как сказал бы статус git.

--смешанный

Сбрасывает индекс, но не рабочее дерево (т. е. измененные файлы сохраняются, но не помечаются для фиксации) и сообщает, что не было обновлено. Это действие по умолчанию.

--сложно

Сбрасывает индекс и рабочее дерево. Любые изменения отслеживаемых файлов в рабочем дереве с <commit> отбрасываются.

Теперь, когда вы делаете что-то вроде git reset HEAD, на самом деле вы делаете git reset HEAD --mixed, и он сбрасывает индекс до состояния, которое было до того, как вы начали добавлять файлы/добавлять изменения в индекс (через git add). В этом случае, в каком бы состоянии ни была рабочая копия, вы не изменили ее ни на один бит, но изменили индекс таким образом, что теперь он синхронизирован с ГОЛОВКОЙ дерева. Независимо от того, использовался ли git add для подготовки ранее зафиксированного, но измененного файла или для добавления нового (ранее неотслеживаемого) файла, git reset HEAD является полной противоположностью git add.

git rm, с другой стороны, удаляет файл из рабочего каталога и индекса, а при фиксации файл также удаляется из дерева. git rm --cached, однако, удаляет файл только из индекса и сохраняет его в вашей рабочей копии. В этом случае, если файл был ранее зафиксирован, вы сделали индекс отличным от HEAD дерева и рабочей копии, так что HEAD теперь имеет ранее зафиксированная версия файла, в индексе вообще нет файла, а рабочая копия имеет последнюю его модификацию. Коммит теперь синхронизирует индекс и дерево, и файл будет удален из дерева (оставив его без отслеживания в рабочей копии). Если для добавления нового (ранее неотслеживаемого) файла использовалось git add, то git rm --cached является полной противоположностью git add (и практически идентично git reset HEAD).

Git 2.25 представил новую команду для этих случаев, git restore, но начиная с Git 2.28 она описывается как «экспериментальная» на странице руководства в том смысле, что поведение может измениться.

person manojlds    schedule 27.04.2011
comment
Я заметил, что после git rm --cached команда git diff не показывает разницы, но git diff --cached показывает разницу, как будто она все еще кэшируется. Однако git status показывает файл как Untracked. Выглядит как-то непоследовательно. - person haridsv; 06.11.2011
comment
Неважно... Я должен был использовать git reset --mixed. Меня немного смутило утверждение, что git rm --cached противоположно git add. В буквальном смысле это неправильно и может привести к повреждению. В моем случае я использовал git add для добавления измененного файла в промежуточную область и хотел, чтобы это было противоположно этому добавлению, а не первоначальному добавлению файла. + Ответ Грега Хьюгилла помог мне получить более четкое представление. - person haridsv; 06.11.2011
comment
Я нахожу использование рабочей копии, дерева и рабочего дерева немного запутанным. Является ли рабочее дерево рабочей копией или деревом? - person Nealv; 23.09.2013
comment
Как упомянул @haridsv, утверждение, что git rm --cached «является полной противоположностью git add file», вводит в заблуждение. git reset file ближе к противоположности git add file. - person Matt Browne; 14.12.2017
comment
@Nealv с опозданием, но для тех, кто найдет эту ветку: рабочая копия, дерево и рабочее дерево относятся к одному и тому же (в контексте git). - person De Novo; 14.02.2019
comment
@DeNovo Я думаю, что working copy такое же, как working tree, но отличается от tree. Если вы посмотрите на первую строку, автор упомянет три вещи - где tree отличается от working copy. - person Yash Kant; 09.07.2019
comment
Это сумасшествие, эти термины смешиваются - настолько запутанно - я видел по крайней мере 4 варианта рабочего дерева. - person Snowcrash; 08.10.2019

Возможно поможет пример:

git rm --cached asd
git commit -m "the file asd is gone from the repository"

против

git reset HEAD -- asd
git commit -m "the file asd remains in the repository"

Обратите внимание: если вы ничего другого не изменили, вторая фиксация фактически ничего не сделает.

person Greg Hewgill    schedule 27.04.2011
comment
Можете ли вы сказать мне, что на самом деле означает этот двойной дефис -- после HEAD? - person yuva; 06.11.2014
comment
@yuva: -- используется для отделения параметров команды от имен файлов. Если бы были и ветка, и файл с именем asd, то git reset HEAD asd было бы неоднозначно. -- говорит, что все, что следует за этим, является именем файла. - person Greg Hewgill; 06.11.2014
comment
Является ли git reset HEAD <file> точно таким же, как git rm --cached <file>, а затем git add --intent-to-add <file>? - person alcohol is evil; 29.07.2017
comment
@alcoholisevil нет, кроме как в особом случае. См. этот отличный краткий ответ. - person De Novo; 14.02.2019

git rm --cached file удалит файл со сцены. То есть при фиксации файл будет удален. git reset HEAD -- file просто сбросит файл в промежуточной области до состояния, в котором он находился при фиксации HEAD, т. е. отменит любые изменения, которые вы сделали с ним с момента последней фиксации. Если это изменение связано с новым добавлением файла, то они будут эквивалентны.

person yuriks    schedule 27.04.2011
comment
В сочетании с идеей (как упоминалось в других ответах), что git rm --cached file является своего рода противоположностью git add, этот ответ имел для меня большой смысл и был довольно кратким. Почти такой же короткий, как этот комментарий ;) - person rbatt; 05.12.2015
comment
@rbatt просто для того, чтобы оставить здесь комментарий и пояснить, что git rm --cached file не является противоположностью git add file. Поведение оказывается противоположным git add file в конкретном случае, когда вы добавили новый, ранее не отслеживаемый файл. Во всех остальных случаях противоположностью git add file является git reset HEAD file. git reset HEAD file также отменяет git add file в первом случае (добавление неотслеживаемого файла) и в каждом случае, поэтому git предлагает сделать это, если вы хотите отменить добавление git. - person De Novo; 14.02.2019
comment
Что-то не так с вашим ответом, если изменение «добавить файл», то использование git reset HEAD file не будет иметь никакого эффекта, вы получите только fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. - person Andy; 03.06.2021