Чому git не може робити жорсткі / м'які скидання шляхом?


138

$ git reset -- <file_path> може скинутись шляхом.

Однак $ git reset (--hard|--soft) <file_path>буде повідомлено про помилку, як показано нижче:

Cannot do hard|soft reset with paths.

Відповіді:


143

Тому що немає сенсу (інші команди вже надають цю функціональність), і це зменшує потенціал зробити випадкові випадки.

Щойно робиться "жорстке скидання" шляху git checkout HEAD -- <path>(перевірка наявної версії файлу).

Помірне скидання шляху не має сенсу.

Змішане скидання шляху - це те, що git reset -- <path>робить.


72
Особисто я вважаю , git checkout -- <path>повинен бути замінений з git reset --hard <path>. Це має набагато більше сенсу ...
vergenzt

24
git checkout -- <path>не робить жорсткого скидання; він замінює вміст робочого дерева поетапним вмістом. git checkout HEAD -- <path>робить жорстке скидання для шляху, замінюючи і індекс, і робоче дерево версією з комісії HEAD.
Дан Фабуліч

1
@EdPlunkett Er, друге речення у відповіді говорить вам, яка інша команда забезпечує функціональність.
Бурштин

16
-1: Оформлення замовлення на вказану версію не видалить файли з робочої копії, якщо зазначена редакція містить видалені файли. reset --hardз доріжкою забезпечив би цей недолік. Git вже настільки потужний, що виправдання "Ми не даємо вам зробити це задля власного захисту" не має жодної води: Є безліч способів зробити неправильну справу "випадково". Нічого з цього не має значення, коли у вас є git reflog.
void.pointer

1
як зазначає @ void.pointer, замовлення не видалить файли. Якщо ви хочете такої поведінки, то подивіться на цю відповідь. І все-таки сподіваюся, що коли-небудь ми отримаємо git reset --hard -- <path>. Для цього є законні випадки використання.
Маріуш Павельський

18

Ви можете виконати те, що намагаєтесь робити, використовуючи git checkout HEAD <path>.

Однак, надане повідомлення про помилку для мене не має сенсу (так як git resetце добре працює в підкаталогах), і я не бачу причини, чому git reset --hardб не робити саме те, про що ви просите.


з використанням каси етапів змін, що не є тим самим, як скидання --soft
worc

11

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

Отже, що робить скидання git ? Залежно від вказаних параметрів, він може робити дві різні речі:

  • Якщо вказати шлях, він замінить відповідні файли в індексі файлами з комітки (HEAD за замовчуванням). Ця дія взагалі не впливає на робоче дерево і зазвичай використовується як протилежне git add.

  • Якщо не вказати шлях, він переміщує поточну голову гілки до визначеної комірки та разом із цим необов'язково скидає індекс та робоче дерево у стан цього коміту. Ця додаткова поведінка контролюється параметром режиму:
    --soft : не торкайтеся індексу та робочого дерева.
    --mixed (за замовчуванням): скидання індексу, але не робоче дерево.
    --hard : скидання індексу та робочого дерева.
    Є й інші варіанти, див. Документацію для повного списку та деякі випадки використання.

    Якщо ви не вкажете git reset --softкоманду , вона за замовчуванням відповідає HEAD, тому нічого не зробить, оскільки це команда перемістити голову до HEAD (до її поточного стану). git reset --hardЗ іншого боку, це має сенс через його побічних ефектів , він говорить про переміщення голови до HEAD та скидання індексу та робочого дерева на HEAD.

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


зрозуміло, що скидання призначене в першу чергу для переміщення головки гілки, але оскільки вона має додаткову функціональність скидання робочого дерева та індексу для цілих комітетів та функціональність скидання індексу для конкретних файлів, чому це не відбувається чи є функціонал скидання робочого дерева для певних файлів? Я вважаю, що це запитує ОП.
Данило Суза Мораш

Може тому, що ця функціональність (скидання робочого дерева для певних файлів) вже доступна як git checkoutкоманда? І якщо зробити скидання таким же чином, це ще більше бентежить користувачів. Моя відповідь полягала в тому, що --hardваріант не застосовується до певних файлів, оскільки це режим для скидання гілки, а не скидання індексу. І скидання робочого дерева називається замовленням, як ви можете прочитати в інших відповідях. Все це лише погана конструкція користувальницького інтерфейсу Git, IMHO.
користувач

Порівнюючи перший варіант з git checkout: git reset --встановлює лише індекс, а git checkout --встановлює лише робоче дерево?
seeker_of_bacon

4

Переконайтеся, що ви поставили косу рису між початковим або вихідним (джерелом) та фактичним гіллям:

git reset --hard origin/branch

або

git reset --hard upstream/branch`

Будь ласка, прочитайте питання ще раз.
Ксерус

3

За цим є дуже важлива причина: принципи checkoutтаreset .

У термінах Git замовлення означає "внести в поточне робоче дерево". І git checkoutми можемо заповнити робоче дерево даними з будь-якої області, будь то з фіксації у сховищі або окремих файлів з комітету чи області постановки (що є рівним за замовчуванням).

У свою чергу, скидання git не має цієї ролі. Як випливає з назви, воно буде скинути поточний ref, але завжди матиме сховище як джерело, незалежно від "досяжності" (--soft, --mixed або --hard).

Резюме:

  • замовлення : з будь-якого місця (індекс / репо-комітет) -> робоче дерево
  • скинути : Зробити Repo -> Перезаписати HEAD (і необов'язково індексувати і робоче дерево)

Тому, що може бути трохи заплутаним, це існування, git reset COMMIT -- filesоскільки "перезапис HEAD" лише з деякими файлами не має сенсу!

За відсутності офіційного пояснення я можу лише припускати, що розробники git виявили, що resetвсе ще є найкращим ім'ям команди, щоб відкинути зміни, внесені в область постановки, і, враховуючи, що єдиним джерелом даних було сховище, тоді " давайте продовжимо функціональність "замість створення нової команди.

Тож якимось чином git reset -- <files>вже є винятковим: воно не перезаписує ГОЛОВУ. IMHO всі такі варіанти були винятками. Навіть якщо ми можемо запустити --hardверсію, інші (наприклад --soft) не мали б сенсу.


Мені подобається ця відповідь. Дійсно, git reset -- <files>впало так, як його додали, тому що це корисна функція, але ніхто не був впевнений, в яку команду її слід поставити. На щастя, зараз у нас набагато більше розумних git restoreфункціональних можливостей git checkout -- <path> git checkout <commit> -- <path>і git reset [<commit>] -- <path>з значно безпечнішими налаштуваннями та ще більше функцій, яких ви раніше не могли зробити (всупереч тому, що прийнято відповідати. Тепер, нарешті, ви можете легко відновити лише робоче дерево, не торкаючись покажчика).
Mariusz Pawelski

0

Пояснення

В 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>

(Mnenonic для reco: reset && check out)


-2

мерзотник скидання --М'які ГОЛОВИ ~ 1 файл скасування фіксації , але зміни залишаються в місцевому. ім'я файлу може бути - для всіх зафіксованих файлів


6
фатальноCannot do soft reset with paths.
альт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.