Поскольку вы спрашиваете о конкретной реализации, которую, на мой взгляд, на самом деле легче объяснить, взгляните на то, что на самом деле находится в .git/HEAD
, когда вы находитесь на ветке:
$ cat .git/HEAD
ref: refs/heads/master
$ git checkout -b new
Switched to a new branch 'new'
$ cat .git/HEAD
ref: refs/heads/new
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ cat .git/HEAD
ref: refs/heads/master
Так что, пока я "на ветке", как скажет git status
, имя ветви - полное имя ссылки, на самом деле - находится в .git/HEAD
.Таким образом, .git/HEAD
не изменяется и не нуждается в изменении.
Вопрос о том, существует ли .git/refs/heads/master
, более проблематичен:
$ cat .git/refs/heads/master
cat: .git/refs/heads/master: No such file or directory
$ git rev-parse master
b5101f929789889c2e536d915698f58d5c5c6b7a
$ grep master .git/packed-refs
b5101f929789889c2e536d915698f58d5c5c6b7a refs/heads/master
b5101f929789889c2e536d915698f58d5c5c6b7a refs/remotes/origin/master
То, что здесь произошло, это то, что Git имеет упаковано моих имен ссылок, так что больше нет простого файла: refs/heads/master
хранится вместо этого в .git/packed-refs
как одна из нескольких строк (другая совпадающая строка в этом случае - refs/remotes/origin/master
).
То есть карта ссылки на хэш-идентификатор хранится в некоторой базе данных , не обязательно в простом файле.(Однако «база данных» с упакованными ссылками все еще довольно проста.)
Однако, чтобы ответить на ваш главный вопрос, просто да : git reset --soft <hash>
записывает <hash>
в имяотображение на хеш-идентификатор.Это верно, даже если мы используем имя вместо хеш-идентификатора:
$ git checkout new
$ git reset --soft master~3
Имя new
теперь относится к тому же хеш-идентификатору фиксации, к которому относится имя master~3
:
$ git rev-parse new
371820d5f1bb3c3e691ad21cee652c02c36ea758
$ git rev-parse master~3
371820d5f1bb3c3e691ad21cee652c02c36ea758
(Акт записи нового хеш-идентификатора в имя new
происходит в текущих версиях Git, чтобы переопределить базу данных упакованных ссылок, написав простой файл .git/refs/heads/new
, но вы не должны зависеть отэто - используйте git rev-parse
и git update-ref
вместо.)
Так как я создал new
из master
, выше, это просто привело к перемещению имени new
назад на три первых родителя.хмель (master~3
).Это означает, что new
является предком master
, поэтому:
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ git branch -d new
Deleted branch new (was 371820d5f1).
... так что Git в порядке, просто удалив имя new
сейчас, так как оно полностью объединено с master
.
Но я не знаю, почему здесь используется слово «история».
«История» на самом деле не лучшее слово.Чтобы действительно понять это, прочитайте на сайте Думайте, как (а) Git .Ключевой концепцией здесь является достижимость .Изменение идентификатора хеша фиксации, хранящегося под именем ветви, как это делает git reset
, изменяет набор достижимых коммитов .Если набор растет, достижимо больше коммитов;если оно уменьшается, становится доступным меньше коммитов;если он остается того же размера, то то же самое число коммитов достижимо, но сам набор может или не может быть тем же самым.
«История» - это, в общем и целом,набор коммитов в репозитории, или набор коммитов, достижимых с какого-либо имени, или некоторое подмножество коммитов, достижимых с какого-либо имени.Используя некоторые, но не все эти свободные определения, перемещение имени меняет историю.