Подтвердить что ты не робот

Почему git не может выполнить жесткий/мягкий сброс по пути?

$ git reset -- <file_path> может reset по пути.

Однако $ git reset (--hard|--soft) <file_path> сообщит об ошибке, как показано ниже:

Cannot do hard|soft reset with paths.
4b9b3361

Ответ 1

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

A "hard reset" для пути выполняется только с помощью git checkout HEAD -- <path> (проверка существующей версии файла).

Мягкий reset для пути не имеет смысла.

Смешанный reset для пути - это то, что делает git reset -- <path>.

Ответ 2

Вы можете выполнить то, что вы пытаетесь сделать, используя git checkout HEAD <path>.

Тем не менее, предоставленное сообщение об ошибке не имеет для меня никакого смысла (поскольку git reset отлично работает в подкаталогах), и я не вижу причин, почему git reset --hard не должен делать именно то, что вы просите об этом.

Ответ 3

На вопрос, как уже ответили, я объясню почему.

Итак, что делает git reset? В зависимости от указанных параметров он может выполнять две разные функции:

  • Если вы укажете путь, он заменит соответствующие файлы в индексе на файлы из фиксации (по умолчанию HEAD). Это действие никак не влияет на рабочее дерево и обычно используется как противоположность git add.

  • Если вы не укажете путь, он перемещает текущий заголовок ветки в указанный коммит и, вместе с этим, дополнительно сбрасывает индекс и рабочее дерево в состояние этого коммита. Это дополнительное поведение контролируется параметром mode:
    --soft: не трогайте указатель и рабочее дерево.
    --mixed (по умолчанию): сбросить индекс, но не рабочее дерево.
    --hard: сбросить индекс и рабочее дерево.
    Есть и другие варианты, полный список и некоторые варианты использования см. в документации.

    Когда вы не указываете коммит, по умолчанию используется HEAD, поэтому git reset --soft ничего не будет делать, так как это команда для перевода головы в HEAD (в ее текущее состояние). git reset --hard, с другой стороны, имеет смысл из-за его побочных эффектов, он говорит, что переместите голову в HEAD и сбросьте индекс и рабочее дерево в HEAD.

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

Ответ 4

Убедитесь, что вы поставили косую черту между origin или upstream (source) и фактической веткой:

git reset --hard origin/branch

или

git reset --hard upstream/branch'

Ответ 5

объяснение

В руководстве по 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 \"[email protected]\" && git checkout \"[email protected]\" && git status --short #"  # Avoid: "fatal: Cannot do hard reset with paths."

Затем вы можете сделать одно из:

$ git reco <paths>

$ git reco <branch/commit> <paths>

$ git reco -- <paths>

(Mnenonic для reco: re && c heck o ut)

Ответ 6

За этим стоит очень важная причина: принципы checkout и reset.

В терминах Git оформление заказа означает "внести в текущее рабочее дерево". А с помощью git checkout мы можем заполнить рабочее дерево данными из любой области, будь то из фиксации в репозитории или отдельных файлов из фиксации или из промежуточной области (которая является даже по умолчанию).

В свою очередь, git reset не имеет этой роли. Как следует из названия, он сбросит текущую ссылку, но всегда будет иметь хранилище в качестве источника, независимо от "досягаемости" (--soft, --mixed или --hard).

Резюме:

  • оформить заказ: откуда угодно (индекс/фиксация репо) → рабочее дерево
  • сбросить: Repo commit → Overwrite HEAD (и, возможно, индексировать и рабочее дерево)

Поэтому то, что может немного сбивать с толку, это существование git reset COMMIT -- files, так как "перезаписывать HEAD" только некоторыми файлами не имеет смысла!

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

Так что как-то git reset -- <files> уже немного исключительный: он не перезаписывает ГОЛОВУ. ИМХО все такие вариации были бы исключениями. Даже если мы сможем придумать версию --hard, другие (например, --soft) не будут иметь смысла.

Ответ 7

git reset --soft HEAD ~ 1 имя_файла отменить фиксацию, но изменения остаются в локальном. имя файла может быть - для всех зарегистрированных файлов