Short
... "переместить кончик текущей ветви к предыдущему коммиту в той же ветви, сокращая текущую ветку" ...
Этот является одним из способов использования git reset
. Тем не менее, он также может удлинить текущую ветвь или полностью переместить ее в другое место, или не делать ни того, ни другого. Если HEAD
присоединен (обычный случай), эффект на имя-как-указатель больше похож на «go to»:
F <-- a
/
D--E <-- b (HEAD)
/
...--C--G--H <-- master
\
I--J <-- develop
Так как HEAD
присоединяется к имени b
, git reset
к некоторому произвольному коммиту, например H
или I
, переместится b
так, чтобы оно указывало на что совершать. Если вы выберете C
или D
, это можно рассматривать как «укоротить текущую ветвь» (в этом случае оставшиеся коммиты теперь находятся только в ветке a
). Однако, если вы выберете F
, так что b
и a
оба будут указывать на F
, это можно рассматривать как «удлинение текущей ветви». Если вы выберете коммит J
, так что b
и develop
оба указывают на J
, трудно назвать это сокращение или удлинением.
Long
Команда git reset
очень сложна, потому что, как и ряд других команд Git, она выполняет некоторые действия, которые не обязательно связаны друг с другом. Например, git reset -p <em>file</em>
действует как своего рода инверсия git add -p <em>file</em>
, и на самом деле обе операции (добавление и сброс с помощью -p) реализованы с помощью другой внутренней команды Git, написанной на Perl. , а не программами на C-языке с именами git-reset
и git-add
. 1
Однако есть три «основных режима» сброса, каждый из которых имеет общий набор действий, которые они делают. Это те, которые вы получаете с git reset --soft
, git reset --mixed
и git reset --hard
, ни один из которых не разрешает указатели имени пути, но все они разрешают определитель фиксации:
git reset --soft a234567
git reset --mixed cafedad
git reset --hard HEAD~3
например.
Что они делают:
Разрешить спецификатор коммита в хеш-код коммита, например git rev-parse
. Короткий хеш, такой как a234567
или cafedad
, ищется в базе данных хэш-идентификаторов и превращается в полный хэш-идентификатор. Имя типа master
или v2.3
ищется в базе данных name-to-hash-ID, а затем при необходимости преобразуется в хеш коммита. Относительное имя, такое как HEAD~3
, предписывает Git разрешить первую часть, а затем применить оператор отношения, поэтому HEAD~3
сначала ищет идентификатор хеша для HEAD
, а затем возвращает обратно три первых родителя в графе фиксации.
Этот шаг может завершиться неудачей либо потому, что хеш-идентификатор недействителен, либо потому, что он не может быть преобразован в коммит (это хеш-код дерева или большого двоичного объекта). В этом случае git reset
останавливается с сообщением об ошибке.
Вы можете опустить спецификатор фиксации, в этом случае спецификатор фиксации будет считан из текущего значения HEAD
. То есть, если к какому-либо имени ветки присоединено HEAD
- например, если вы используете master
или develop
- Git будет читать хэш-идентификатор из этого имени ветки. Если HEAD
отсоединен, он уже содержит необработанный хеш-идентификатор, поэтому Git будет считывать хеш-идентификатор из HEAD
.
Теперь, когда git reset
имеет хеш-идентификатор, он записывает этот хэш-идентификатор в или через HEAD
. 2 То есть, если HEAD
присоединено к имени ветви, Git будет хранить новый идентификатор хеша в этом имени ветви. Если HEAD
отключен, Git запишет недавно выбранный хэш-идентификатор в HEAD
.
Обратите внимание, что если вы указали HEAD
на шаге 1 или ничего не указали на шаге 1, это записывает текущее значение, прочитанное из HEAD
обратно в или сквозной HEAD
, что означает, что ничего не меняется. Однако, если вы действительно указали какую-то другую фиксацию, то в этот момент изменяется либо HEAD
(случай отсоединенного HEAD), либо изменяется цель HEAD
(случай присоединенного HEAD).
Если вы использовали --soft
, git reset
теперь закончен.
В противном случае - для --mixed
или --hard
- git reset
теперь сбрасывает индекс, чтобы его содержимое соответствовало коммиту, указанному HEAD
.
Если вы использовали --mixed
, git reset
теперь закончен.
в противномise - т.е. только для git reset --hard
- git reset
теперь сбрасывает рабочее дерево, делая его содержимое совпадающим с индексом, который был только что сброшен на шаге 3.
(Шаги 3 и / или 4 также могут быть неудачными. Если шаг 3 не пройден, Git может восстановить HEAD
и индекс до того, как они были до git reset
, даже запущенного, потому что Git обновляет эти две сущности, создавая новые и затем использование атомарной операции для обмена обновлениями в базовой файловой системе. Однако, если шаг 4 завершится неудачно, вы, вероятно, останетесь в беспорядке.)
1 Когда вы запускаете git xyz
, Git помещает внутренний каталог git-core
в $PATH
. (Описание здесь слегка sh / bash-centric, но алгоритм тот же, даже в Windows.) Запустите git --exec-path
, чтобы увидеть, где этот каталог git-core
находится в вашей установке. Загляните в этот каталог, и вы найдете программы с именами git-add
, git-commit
, git-rebase
, git-reset
и так далее. Таким образом, git xyz
работает так, что Git устанавливает некоторый контекст, вставляет этот «основной» каталог в начало $PATH
, а затем вызывает git-xyz
. Если этот файл существует в git-core
, это тот, который запускается сейчас. Если нет, будет запущен любой другой файл с именем git-xyz
, который находится где-либо в вашем $PATH
. Таким образом, вы можете написать свою собственную программу, встроить ее в исполняемый файл с именем git-xyz
и запустить ее с git xyz
, если в этом каталоге git-core нет git-xyz
.
2 Имя HEAD
является особенным в Git. Он буквально жестко запрограммирован в различных исходных файлах, а в древнем прошлом Git он хранился как символическая ссылка. Этот метод не работает в Windows, поэтому в какой-то момент имя стало немного менее особенным: теперь любая ссылка теперь может быть тем, что Git называет символьной ссылкой . Символьная ссылка - это ссылка, которая разрешается чтением некоторой другой ссылки. Команда git symbolic-ref
является внешним интерфейсом для чтения и записи таких ссылок.
Хотя теперь любая ссылка может быть сделана символической, HEAD
по-прежнему важен для Git: если файл отсутствует, Git будет утверждать, что хранилище больше не является хранилищем. Поскольку это один из наиболее активных файлов в хранилище, если ваша система падает, когда вы выполняете какую-либо команду Git, иногда файл пропадает. В этом случае вы часто можете восстановить все, просто вручную создав отсутствующий файл HEAD
.