Вопрос по git, git-reset – Почему git не может делать жесткий / мягкий сброс по пути?

108

$ git reset -- <file_path> можно сбросить по пути.

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

Cannot do hard|soft reset with paths.

Ваш Ответ

6   ответов
0

Это очень важная причина:the principles of checkout and reset.

В терминах Git,checkout означает «внести в текущее рабочее дерево». И сgit checkout мы можем заполнить рабочее дерево данными изany область из коммита в репозитории или отдельных файлов из коммита илиstaging area (который является даже по умолчанию).

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

Резюме:

  • checkout: From anywhere (index / repo commit) -> working tree
  • reset: Repo commit -> Overwrite HEAD (and optionally index and working tree)

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

В отсутствие официального объяснения, я могу только предположить, что разработчики Git обнаружили, чтоreset было по-прежнему лучшим названием команды для отмены изменений, внесенных в промежуточную область, и, учитывая, что единственным источником данных был репозиторий, то & quot;let's extend the functionality& Quot; вместо создания новой команды.

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

0

Explanation

git reset manual перечисляет 3 способа вызова:

  • 2 are file-wise: These do not affect the working tree, but operate only on the files in the index specified by <paths>:

    • git reset [-q] [<tree-ish>] [--] <paths>..
    • git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
  • 1 is commit-wise: Operates on all files in the referenced <commit>, and may affect the working tree:

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

Нет режима вызова, который работает только с указанными файламиand влияет на рабочее дерево.

Workaround

Если вы хотите оба:

  • Reset the index/cache version of a file(s)
  • Checkout the file(s) (ie, make the working tree match the index and commit version)

Вы можете использовать этот псевдоним в вашем файле конфигурации 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>

(Мненоник дляreco: reустановить & amp;cщеколдаoут)

7

Вопросhow ужеответилЯ объяснюwhy часть.

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

  • If you specify a path, it replaces the matched files in the index with the files from a commit (HEAD by default). This action doesn't affect the working tree at all and is usually used as the opposite of git add.

  • If you don't specify a path, it moves the current branch head to a specified commit and, together with that, optionally resets the index and the working tree to the state of that commit. This additional behavior is controlled by the mode parameter:
    --soft: don't touch the index and the working tree.
    --mixed (default): reset the index but not the working tree.
    --hard: reset the index and the working tree.
    There are also other options, see the documentation for the full list and some use cases.

    When you don't specify a commit, it defaults to HEAD, so git reset --soft will do nothing, as it is a command to move the head to HEAD (to its current state). git reset --hard, on the other hand, makes sense due to its side effects, it says move the head to HEAD and reset the index and the working tree to HEAD.

    I think it should be clear by now why this operation is not for specific files by its nature - it is intended to move a branch head in the first place, resetting the working tree and the index is secondary functionality.

Возможно, потому что эта функциональность (сброс рабочего дерева для определенных файлов) уже доступна какgit checkout команда? А сброс настроек для выполнения той же задачи может еще больше запутать пользователей. Мой ответ был таков--hard Эта опция не применима к определенным файлам, потому что это режим сброса ветви, а не сброса индекса. И сброс рабочего дерева называется checkout, как вы можете прочитать в других ответах. Все это просто плохой дизайн пользовательского интерфейса Git, IMHO.
ясно, что сброс предназначен в первую очередь для перемещения заголовка ветви, но поскольку он имеет дополнительные функции сброса рабочего дерева и индекса для всех фиксаций, а также функциональность сброса индекса для конкретных файлов, почему это не так? у него есть функциональность сброса рабочего дерева для определенных файлов? Я полагаю, что именно об этом спрашивает ОП.
113

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

«Хард ресет» для пути просто сделано сgit checkout HEAD -- <path> (проверка существующей версии файла).

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

Что такое смешанный сброс для путиgit reset -- <path> делает.

Примечание для тех, кто не заметил, что. был вне кода snip & git checkout HEAD - & lt; path & gt; . & Quot; будет сбрасывать все - не включать.
Почему нет смысла? Какие другие команды предоставляют такую функциональность? В вашем ответе нет содержания, кроме «Вы не можете этого сделать». Бессмысленное сообщение об ошибке уже очень хорошо сообщило об этом факте. Почему это говорит мне о «путях»? Очень полезно
git checkout -- <path> не выполняет полный сброс; он заменяет содержимое рабочего дерева поэтапным содержимым.git checkout HEAD -- <path> выполняет полный сброс пути, заменяя индекс и рабочее дерево версией из фиксации HEAD.
Лично я считаюgit checkout -- <path> должно бытьreplaced сgit reset --hard <path>, Это имеет гораздо больше смысла ...
-1: возврат к указанной ревизии не удалит файлы из рабочей копии, если указанная ревизия содержит удаленные файлы.reset --hard с путем обеспечил бы этот недостающий кусок. Git уже настолько мощен, что «мы не позволяем вам сделать это для вашей собственной защиты». Оправдание не дает воды: есть много способов сделать что-то не так "случайно". Ничего из этого не имеет значения в любом случае, когда у вас естьgit reflog.
-1

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

фатальныйCannot do soft reset with paths.
17

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

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

Похожие вопросы