Загалом, git resetфункція полягає в тому, щоб взяти поточну гілку і скинути її на точку десь в іншому місці, і, можливо, принести індекс і дерево роботи. Більш конкретно, якщо ваша головна галузь (наразі перевірена) така:
- A - B - C (HEAD, master)
і ви розумієте, що хочете, щоб майстер вказував на B, а не на C, ви будете використовувати його git reset Bдля переміщення туди:
- A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore
Відступ: Це відрізняється від каси. Якщо ви біжите git checkout B, ви отримаєте це:
- A - B (HEAD) - C (master)
Ви опинилися в відокремленому стані HEAD. HEAD, дерево роботи, індексувати всі збіги B, але головна гілка залишилася в C. Якщо ви зробите нове зобов'язання Dв цей момент, ви отримаєте це, що, мабуть, не те, що ви хочете:
- A - B - C (master)
\
D (HEAD)
Пам’ятайте, що скидання не робить зобов’язань, воно лише оновлює гілку (яка є вказівником на комісію), щоб вказувати на іншу комісію. Решта - лише деталі того, що відбувається з вашим індексом та робочим деревом.
Використовуйте випадки
Я висвітлюю багато основних випадків використання в git resetмежах своїх описів різних варіантів у наступному розділі. Його справді можна використовувати для найрізноманітніших речей; загальний потік полягає в тому, що всі вони передбачають скидання гілки, індексу та / або робочого дерева, щоб вказувати / відповідати заданій комісії.
Речі, на які слід бути обережними
--hardможе призвести до того, що ви дійсно втратите роботу. Це змінює ваше робоче дерево.
git reset [options] commitможе призвести до (втрати) зобов'язань. У наведеному вище прикладі іграшки ми втратили прихильність C. Він все ще знаходиться в репо, і ви можете знайти його, переглянувши git reflog show HEADабо git reflog show master, але він фактично недоступний з жодної гілки.
Git назавжди видаляє такі зобов’язання через 30 днів, але до цього часу ви можете відновити C, знову вказуючи гілку на нього ( git checkout C; git branch <new branch name>).
Аргументи
Перефразовуючи сторінку чоловіка, найчастіше вживається форма git reset [<commit>] [paths...], яка скине задані шляхи до їх стану від даної фіксації. Якщо шляхи не надані, все дерево скидається, а якщо фіксація не передбачена, вважається, що це HEAD (поточне виконання). Це поширений зразок для команд git (наприклад, checkout, diff, log, хоча точна семантика відрізняється), тому це не повинно бути занадто дивним.
Наприклад, git reset other-branch path/to/fooскидає все в шляху / до / foo до свого стану в іншій галузі, git reset -- .скидає поточний каталог на його стан у HEAD, а простий git resetскидає все на його стан у HEAD.
Основні варіанти роботи дерева та параметри індексу
Існує чотири основні варіанти контролю того, що відбувається з вашим робочим деревом та індексом під час скидання.
Пам'ятайте, що індекс - це "інсценізація області" git - це те, куди йдуть справи, коли ви говорите, git addготуючись до вчинення.
--hardзмушує все відповідати виконанню, яку ви скинули. Це найлегше зрозуміти, напевно. Усі ваші локальні зміни стають обмеженими. Одним із основних напрямків роботи є знеструмлення вашої роботи, але не перемикання зобов'язань: git reset --hardозначає git reset --hard HEAD, тобто не змінюйте гілку, а позбавляйтеся від усіх локальних змін. Інший - просто переміщення гілки з одного місця в інше та синхронізація дерева індексу / роботи. Це той, який може насправді змусити вас втратити роботу, оскільки він модифікує ваше робоче дерево. Будьте дуже впевнені, що хочете відкинути місцеву роботу, перш ніж запустити будь-яку reset --hard.
--mixedє типовим, тобто git resetзасобом git reset --mixed. Він скидає індекс, але не дерево роботи. Це означає, що всі ваші файли є неушкодженими, але будь-які відмінності між оригінальним фіксуванням та тим, до якого ви скинули, відображатимуться як локальні модифікації (або не відстежені файли) зі статусом git. Використовуйте це, коли зрозумієте, що зробили якісь погані зобов’язання, але хочете зберегти всю роботу, яку ви зробили, щоб ви могли її виправити та повторно. Для здійснення зобов’язань вам доведеться знову додати файли до індексу ( git add ...).
--softне торкається індексу чи робочого дерева. Усі ваші файли є недоторканими, як і раніше --mixed, але всі зміни відображаються як changes to be committedзі статусом git (тобто зареєстровано під час підготовки до вчинення). Використовуйте це, коли зрозумієте, що зробили якісь погані вчинки, але робота - все добре - все, що вам потрібно зробити, - це повторити її по-іншому. Індекс недоторканий, тому ви можете скористатись негайно, якщо захочете - отримана комісія матиме той самий вміст, що і там, де ви були до скидання.
--mergeдодано нещодавно і призначено допомогти вам перервати невдале злиття. Це необхідно, тому що git mergeнасправді ви зможете спробувати злити з брудним робочим деревом (одне з локальними модифікаціями) до тих пір, поки ці модифікації будуть у файлах, на які не впливає злиття. git reset --mergeскидає індекс (як-от --mixed- всі зміни відображаються як локальні модифікації) та скидає файли, на які впливає злиття, а інші залишає в спокої. Це, сподіваємось, відновить усе, як було до поганого злиття. Зазвичай ви будете використовувати його як git reset --merge(означає git reset --merge HEAD), оскільки ви хочете скинути злиття, а не перемістити гілку. ( HEADще не оновлено, оскільки злиття не вдалося)
Якщо бути конкретнішим, припустимо, що ви змінили файли A і B, і ви намагаєтеся об'єднатись у гілку, яка модифікувала файли C і D. Злиття чомусь не вдається, і ви вирішили перервати це. Ви використовуєте git reset --merge. Це повертає C і D до того, як вони були HEAD, але залишає ваші модифікації A і B у спокої, оскільки вони не були частиною спроби злиття.
Хочете дізнатися більше?
Я думаю, що man git resetце дуже добре для цього - можливо, вам потрібно трохи почуття того, як git працює для них, щоб дійсно зануритися в хоч. Зокрема, якщо ви знайдете час, щоб уважно їх прочитати, дуже корисні ці таблиці з деталізацією станів файлів в індексі та робочому дереві для всіх різних варіантів та випадків. (Але так, вони дуже щільні - вони дуже стисло передають дуже багато вищевказаної інформації.)
Дивні позначення
"Дивне позначення" ( HEAD^і HEAD~1), яке ви згадуєте, - це просто скорочення для вказівки комітетів, без використання хеш-імені типу 3ebe3f6. Це повністю задокументовано в розділі "уточнення змін" сторінки man для git-rev-розбору з великою кількістю прикладів та відповідних синтаксисів. Карета і тильда насправді означають різні речі :
HEAD~є скороченим HEAD~1і означає першого батька вчинення. HEAD~2означає перший з батьків перших батьків. Подумайте про те HEAD~n, що "п позначається перед ГОЛОВОЮ" або "родоначальником п’ятого покоління ГОЛА".
HEAD^(або HEAD^1) також означає перший з батьків. HEAD^2означає другий з батьків. Пам'ятайте, що у звичайній комісії злиття є два батьки - перший з батьків є об'єднаним в коміт, а другий з батьків - це об'єднання, яке було об'єднано. Взагалі злиття насправді можуть мати довільно багато батьків (злиття восьминога).
- Ці
^та ~оператори можуть бути нанизані, як і в HEAD~3^2, другий батько третього покоління предка HEAD, HEAD^^2другий батько першого батька HEAD, або навіть HEAD^^^, що еквівалентно HEAD~3.
