Почему существуют 2 способа нефиксировать файл в git?

Иногда git предлагает git rm --cached отключить файл, иногда git reset HEAD file. Когда следует использовать какой?

EDIT:

D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       a
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

D:\code\gt2>touch b

D:\code\gt2>git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       b
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add b

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#
688
задан Senthess 03 авг. '11 в 0:50
источник поделиться
11 ответов

git rm --cached <filePath> не блокирует файл, он фактически выполняет удаление файла (ов) из репо (при условии, что он уже был установлен ранее), но оставляет файл в рабочем дереве (оставив вас с необработанным файлом).

git reset <filePath> будет неустановлено любые поэтапные изменения для данного файла (ов).

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

1109
ответ дан Ryan Stewart 03 авг. '11 в 1:03
источник поделиться

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

git reset HEAD file (который по умолчанию использует флаг --mixed) отличается тем, что в случае, когда файл уже находится в репо, он заменяет индексную версию файла ссылкой на репо (HEAD), эффективно не используя модификации.

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

К вопросу о Why are there 2 ways to unstage a file in git? - никогда не существует только одного способа сделать что-либо в git. это его красота:)

285
ответ дан manojlds 03 авг. '11 в 2:00
источник поделиться

Довольно просто:

  • git rm --cached <file> заставляет git полностью останавливать файл полностью (оставляя его в файловой системе, в отличие от простой git rm *)
  • git reset HEAD <file> отменяет любые изменения, внесенные в файл с момента последнего фиксации (но не возвращает их в файловой системе, в отличие от того, что может предложить название команды **). Файл остается под контролем версии.

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

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

** Я боялся смущающе долгое время использовать команду git reset из-за ее имени - и сегодня я часто просматриваю синтаксис, чтобы убедиться, что я не испортил, (update): я наконец-то нашел время обобщил использование git reset на странице TL;DR, так что теперь я имеют лучшую ментальную модель того, как она работает, и краткое описание, когда я забываю некоторые детали.)

76
ответ дан waldyrious 18 окт. '14 в 0:16
источник поделиться

Этот поток немного устарел, но я все же хочу добавить небольшую демонстрацию, так как это еще не интуитивная проблема:

me$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   to-be-added
#   modified:   to-be-modified
#   deleted:    to-be-removed
#

me$ git rm --cached to-be-added
rm 'to-be-added'

    # ok

me$ git reset -q HEAD to-be-modified

    # ok

me$ git reset -q HEAD to-be-removed

    # ok

me$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   to-be-modified
#   deleted:    to-be-removed
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   to-be-added
no changes added to commit (use "git add" and/or "git commit -a")

git reset HEAD (без -q) дает предупреждение об измененном файле, а его код выхода - 1, который будет считаться ошибкой в ​​script.

Изменить: git checkout HEAD to-be-modified to-be-removed также работает для нестационарной работы, но полностью удаляет изменение из рабочей области

32
ответ дан Daniel Alder 16 апр. '13 в 22:00
источник поделиться

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

git stash
git stash pop

это выполняет reset в HEAD и повторно применяет ваши изменения, позволяя вам перегруппировать отдельные файлы для фиксации. это также полезно, если вы забыли создать ветвь функции для запросов на pull (git stash ; git checkout -b <feature> ; git stash pop).

25
ответ дан ives 10 февр. '15 в 20:06
источник поделиться

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

  • git reset HEAD <file> отключает файл в текущей фиксации.
  • git rm --cached <file> также отключит файл для будущих коммитов. Он не установлен, пока он не будет добавлен снова с помощью git add <file>.

И еще одно важное различие:

  • После запуска git rm --cached <file> и нажмите на свою ветку на удаленный компьютер, любой, кто потянет вашу ветку с удаленного, получит файл, ФАКТИЧЕСКИ удаленный из своей папки, хотя в вашем локальном рабочем наборе файл просто перестает быть просмотренным (то есть физически не удаляется из папки).

Это последнее отличие важно для проектов, которые включают конфигурационный файл, в котором каждый разработчик в команде имеет другую конфигурацию (то есть другой базовый url, ip или порт), поэтому, если вы используете git rm --cached <file>, тот, кто тянет вашу ветку вам придется вручную заново создать конфигурацию, или вы можете отправить их вам, и они могут повторно отредактировать ее обратно в свои настройки ip (и т.д.), потому что удаление только влияет на то, что люди вытаскивают вашу ветку с удаленного.

9
ответ дан DrewT 10 авг. '14 в 23:04
источник поделиться

Скажем, вы stage весь каталог через git add <folder>, но вы хотите исключить файл из поэтапного списка (т.е. список, который генерируется при запуске git status) и сохранить изменения в исключенном файле (вы что-то работали и не готовы к фиксации, но вы не хотите потерять свою работу...). Вы можете просто использовать:

git reset <file>

Когда вы запустите git status, вы увидите, что любой файл вы reset равны unstaged, а остальные файлы, которые вы added, все еще находятся в списке staged.

6
ответ дан jiminikiz 28 авг. '15 в 19:08
источник поделиться

Я удивлен, что никто не упомянул git reflog (http://git-scm.com/docs/git-reflog):

# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}

reflog - это git история, которая не только отслеживает изменения в репо, но также отслеживает действия пользователя (например, pull, checkout to different branch и т.д.) и позволяет отменить эти действия. Поэтому вместо отказа от файла, который был ошибочно поставлен, где вы можете вернуться к точке, где вы не создавали файлы.

Это похоже на git reset HEAD <file>, но в некоторых случаях может быть более зернистым.

Извините - не отвечая на ваш вопрос, а просто указывая еще один способ нестационарных файлов, которые я использую довольно часто (я, например, как и ответы Райана Стюарта и очень валидный).) Надеюсь, это поможет.

5
ответ дан Alex 10 февр. '15 в 15:06
источник поделиться

Мне кажется, что git rm --cached <file> удаляет файл из индекса, не удаляя его из каталога, где будет выполняться простой git rm <file>, так же как OS rm <file> удалит файл из каталога без удаления его версии.

3
ответ дан ernie.cordell 06 июня '13 в 15:06
источник поделиться

1.

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a

(используйте "git rm --cached..." для нестабильности)

  • git - это система указателей

  • у вас еще нет фиксации, чтобы изменить указатель на

  • единственный способ "вывести файлы из ведра, на которые указывает", - это удалить файлы, которые вы сказали git, для просмотра изменений

2.

D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a

git commit -m a

  • вы совершили, сохранено

3.

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

(используйте "git reset HEAD...", чтобы отключиться)

  • вы сделали фиксацию в своем коде в настоящее время
  • теперь вы можете reset указатель на вашу фиксацию вернуться к последнему сохранению
3
ответ дан Timothy L.J. Stewart 08 сент. '16 в 19:26
источник поделиться

Чтобы не обращать внимание на весь каталог, используйте rm рекурсивно (-r)

git rm -r --cached folderpath
0
ответ дан DevWL 18 окт. '17 в 22:52
источник поделиться

Другие вопросы по меткам