Як я можу перемістити HEAD назад до попереднього місця? (Відображена голова) & Скасувати зобов’язання


179

У Git я намагався виконати squash commitоб'єднання в іншу гілку, а потім перезавантаження HEADна попереднє місце за допомогою:

git reset origin/master

Але мені потрібно вийти з цього. Як я можу перемістити HEAD назад до попереднього місця?

У мене є фрагмент SHA-1 ( 23b6772) комісії, до якого мені потрібно перемістити його. Як я можу повернутися до цього зобов'язання?


12
HEAD - це лише вказівник на ваше поточне місцеположення (або точна редакція). git checkout 23b6772повинен робити.
Ярослав Адмін


1
@YaroslavAdmin Ні це не повинно . Перевірка комісії безпосередньо є причиною того, що сталося відокремлене стан HEAD (оскільки відділення дистанційного відстеження неможливо перевірити самостійно та автоматично відкласти на зобов’язання, на яке вони вказують, коли ви намагаєтесь зробити так, як це робило OP). Вибачте за некромантичний коментар :-) Я сподіваюся, що початкова проблема вже вирішена ...
RomainValeri

Відповіді:


398

Перш ніж відповісти, давайте додамо деяку інформацію, пояснивши, що це HEADтаке.

First of all what is HEAD?

HEADце просто посилання на поточний комітет (останній) у поточній галузі.
У HEADбудь-який момент може бути лише одиниця (за винятком git worktree).

Вміст HEADзберігається всередині, .git/HEADі він містить 40 байт SHA-1 поточної комісії.


detached HEAD

Якщо ви не перебуваєте на останньому комітеті - це означає, що HEADвказує на попереднє вчинення в історії, воно називається detached HEAD.

Введіть тут опис зображення

У командному рядку це буде виглядати приблизно так - SHA-1 замість назви гілки, оскільки значення 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та перевірка потрібного запису відмикання HEADповернеться до цього зобов’язання.

Кожен раз, коли зміниться HEAD, буде новий запис у reflog

git reflog
git checkout HEAD@{...}

Це поверне вас до бажаного завдання

Введіть тут опис зображення


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.

Введіть тут опис зображення


Якщо ви не є останньою комісією - це означає, що HEAD вказує на попереднє фіксацію в історії, її називають відокремленою HEAD, якщо цей попередній запис в історії не є підказкою іншої гілки. З мого досвіду, ви можете сказати, що ви відсторонені, якщо HEAD не вказує на зобов'язання, на яке також вказує будь-яка галузь. Це не стосується тегів.
Тім

Ви можете бути в відокремленій ГОЛОВІ і одночасно мати гілку з тим же посвідченням, що і ГОЛОВА цієї гілки. Я не розумію ваш коментар
CodeWizard

3
У мене проблеми з використанням розмітки вбудованого коду для заголовків :)
jub0bs

Не вдалося знайти кращого способу підкреслити це. не соромтеся редагувати. ви більше ніж ласкаво просимо
CodeWizard

22

Зробіть

git reset 23b6772

Щоб побачити, чи знаєте ви правильне положення:

git status

Ви щось побачите

На магістралі філії Ваша філія відстає від "початкового / початкового" на 17 коміттів, і її можна швидко переслати.

Потім перепишіть історію на пульт, щоб відобразити зміни:

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

1
Будь ВІДБУДУЮЩЕ з обережністю git push --force. У багатьох ситуаціях це зробить вас найменш популярною людиною в команді на деякий час ....
Kay V

щоб додати до вищевказаної примітки, я щойно натрапив на цю цитату на сайті about.gitlab.com/blog/2014/11/26/keeping-your-code-protected і повинен був додати її: "Один поштовх git push --force може легко зруйнувати день для багатьох людей: у сховищах [186 Дженкінса] їхні відділення філій перемотуються назад, щоб вказувати на більш старі комісії, і фактично нові комісії були замінені після поганого натиску ". - дуже непопулярний розробник ....
Kay V

2
@KayV погляньте git push --force-with-lease(стаття Thoughtbot : thinkbot.com/blog/git-push-force-with-lease )
жовтня

1
Корисний прапор, @oktober і хороша стаття. Дякуємо за те, що ви додали його сюди і пінг-мене про це.
Kay V

1
спасибі! це допомогло мені погано злитись. оскільки злиття не реагують так само, revertяк на коміти, я опинився в надзвичайно важкій ситуації. force-with-leaseдав мені впевненість переписати історію git гілки, не впливаючи на роботу інших людей. браво!
anon58192932

11

Найшвидше рішення (всього 1 крок)

Використовуйте git checkout -

Ви побачите Switched to branch <branch_name>. Підтвердіть, що це потрібна гілка.


Коротке пояснення: ця команда поверне HEAD назад до останнього положення. Дивіться примітку про результати наприкінці цієї відповіді.


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


Більш методичне рішення (2 кроки, але запам'ятовується)

Швидкий підхід вирішує питання ОП. Але що робити, якщо ваша ситуація трохи інша: скажіть, ви перезапустили Bash, а потім опинилися з від'єднаною HEAD. У цьому випадку ось два простих, легко запам'ятовуються кроки.

1. Виберіть потрібну гілку

Використовуйте git branch -v

Ви бачите список існуючих місцевих відділень. Візьміть назву філії, що відповідає вашим потребам.

2. Перемістіть ГОЛОВУ до неї

Використовуйте git checkout <branch_name>

Ви побачите Switched to branch <branch_name>. Успіху!


Результати

За допомогою будь-якого способу ви можете продовжувати додавати та виконувати свою роботу, як і раніше: ваші наступні зміни будуть відстежуватися <branch_name>.

Зверніть увагу, що обидва git checkout -і git checkout <branch_name>нададуть додаткові вказівки, якщо ви внесли зміни, поки HEAD був відключений.


Це не працює, тому що якщо я (припустимо, що 8acc968 HEAD ~ 2), git checkout 8acc968то git branch -vє MyBranchв списку нижче ... але потім git checkout MyBranchвидаляє мої коментарі.
amuliar

Привіт @amuliar - git checkout 8acc968перевірить комісію , а не відділення. Якщо MyBranchу вас є бажані зобов'язання, спробуйте git checkout MyBranch. Якщо він не містить змін у коміті 8acc968, вам потрібно буде об'єднати ці зміни після перевірки відділення.
Kay V

Дякую за відповідь! Я git checkoutпобачив попереднє зобов’язання і хотів повернутися до останнього. Але без останнього хеш-кома, я сильно загубився. Це рішення ідеально підходить для моєї ситуації!
zyy

4

Питання можна прочитати як:

Я був у відстороненому стані з HEADat 23b6772і набрав git reset origin/master(бо хотів зробити сквош). Тепер я передумав, як мені повернутися до свого HEADіснування 23b6772?

Відверта відповідь: git reset 23b6772

Але я потрапив у це питання, тому що мені нудно було вводити (копіювати та вставляти) хеші або його абревіатуру щоразу, коли я хотів посилатися на попередній, HEADі гуглив, щоб побачити, чи є якісь скорочення.

Виявляється, є!

git reset -(або в моєму випадку git cherry-pick -)

Що до речі було те саме, cd -що повернутися до попереднього поточного каталогу у * nix! Так ура, я навчився одним каменем дві речі.


0

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

Поверніться до попереднього місця, виконайте командний крок з розумом -

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

Ви повернетесь до попереднього місця з оновленою фіксацією з віддаленого сховища.


0

Сьогодні я помилково перевірив зобов’язання і почав працювати над ним, внісши деякі зобов’язання щодо окремого стану HEAD. Потім я натиснув на віддалену гілку за допомогою наступної команди:

git push origin HEAD: <My-remote-branch>

Тоді

git checkout <My-remote-branch>

Тоді

git pull

Нарешті я отримав усі свої зміни у своїй гілці, які я вніс окремо в голову.


0

Це може бути не технічним рішенням, але воно працює. (якщо хтось із ваших товаришів по команді має ту саму гілку в місцевій)

Припустимо, назва вашої гілки як гілка-ххх .

Кроки до вирішення:

  • Не оновлювати і не тягнути - нічого
  • Просто створіть нову гілку ( гілка-yyy ) з відділення-xxx на своїй машині
  • Ось і все, всі ваші існуючі зміни будуть у цій новій галузі ( гілка-yyy ). Ви можете продовжити свою роботу з цією галуззю.

Примітка. Знову ж таки, це не технічне рішення, але це допоможе точно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.