Git reset --soft только меняет значения хешей? - PullRequest
0 голосов
/ 30 января 2019

В этом посте автор хорошо объясняет 3 варианта сброса git (мягкий, смешанный, жесткий): https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

Он использует «три дерева» в качестве устройства для представления 1) рабочее дерево, 2) промежуточная область, 3) "история фиксации / ссылки на фиксацию":

--hard сбрасывает (1), (2), (3);

--mixed сбрасывает (2) и (3);

--soft только изменения (3).

Это то, что (3) на самом деле представляет менянемного неясно о.Я вижу, как git reset --soft может использоваться для изменения того, на что указывает ветвь.Но я не знаю, почему здесь используется слово «история».Что именно было изменено, кроме фиксации, на которую ссылаются ветка и HEAD?

Редактировать: В частности, git reset --soft <SHA1> только редактировать i) значение хеш-функции внутри файла .git/refs/heads/master иii) значение хеша внутри .git/HEAD и ничего больше?

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Поскольку вы спрашиваете о конкретной реализации, которую, на мой взгляд, на самом деле легче объяснить, взгляните на то, что на самом деле находится в .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, изменяет набор достижимых коммитов .Если набор растет, достижимо больше коммитов;если оно уменьшается, становится доступным меньше коммитов;если он остается того же размера, то то же самое число коммитов достижимо, но сам набор может или не может быть тем же самым.

«История» - это, в общем и целом,набор коммитов в репозитории, или набор коммитов, достижимых с какого-либо имени, или некоторое подмножество коммитов, достижимых с какого-либо имени.Используя некоторые, но не все эти свободные определения, перемещение имени меняет историю.

0 голосов
/ 30 января 2019

Как писатель писал в теме, для понимания этого вам нужно понять внутренности git.

Я постараюсь объяснить то же самое в лучшем виде.

ВКоммиты git - это связанный список со ссылкой на дерево, в котором есть ссылки для больших двоичных объектов (файлов) и деревьев.

>    C1<------C2<--------C3
>     |        |          |
>     V        V          V
>     T1       T2         T3
>     |       / \         /\
>     V      /   v       /  \
>     B1 <--     B2 <---    B1'

Как вы можете видеть выше

  • В коммите 1 (т.е.) C1 имеет файл B1
  • В C2 добавляется новый файл B2.
  • В C3 изменяется файл B1 (B1 ') и в данные добавляется новый снимок полного файла.структура.

То, что я объяснил выше, это внутренняя структура git.

GIT использует DAG (структура данных ориентированного ациклического графа) * ​​1023 *

Теперь команды ветвления, сброса и извлечения работают только на уровне фиксации (как вы видите коммиты из связанного списка).

Итак, предположим, что ваша ветка указывает на коммит C2, и теперь вы добавляете новый коммит C3 в той же веткетаким образом, указатель ветвления будет перемещаться из C2 в C3.

Аналогичным образом сброс является противоположнымКогда вы делаете сброс, указатель переходит на обратную фиксацию из текущей фиксации.Допустим, вы находитесь на коммите C2 и делаете сброс, вы переместите указатель текущей ветви на предыдущий коммит.

Давайте перейдем к мягкому, жесткому и смешанному.Сброс имеет 3 варианта

  1. hard: здесь указатель перемещается на предыдущий коммит, а изменения предыдущих коммитов полностью удаляются из рабочего каталога.

  2. смешанный: здесь указатель перемещается на предыдущий коммит, а изменения предыдущих коммитов сохраняются в рабочем каталоге без их постановки / добавления, т. е. если вы запускаете команду

    git reset - смешанный HEAD ~ 1

    git commit

    нечего коммитить, рабочее дерево чистое

    , так как вам нужно добавлять / обрабатывать файлы, используя

git add <filename>
soft: Здесь указатель перемещается на предыдущий коммит, а изменения предыдущих коммитов сохраняются в рабочем каталоге с добавлением их, т. Е. Если вы запускаете команду

git reset --mixed HEAD ~ 1

git commit

это создаст новый коммит, так как все изменения были подготовлены для коммита.

Дайте мне знать, если у вас есть какие-либо вопросы.:)

...