невозможно увидеть новый коммит Git после проверки предыдущих коммитов - PullRequest
0 голосов
/ 16 декабря 2018

Я сделал коммит git, VCS, а затем извлек другие из журнала.Я не могу найти новый git commit для оформления заказа.Я потерял все свои изменения и не смог вернуться к новейшему коммиту

1 Ответ

0 голосов
/ 16 декабря 2018

TL; DR

Пока вы сделали свой коммит на ветке, вам просто нужно использовать git checkout <em>branch</em> сейчас.

Если вы сделали свой коммит в detached HEAD режим, вы должны найти его хэш-идентификатор.Целесообразно дать этому хэш-идентификатору удобочитаемое имя, возможно, имя ветви, впоследствии.Вы можете использовать git reflog, чтобы помочь вам найти потерянный хеш-код.

Long

Обратите внимание, что я добавил несколько слов к вашему вопросу здесь.Эта специфика важна.

... и затем я извлек [[]] другой более ранний [commit] из журнала [то есть, используя необработанный хеш-идентификатор, отображаемый git log, я запустил git checkout a123456... или аналогичный].Я не могу найти новый git commit ['hash ID] для проверки.Я потерял все свои изменения и не смог вернуться к новейшему коммиту

Как вы теперь знаете, идентификатор хита Git - это уникальное имя, которое Git использует для поиска каждого коммита.То есть каждый коммит Git имеет какую-то большую уродливую строку букв и цифр, которую Git использует для определения местоположения этого коммита: например,

git checkout 5d826e972970a784bd7a7bdf587512510097b8c7

находит этот коммит (если он существует - это коммит в репозитории Gitдля Git, поэтому он, вероятно, отсутствует в вашем собственном репозитории) и извлекает его содержимое в форму, с которой мы можем работать.

Вы также знаете, что каждый коммит содержит полный и полный снимок вашего исходного кода.Каждый коммит также имеет некоторые метаданные , данные о коммите, такие как ваше имя (или имя того, кто сделал этот коммит), адрес электронной почты и так далее.Возможно, вы не знаете, что каждый коммит также хранит хэш-идентификатор своего родительского (предыдущего или предшествующего) коммита.Например, родителем коммита, чей хеш-идентификатор, который я использовал выше, является коммит, чей хеш-код начинается с b5796d9a.

Когда вы запускаете git log, по умолчанию для Git показывается вам current commit - тот, который вы проверили.Затем Git использует сохраненный родительский идентификатор этого коммита, чтобы показать вам коммит, который был до этого.У этого родителя есть другой родитель, поэтому после показа вам родителя Git переходит к прародителю и так далее.Вот почему вы не можете видеть свой последний коммит: вы начинаете со старого коммита и двигаетесь назад оттуда.

Это первый ключ к использованию Git: Git работает в обратном направлении. Он должен начинаться в конце и двигаться к началу.Но на самом деле он начинается в любой выбранный вами момент времени, поэтому, чтобы вернуться к «сейчас», вам нужно сделать что-то другое.

Обратите внимание, что Git запоминает, какой коммит является текущим коммит, используя механизм, который Git называет HEAD (пишется во всех столицах, как это, хотя вы можете использовать символ @, если хотите).Итак, ниже, когда мы продолжаем упоминать HEAD, помните, что это способ, которым Git запоминает коммит, который вы получили прямо сейчас .

Имена ветвей и тегов

AsВы только что видели, хеш-идентификаторы не очень дружелюбны к человеку.В результате мы, как правило, не используем их много, по крайней мере, не напрямую, и Git не заставляет нас использовать их.Вместо этого Git предлагает нам возможность связывать удобочитаемые имена с различными коммитами.Наиболее важным видом имени является имя ветви , но, возможно, проще начать с иллюстрации имени тега , поскольку имена ветвей имеют несколько специальных свойств.

имя тега - это просто удобочитаемое имя для коммита.Например, в Git-репозитории для Git имя тега v2.20.0 идентифицирует коммит, который сопровождающие обозначили как «Git 2.20».Следовательно, имя v2.20.0 имеет ту же функцию, что и большая уродливая вещь 5d826e9729....Поэтому вместо:

git checkout 5d826e972970a784bd7a7bdf587512510097b8c7

я могу сделать:

git checkout v2.20.0

Конечный результат точно такой же: я получаю версию Git 2.20 (если быть точным, 2.20.0)check-out.

Если я сделаю это, я получу то, что Git называет отделяемой HEAD:

$ git checkout v2.20.0
Note: checking out 'v2.20.0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 5d826e9729 Git 2.20

Причина, по которой Git напечатал все вышеперечисленное, заключается в том, что новички в Git забывают, что это приводит к отсоединению HEAD, и что отсоединенные HEAD могут быть болезненными, если вы забудете.В этом режиме я могу просто git checkout master вернуться в ветку master:

$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

и теперь все снова становится разумным.

Имена ветвей особые

Имена ветвей, такие как имена тегов, идентифицируют какой-то конкретный коммит:

$ git rev-parse master
5d826e972970a784bd7a7bdf587512510097b8c7

Вот тот же самый хэш-идентификатор еще раз.Но есть ключевые различия между именем ветви и любым другим способом присвоения имени коммиту, например v2.20.0 или 5d826e972970a784bd7a7bdf587512510097b8c7.В частности, когда вы используете git checkout с необработанным хеш-идентификатором или с именем тега, Git сохраняет фактический хеш-идентификатор фиксации непосредственно в HEAD.Это тот отдельный режим HEAD, который мы только что видели.

Как только вы перейдете в этот режим, место only , которое имеет Git для поиска текущего идентификатора хеша, - это специальное имя HEAD.Каждый раз, когда вы используете git checkout с другим коммитом, он перезаписывает идентификатор хеша, который Git вставил в HEAD ранее.И так как Git работает в обратном направлении , отсюда легко идти в обратном направлении - очень трудно идти вперед!

Но когда вы даете git checkout a имя ветки подобно master, Git делает что-то совсем другое.Вместо того, чтобы устанавливать HEAD для запоминания необработанного хеш-идентификатора, Git устанавливает его HEAD для запоминания самого имени ветви :

$ cat .git/HEAD
ref: refs/heads/master

Так что теперь вы on branch master, как говорит git status.Git не запоминает хэш-идентификатор напрямую, а скорее запоминает тот факт, что вы находитесь в этой ветке.Между тем, имя ветви помнит хеш коммита.Таким образом, HEAD присоединено к имени, а имя имеет хэш-идентификатор.

Если вы сейчас делаете новый коммит, то, что Git делает в этот момент, особенно умно.Git строит новый коммит как обычно, используя хэш-идентификатор текущего коммита в качестве родителя нового коммита.Затем, когда новый коммит завершен и ему присвоен большой уродливый хеш-идентификатор, Git записывает хеш-код нового коммита в имя master, то есть имяк которому прикреплен HEAD.

Мы можем нарисовать это в виде картинки, хотя это очень помогает заменить большие уродливые идентификаторы хеша одиночными буквами.Допустим, мы находимся в коммите, чей идентификатор хеша равен H, а его родитель имеет идентификатор хеша G, чей родитель равен F, и так далее.Мы говорим, что каждый коммит указывает на его родителя:

... <-F <-G <-H

* имя ветви master содержит идентификатор хэша H, поэтому masterсам по себе указывает на H:

... <-F <-G <-H   <--master

Наконец, HEAD является присоединенным к master, поэтому, если существует несколько имен веток, Git знает, какое из них использовать:

...--F--G--H   <-- master (HEAD)
         \
          I--J--K   <-- develop

Итак, если мы сейчас сделаем наш новый коммит, ему будет присвоен новый хэш-идентификатор - я буду использовать следующую букву L здесь - и он укажет на H, изатем Git перезаписывает имя master, чтобы оно указывало на L:

...--F--G--H--L   <-- master (HEAD)
         \
          I--J--K   <-- develop

Так что это второй ключ к использованию Git: перемещение имен ветвей. Имя ветви содержитидентификатор хэша последнего коммита в ветви.Создание нового коммита, когда у вас извлечена какая-то конкретная ветвь - в то время как ваш HEAD присоединен к этому имени ветки - автоматически перемещает имя ветки.

Поскольку ваш HEAD присоединен к имени ветви, а имя ветви теперь идентифицирует новый последний коммит, git log начнется с коммита L и будет работать в обратном направлении, показывая вам L, затемH, затем G и т. Д.

Вот почему отдельные заголовки немного болезненны

Предположим, что у вас есть оригинальная последовательность выше, но вы используете git checkout снеобработанный хэш-идентификатор для выбора исторического коммита G.Чтобы все было в порядке, нам нужно немного поднять H:

          H   <-- master
         /
...--F--G   <-- HEAD
         \
          I--J--K   <-- develop

Теперь давайте сделаем новый коммит L:

          H   <-- master
         /
...--F--G--L   <-- HEAD
         \
          I--J--K   <-- develop

Примечаниечто только имя для нового коммита L равно HEAD.Теперь давайте используем git checkout в , переместим наш HEAD куда-нибудь еще или повторно прикрепим его.Например, давайте просто присоединим его к master:

          H   <-- master (HEAD)
         /
...--F--G--L
         \
          I--J--K   <-- develop

Команда git log будет начинаться с коммита H и будет работать в обратном направлении, показывая нам H, затем G, затем F и т. д. как обычно.

Если мы не сохранили (записали или в режиме прокрутки в окне терминала или что-то еще) хеш-идентификатор commit L, как мы будемкогда-нибудь снова находите этот коммит?

Вот где появляются рефлоги

Чтобы помочь спасти нас от ошибок, Git хранит журнал предыдущих значений каждого из этих различныхимена.То есть, если master указывал на G в какой-то момент - прежде чем мы сделали H - и тогда мы сделали H, master теперь указывает на H, но использовалось для указывает на G, поэтому Git сохраняет запись reflog, написанную master@{1}, чтобы помнить, что master когда-то указывал на G.

Git делает то же самое со специальным именем HEAD.Каждый раз, когда мы проверяем какой-то новый коммит, Git обновляет рефлог HEAD.Мы можем просмотреть этот reflog с помощью git reflog, который по умолчанию показывает отображение reflog для HEAD:

$ git reflog
5d826e9729 (HEAD -> master, tag: v2.20.0, origin/master, origin/HEAD) HEAD@{0}: checkout: moving from 5d826e972970a784bd7a7bdf587512510097b8c7 to master
5d826e9729 (HEAD -> master, tag: v2.20.0, origin/master, origin/HEAD) HEAD@{1}: checkout: moving from master to v2.20.0

В этом случае первые две записи reflog не особенно интересны, так как оба предназначены для последнего коммитана master.Но если вы сделали коммит, как L на нашем рисунке выше, и теперь нужно найти его хэш-идентификатор, git reflog может быть весьма полезным.

Предоставление нового имени ветки существующему коммиту

Предположим, что вы действительно сделали L подобным образом и потеряли его:

          H   <-- master (HEAD)
         /
...--F--G--L
         \
          I--J--K   <-- develop

Затем вы используете git reflog, чтобы найти его, и вы его нашли.Теперь вы можете проверить это:

git checkout llllllllllllllllllllllllllllllllllllllll

(конечно, используйте фактический хэш-идентификатор).Теперь вы будете в режиме «отсоединенного ГОЛОВКА», и теперь пришло время для совета, который печатает git checkout при первом входе в этот режим отсоединенного ГОЛОВКА.Он сказал, что мы можем использовать, например, git checkout -b:

git checkout -b xyz-branch

.

Для этого нужно создать a новое имя ветви,указывает на текущую (то есть HEAD) фиксацию, а затем немедленно присоединяет HEAD к этой фиксации.Итак, теперь у нас есть:

          H   <-- master
         /
...--F--G--L   <-- xyz-branch (HEAD)
         \
          I--J--K   <-- develop

Теперь все готово, потому что у нас есть понятное человеку имя ("xyz-branch") для last зафиксировать в этой новой ветке.Каждый раз, когда мы добавляем новый коммит, проверяя ветку, выполняя некоторую работу и фиксируя ее, Git автоматически обновляет имя новой ветки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...