Перевірка старого коміту та підтримка голови на головній гілці?


85

В даний час для переключення на інший коміт git (на тій самій гілці ... власне, на головній гілці!), Я виконую команду

git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

Тепер, кожен раз, коли я роблю цю гіт, мені каже, що я зараз з відірваною головою. Як мені перейти до старішого коміту і при цьому зберегти голову на тій самій гілці?


1
Після того, як ви виконаєте цю команду, ваш HEAD ref зміниться на це коміт. Немає сенсу хотіти, щоб ГОЛОВА також вказувала кудись ще.
Greg Hewgill

З того, що я зрозумів із повідомлення git, воно нікуди не вказує , що є небажаним.
пожирав елізіум

1
З'явиться повідомлення Git показує , коли ви закінчували специфічно зробити так говорить : «Голова тепер в ea3d5ed ...», який говорить вам , що голова буде вказувати куди - то. Це просто вказівник кудись, що не має жодної іншої назви, крім HEAD (на даний момент, оскільки a git checkoutдо іншого коміту або імені гілки перемістить HEAD до цього нового місця).
Greg Hewgill

Чи наведені відповіді адекватно пояснюють це, чи є щось, з чим ми могли б бути більш зрозумілими? Я був би радий пояснити вам свою відповідь, якщо вона не відповідає на ваше запитання.
Брайан Кемпбелл,

Якщо ви прийшли сюди, шукаючи спосіб перевірити ще один коміт, зберігаючи HEAD повністю незмінним (наприклад, для повернення до попереднього коміту): git revert --no-commit 0766c053..HEADзробить це, де 0766c053є коміт, який ви хочете перевірити. Це зі stackoverflow.com/a/21718540/525872 .
Джо Лісс

Відповіді:


193

Більшу частину часу, коли я роблю це, я оформлюю оплату до тимчасової гілки:

git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

Потім після закінчення я просто видаляю гілку


80

Це залежить від того, що ви хочете зробити під час оформлення замовлення. Якщо все, що ви робите, - це перевірити його, щоб ви могли створити або протестувати цю редакцію, то в роботі з відірваною головою немає нічого поганого. Просто пам’ятайте перевірити фактичну гілку перед тим, як робити будь-які коміти ( git checkout masterнаприклад), щоб не створювати комітів, які не входять до жодної гілки.

Однак, якщо ви хочете зробити більше комітів, починаючи з цього моменту, вам слід створити гілку. Якщо ви робите коміти, на які не посилається гілка, вони можуть легко загубитися і в кінцевому підсумку будуть очищені збирачем сміття git, оскільки до них нічого не відноситься. Ви можете створити нову гілку, запустивши:

git checkout -b newbranch ea3d5ed

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

Почнемо з 3 комітів master, A, B і C. masterє поточною гілкою, тому HEADвказує наmaster , що вказує на комітування C.

ABC
* - * - * <- майстер <- ГОЛОВА

Тепер, якщо ми здійснимо фіксацію, git створить коміт, у якому батьківським є C (оскільки це поточний коміт, на який вказується HEADчерез via master), і оновиться, masterщоб вказати на цей новий коміт. Усі наші коміти зараз увійшли masterта HEADвказують на новий коміт master.

А Б В Г
* - * - * - * <- майстер <- ГОЛОВА

А тепер давайте перевіримо В, даючи нам відокремлений HEAD.

А Б В Г
* - * - * - * <- майстер
   ^
    \-- ГОЛОВА

Тут все працює чудово; ми можемо переглянути всі файли, створити нашу програму, протестувати її тощо. Ми навіть можемо створювати нові коміти; але якщо ми так зробимо, немає жодної гілки, на якій ми перебуваємо, тому ми не можемо вказувати жодної гілки на цей новий коміт. Єдине, на що вказує HEAD:

А Б В Г
* - * - * - * <- майстер
    \
     * <- ГОЛОВА
     Е

Якщо пізніше ми вирішимо перевірити ще masterраз, нічого, що стосується E.

А Б В Г
* - * - * - * <- майстер <- ГОЛОВА
    \
     *
     Е

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

Отже, замість того, щоб перевіряти оголену версію та отримувати відірвану голову, якщо ви відчуваєте, що збираєтеся робити більше комітів, вам слід використати git checkout -b branch Bдля створення гілки та перевірки її. Тепер ваші коміти не будуть втрачені, оскільки вони будуть включені до гілки, до якої ви можете легко звернутися та об'єднати пізніше.

А Б В Г
* - * - * - * <- майстер
   ^
    \ - гілка <- ГОЛОВА

Якщо ви забудете це зробити і створите коміти з гілки, не потрібно турбуватися. Ви можете створити гілку з посиланням на версію головки за допомогою git checkout -b branch. Якщо ви вже повернулися до masterгілки і зрозуміли, що забули помилковий коміт, ви можете знайти його за допомогою git reflog, який покаже вам історію того, на що HEADвказували коміти за останні кілька днів. Все, що все ще є у перегляді, не буде зібраним сміттям, і, як правило, посилання зберігаються в перегляді принаймні 30 днів.


Мені не зовсім зрозуміло, чому при оформленні старого коміту голова від'єднується . Можливо, проблема в тому, що означає відірвана голова? З іншого боку, якщо перевірка старого коміту з від’єднаною головою призведе лише до його втрати, чому б хтось це робив? Просто щоб возитися і пробувати щось? Чому спочатку git це дозволяє?
пожирав елізіум

5
"Від'єднана голова" @devoured elysium означає, що у вас є HEADпосилання, яке вказує безпосередньо на SHA-1 коміту, а не на гілку, яка в свою чергу вказує на коміт. Оскільки ваша голова не посилається на гілку, Git не знає, яку гілку оновлювати, коли ви додаєте нові коміти. Як я пояснив на початку моєї відповіді, цілком добре мати відокремлену голову, якщо ви повертаєтесь до старої версії лише для побудови або тестування коду; Ви завжди можете повернутися до гілки git checkout masterабо тому подібного. Проблема лише в тому, що ви вчиняєте, коли у вас відірвана голова.
Брайан Кемпбелл,

@BrianCampbell - Після здійснення комітів на гілці (де зараз знаходиться ваша голова), ви об'єднуєте гілку в B та B в master. Що робити далі?
amey1908

Ваше пояснення зробило для мене купу інших речей. Дякую. Я міг би нарешті зрозуміти git ...
Джо

8

Якщо ви просто хочете повернутися до попереднього коміту, щоб пограти з ним, не вносячи жодних змін, ви можете це зробити

git co <previous-commit-id>

Ви опинитеся у гілці під назвою "(без гілки)" після цієї команди.

Підтвердьте це

git br

Після того, як ви пограєте з цим раніше зафіксованим кодом, ви можете перейти до гілки, в якій ви були

git co <the-branch-you-were-on>

"(Без гілки)" буде видалено автоматично. Таким чином вам не потрібно створювати тимчасову гілку.


5

HEAD Git - це просто вказівник, який говорить про те, що знаходиться в робочому каталозі. Якщо ви хочете перевірити коміт, який не є головою гілки, вам просто потрібно перенаправити HEAD, щоб вказати на цей коміт. Тут ніяк не обійти. Ви можете створити тимчасову гілку під час цього коміту, але HEAD все одно буде спрямовано від майстра.

Це коротке пояснення. Можливо, наведена нижче детальна інформація допоможе зрозуміти, чим відрізняються HEAD та master:

Зазвичай все виглядає так:

C ← refs/heads/master ← HEAD 
↓
B
↓
A

Що означає: «Батьком C є B, а батьком B є A. Головний гілка вказує на C, і я зараз перевірив вміст master. Крім того, коли я здійснюю комісію, майстер буде оновлений. "

Тут передбачаються деякі припущення, які необхідні для глибокого розуміння графіка коміту. А саме, коміти стосуються лише своїх батьків, а вміст гілки - це ті коміти (і лише ті коміти), до яких можна дійти, перейшовши за батьківськими посиланнями. (Немодифікований) вміст робочого дерева та індекс повинен відповідати коміту, названому HEAD, або опосередковано (“символічно”), або безпосередньо (“від’єднано”).

Таким чином, якщо ви хочете перевірити старий коміт, HEAD потрібно оновити, щоб вказати на бажаний коміт. git-checkoutробить саме це:

C ← refs/heads/master 
↓
B ← HEAD
↓
A

Тепер ви залишили свою гілку за собою, оскільки дивитесь на щось старе. Це цілком нормально, оскільки рада «відірваної голови» спокійно говорить вам (наголошу на моєму):

Ви можете озирнутися, зробити експериментальні зміни та здійснити їх, а також можете відкинути будь- які зроблені вами зобов’язання, зроблені в цьому стані, не впливаючи на будь-які гілки , виконавши чергову перевірку.

З іншого боку, при перезавантаженні вашої гілки ви також отримуєте HEAD там, де потрібно, це мало б зовсім інший ефект!

C
↓
B ← refs/heads/master ← HEAD
↓
A

Фіксація C стане сміттям, оскільки ви заявили, що більше не хочете, щоб вона була частиною головної гілки.

Коротше кажучи, все, що вам потрібно зробити, це зрозуміти, що означає git під «ГОЛОВОЮ» - це де ви знаходитесь, а не там, де є якась гілка. І якщо ви знаходитесь не так, як там, де є гілка, немає іншого вибору, як використовувати відокремлену ГОЛОВУ.

(Можливо, також перегляньте GitHub, gitk або gitweb, щоб переглянути історію комітів, якщо збиття з вашої HEAD продовжує вас дратувати.)


1

Питання трохи розпливчасте, але якщо ви хочете просто змінити файли у вашому робочому дереві, ви можете просто зробити це:

git checkout [commit|branch] -- .

Потім ви можете поетапно внести зміни та створити новий коміт, якщо хочете. Іноді це досить корисно.


0

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

Крок 1: Створіть тег старого коміту, до якого ви хочете повернутися.

як тег v2.0

Крок 2: Git Checkout v2.0

ось воно, зараз ваша HEAD вказує на коміт 'v2.0', але майстер все ще вказує на останній коміт.

C:\Program Files\Git\doc\git\html\git-checkout.html цей документ може вам допомогти

або введіть git help <checkout>

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