Ответы:
Потому что в этом нет смысла (другие команды уже предоставляют эту функциональность), и это снижает вероятность случайного неправильного действия.
«Жесткий сброс» для пути только что сделан git checkout HEAD -- <path>(проверяя существующую версию файла).
Мягкий сброс для пути не имеет смысла.
Смешанный сброс для пути это то, что git reset -- <path>делает.
git checkout -- <path>не делает хард ресет; он заменяет содержимое рабочего дерева поэтапным содержимым. git checkout HEAD -- <path>выполняет полный сброс пути, заменяя индекс и рабочее дерево версией из коммита HEAD.
reset --hardс путем обеспечил бы этот недостающий кусок. Git уже настолько силен, что «Мы не позволяем вам сделать это для вашей собственной защиты», оправдание не содержит воды: существует множество способов сделать неправильную вещь «случайно». Ничего из этого не имеет значения, если у вас есть git reflog.
git reset --hard -- <path>. Есть законные варианты использования для этого.
Вы можете выполнить то, что вы пытаетесь сделать, используя git checkout HEAD <path>.
Тем не менее, предоставленное сообщение об ошибке не имеет смысла для меня (так git resetкак прекрасно работает на подкаталогах), и я не вижу причин, почему git reset --hardне следует делать именно то, что вы просите об этом.
На вопрос, как уже ответили , я объясню, почему часть.
Итак, что делает git reset ? В зависимости от указанных параметров он может выполнять две разные функции:
Если вы укажете путь, он заменит сопоставленные файлы в индексе файлами из фиксации (по умолчанию HEAD). Это действие вообще не влияет на рабочее дерево и обычно используется как противоположность git add.
Если вы не укажете путь, он перемещает текущий заголовок ветви в указанный коммит и, вместе с этим , дополнительно сбрасывает индекс и рабочее дерево в состояние этого коммита. Это дополнительное поведение контролируется параметром mode:
--soft : не трогать индекс и рабочее дерево.
--mixed (по умолчанию): сбросить индекс, но не рабочее дерево.
--hard : сбросить индекс и рабочее дерево.
Есть и другие варианты, полный список и некоторые варианты использования см. В документации.
Когда вы не указываете коммит, по умолчанию используется HEAD, поэтому git reset --softничего не будет сделано, поскольку это команда для перевода головы в HEAD (в ее текущее состояние). git reset --hardс другой стороны, имеет смысл из-за его побочных эффектов , он говорит, переместите голову в HEAD и сбросьте индекс и рабочее дерево в HEAD.
Я думаю, к настоящему времени должно быть понятно, почему эта операция не предназначена для конкретных файлов по своей природе - она предназначена для перемещения головки ветви в первую очередь, сброса рабочего дерева, а индекс является вторичной функциональностью.
git checkoutкоманда? А сброс настроек для выполнения той же задачи может еще больше запутать пользователей. Я ответил, что эта --hardопция не применима к определенным файлам, потому что это режим сброса ветвей, а не индексации. И сброс рабочего дерева называется checkout, как вы можете прочитать в других ответах. Все это просто плохой дизайн пользовательского интерфейса Git, ИМХО.
git checkout: git reset --устанавливает только индекс, а git checkout --устанавливает только рабочее дерево?
Убедитесь, что вы поставили косую черту между origin или upstream (source) и фактической веткой:
git reset --hard origin/branch
или
git reset --hard upstream/branch`
За этим стоит очень важная причина: принципы checkoutиreset .
В терминах Git оформление заказа означает «внести в текущее рабочее дерево». И с помощью git checkoutмы можем заполнить рабочее дерево данными из любого области, будь то из коммита в репозитории или отдельных файлов из коммита или промежуточной области (что даже по умолчанию).
В свою очередь, git reset не имеет этой роли. Как следует из названия, он будет сбрасывать текущий ref, но всегда имея хранилище в качестве источника, независимо от «досягаемости» (--soft, --mixed или --hard).
Резюме:
Поэтому то, что может быть немного запутанным, это существование git reset COMMIT -- files поскольку «перезапись HEAD» только некоторыми файлами не имеет смысла!
В отсутствие официального объяснения я могу только предположить, что разработчики git обнаружили, что resetэто все еще было лучшим названием команды для отмены изменений, внесенных в промежуточную область, и, учитывая, что единственным источником данных был репозиторий, тогда « давайте расширим функциональность »вместо создания новой команды.
Так что как-то git reset -- <files>уже немного исключительно: оно не перезаписывает ГОЛОВУ. ИМХО все такие вариации были бы исключениями. Даже если мы сможем придумать --hardверсию, другие (например --soft) не будут иметь смысла.
git reset -- <files>упал так, как будто он был добавлен, потому что это полезная функция, но никто не был уверен, в какую команду ее следует ставить. К счастью, теперь у нас гораздо больше здравомыслящих, git restoreкоторые имеют функциональность git checkout -- <path> git checkout <commit> -- <path>и git reset [<commit>] -- <path>гораздо более разумные настройки по умолчанию и еще больше функций, которые вы не могли сделать раньше (вопреки тому, что говорит принятый ответ. Теперь вы можете легко восстановить только рабочее дерево, не касаясь индекса).
В git resetруководстве перечислены 3 способа вызова:
2 относятся к файлам: они не влияют на рабочее дерево , а работают только с файлами в индексе, указанном <paths>:
git reset [-q] [<tree-ish>] [--] <paths>..git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]1 является обязательным: работает со всеми файлами в ссылках <commit>и может влиять на рабочее дерево:
git reset [<mode>] [<commit>]Нет режима вызова, который работает только с указанными файлами и влияет на рабочее дерево.
Если вы хотите оба:
Вы можете использовать этот псевдоним в вашем файле конфигурации git:
[alias]
reco = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #" # Avoid: "fatal: Cannot do hard reset with paths."
Затем вы можете сделать одно из:
$ git reco <paths>
$ git reco <branch/commit> <paths>
$ git reco -- <paths>
(Мненоник для reco: reset && check out)
git checkout -- <path>следует заменить наgit reset --hard <path>. Это имеет гораздо больше смысла ...