git checkout <em>commit</em>
переключает ваше текущее состояние в указанное на commit
...
Да, вроде.Это на самом деле значительно сложнее под капотом.
... и повторно применяет любые незафиксированные изменения (даже неудачно, если ваши незафиксированные изменения несовместимы с commit
, который вы хотитепереключиться на).
Это действительно не делает эту первую часть (но делает вторую), и это осложнение: то, что делает git checkout
, является подмножеством того, что документация git read-tree
вызывает объединение двух деревьев .Если вы перейдете по этой ссылке, вы увидите, что здесь перечислены 21 отдельный случай (один, случай № 3, имеет два подслоя, и я игнорирую случай № 0, который не может произойти, поэтому, если вы подсчитаете подслотыи случай № 0, вы получите 23 разных случаев).Я не буду перечислять их всех здесь, но они как бы сводятся к этой идее: Если Git не нужно прикасаться к индексу и рабочему дереву при переключении коммитов, это не так. Вот чтосохраняет ваши незафиксированные изменения на месте: Git не повторно применяет что-либо, просто он не вырывает также ничего.Это просто мягко ходит на цыпочках вокруг незавершенных изменений.
Это, в свою очередь, в некотором роде (но не полностью) объясняет это радикально иное поведение, что некоторые, в том числе и я, могут зайти так далеко, что называют злом:
Эта функция резко контрастирует с git checkout <em>commit</em> <em>file</em>
, которая просто слепо отбрасывает любые незафиксированные изменения (без какого-либо предупреждения) file
и "форсирует" состояниеиз file
, что в commit
.
Верно, и это потому, что Git рассматривает вашу команду как запрос на замену индексная копия file
с копией из commit
.Обновленная индексная копия также копируется в рабочее дерево.
Я бы сказал (и имел в прошлом), что это должна быть отдельная команда Git .Он реализуется одним и тем же исходным кодом просто потому, что этот исходный код полон кода «извлечение файла из коммита, запись в индекс и рабочее дерево».Но git reset
и git reset
- это отдельная команда. 1 Так что в лучшем случае это оправдание формы Hysterical Raisins .
Конечно, это можно было сделать так, что git checkout <em>commit</em> <em>file</em>
попытался повторно применить незафиксированные изменения к file
и потерпел неудачу изящно, если это не удалось.
ТоТакже доступно в git checkout
, в опции -m
... вроде.Однако, это не на основе на файл , а на основе всего коммита .То есть вы можете git checkout -m <em>commit</em>
, который объединяет ваше рабочее дерево с целевым коммитом (как слияние из трех деревьев), но не git checkout -m <em>commit</em> <em>file</em>
.Чтобы получить этот эффект, извлеките файл из коммита, выберите базовую версию слияния для извлечения и используйте git merge-file
для трех файлов:
git show other:file > file.other
git show base:file > file.base
git merge-file file file.base file.other
1 Git'sreset
также объединяет слишком много несвязанных битов функциональности в одну команду, обращенную к пользователю, если вы спросите меня, но вы этого не сделали.
(С другой стороны,поведение git reset <em>commit</em>
и git reset <em>file</em>
также оставляет место для улучшения согласованности ...)
ОК, возможно, вы сделали!: -)