Как я могу переместить ГОЛОВУ назад в предыдущее место? (Отдельная голова) & Отменить фиксацию

git git-checkout git-reset git-revert git-reflog


В Git я пытался выполнить squash commit , объединив другую ветку и затем сбросив HEAD на прежнее место с помощью:

git reset origin/master

Но мне нужно выйти из этого.Как я могу переместить ГОЛОВУ обратно на прежнее место?

У меня есть фрагмент SHA-1 ( 23b6772 ) коммита, в который мне нужно переместить его. Как я могу вернуться к этому коммиту?




Answer 1 CodeWizard


Прежде чем ответить, давайте добавим некоторую предысторию, объясняющую, что это за HEAD .

First of all what is HEAD?

HEAD - это просто ссылка на текущий коммит (последний) в текущей ветке.
В любой момент времени может быть только один HEAD (исключая git worktree ).

Содержимое HEAD хранится в .git/HEAD и содержит 40 байтов SHA-1 текущего коммита.


detached HEAD

Если вы не используете последний коммит - это означает, что HEAD указывает на предыдущий коммит в истории, он называется detached HEAD .

Enter image description here

В командной строке это будет выглядеть так - SHA-1 вместо имени ветви, поскольку HEAD не указывает на конец текущей ветви:

Enter image description here

Enter image description here


Несколько вариантов,как восстановиться от отсоединенной HEAD:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

При этом будет извлечена новая ветка,указывающая на нужный коммит.
Эта команда выведет на заданный коммит.
В этот момент вы можете создать ветку и начать работу с этой точки.

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Вы также всегда можете использовать reflog .
git reflog отобразит все изменения, которые обновили HEAD , а проверка нужной записи reflog вернет HEAD к этому коммиту.

Каждый раз, когда reflog в reflog будет новая запись

git reflog
git checkout HEAD@{...}

Это вернет вас к желаемому обязательству

Enter image description here


git reset --hard <commit_id>

"Переместите" свой ГОЛОВА обратно на нужный коммит.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Примечание: ( начиная с Git 2.7 ) вы также можете использовать git rebase --no-autostash .

git revert <sha-1>

"Отменить" данный коммит или диапазон коммитов.
Команда сброса "отменяет" все изменения,сделанные в данной фиксации.
Новый коммит с патчем отмены будет зафиксирован,в то время как оригинальный коммит останется в истории.

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Эта схема иллюстрирует,какая команда что делает.
Как вы можете видеть, reset && checkout модифицирует HEAD .

Enter image description here




Answer 2 amuliar


Do

git reset 23b6772

Чтобы убедиться,что ты на правильном месте:

git status

Вы увидите что-нибудь

На мастере ветки ваша ветка находится за 'origin/master' по 17 коммитам,и может быть быстро переадресована.

Затем перепишите историю на вашем пульте,чтобы отразить изменения:

git push --force-with-lease // a useful command @oktober mentions in comments



Answer 3 Kay V


Самое быстрое решение (всего 1 шаг)

Используйте git checkout -

Вы увидите Switched to branch <branch_name> . Подтвердите, что это ветка, которую вы хотите.


Краткое объяснение: эта команда вернет ГОЛОВУ обратно в последнюю позицию. См. Примечание о результатах в конце этого ответа.


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


Более методичное решение (2 шага,но запоминающееся)

Быстрый подход решает вопрос ОП.Но что,если ваша ситуация немного отличается:скажем,вы перезапустили Бэша,а потом обнаружили,что у вас отделился HEAD.В таком случае,вот 2 простых,легко запоминающихся шага.

1.Выберите нужную вам ветку

Используйте git branch -v

Вы видите список существующих местных отделений.Возьмите название филиала,соответствующее вашим потребностям.

2.Переместить HEAD к нему

Использовать git checkout <branch_name>

Вы увидите Switched to branch <branch_name> . Успех!


Outcomes

Используя любой из этих методов, вы можете продолжать добавлять и фиксировать свою работу, как и раньше: ваши следующие изменения будут отслеживаться в <branch_name> .

Обратите внимание, что как git checkout - ,так и git checkout <branch_name> будут давать дополнительные инструкции, если вы зафиксировали изменения, пока HEAD был отсоединен.




Answer 4 antak


Вопрос можно прочитать как:

Я был в отключенном состоянии с HEAD на 23b6772 и набрал git reset origin/master (потому что я хотел раздавить). Теперь я передумал, как мне вернуться к HEAD в 23b6772 ?

Прямой ответ: git reset 23b6772

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

Оказывается,есть!

git reset - (или в моем случае git cherry-pick - )

Который между прочим был таким же, как cd - чтобы вернуться в предыдущий текущий каталог в * nix! Итак, ура, я узнал две вещи одним камнем.




Answer 5 Deepak Kumar


Когда вы запустите команду git checkout commit_id , тогда HEAD отсоединится от 13ca5593d(say commit-id) и ветвь будет доступна дольше.

Вернуться в предыдущее местоположение запустите команду шаг мудро -

  1. git pull origin branch_name (скажем, мастер)
  2. git checkout branch_name
  3. git pull origin branch_name

Вы вернётесь к предыдущему местоположению с обновленным коммитом из удалённого репозитория.