Ответы:
Потому что в этом нет смысла (другие команды уже предоставляют эту функциональность), и это снижает вероятность случайного неправильного действия.
«Жесткий сброс» для пути только что сделан 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
: re
set && c
heck o
ut)
git checkout -- <path>
следует заменить наgit reset --hard <path>
. Это имеет гораздо больше смысла ...