Як рухатись вперед і назад між творами в git?


105

Я роблю це, git bisectі після приходу до проблемного завдання я зараз намагаюся зробити крок вперед / назад, щоб переконатися, що я в правильному.

Я знаю, HEAD^як повернутися назад в історію, але чи є ще один ярлик для того, щоб перемогти мене вперед (до конкретного зобов'язання в майбутньому), як це:

A - B - C(HEAD) - D - E - F

Я знаю , що моя мета F , і я хочу , щоб перейти від C до D .


ПРИМІТКА. Це не дублікат Git: Як переміщатися вперед і назад між комітами , моє запитання дещо інше і на нього не відповідають.


1
stackoverflow.com/questions/2263674/… теж може допомогти.
VonC

git checkout -b new_branch HEAD~4повернутися назад 4 комітки від HEAD, як у stackoverflow.com/a/4940090/911945
Антон Тарасенко

Відповіді:


57

Я трохи експериментував, і, здається, це робиться трюк для навігації вперед ( редагувати : він працює добре лише тоді, коли у вас є лінійна історія без об'єднань):

git checkout $(git rev-list --topo-order HEAD..towards | tail -1)

де towardsSHA1 комітки або тегу.

Пояснення:

  • команда всередині $()означає: дістати всі коміти між поточним HEADі towardsфіксуватим (виключаючи HEAD), і сортувати їх у порядку пріоритетності (як, наприклад, git logза замовчуванням - замість хронологічного порядку, який дивно за замовчуванням rev-list), а потім взяти останній ( tail), тобто той, до якого ми хочемо піти.
  • це оцінюється в передплаті та передається git checkoutдля здійснення замовлення.

Ви можете визначити функцію, доступну як псевдонім, що очікує на параметр у вашому .profileфайлі, для переміщення вперед до конкретної комісії:

# Go forward in Git commit hierarchy, towards particular commit 
# Usage:
#  gofwd v1.2.7
# Does nothing when the parameter is not specified.
gofwd() {
  git checkout $(git rev-list --topo-order HEAD.."$*" | tail -1)
}

# Go back in Git commit hierarchy
# Usage: 
#  goback
alias goback='git checkout HEAD~'

2
Якщо рухатись вперед, це чудово працює на прямих частинах історії, але потрапляє в петлі, коли стикається злиття.
Костас

Так, я насправді не перевіряв його на злиттях. Я спробую заглянути у вільний час, але у мене мало стимулів тимчасово, оскільки ми домовилися мати суворо лінійну історію в нашому проекті;)
jakub.g

2
Чудова відповідь! Змінено для автоматичного визначення поточної гілки: stackoverflow.com/a/23172256/480608
Raine Revere

Це неправильно. git logпоказує комісії в хронологічному порядку, за замовчуванням такі ж, як rev-list, за винятком випадків, коли використовується --graphпрапор.
папіро

Досить переконливі докази того, що git занадто складний. Щось таке, що зазвичай таке просто, як Скасувати чи Повторити, тут ми маємо шалений список суперечливих відповідей. І я навіть не впадав у жодну із пов’язаних відповідей. FWIW, я спробував версію цього з простим лінійним набором комітів і, нарешті, просто відмовився.
Snowcrash

49

Все, що вам потрібно, щоб зрозуміти, не відокремлений стан голови - це скидання, а не оформлення замовлення.

git reset HEAD@{1}

5
або git reset "HEAD@{1}"в певних оболонках, таких як риба і панцир .. git reflogтакож може бути корисним, щоб знайти правильний заряд .
кухар Стів

1
Завжди використовуйте одиничні лапки в командах оболонки, якщо явно не хочете, щоб оболонка намагалася інтерпретувати / розширювати вміст. Це особливо важливо у таких випадках, коли мета - не допустити, щоб оболонка інтерпретувала спеціальні символи. Таким чином, вам не потрібно знати, чи містить рядок щось проблемне.
Кріс Пейдж

Я зробив це, щоб озирнутися назад у часі, потім я git reset HEADповернувся туди, де був… зараз я не маю уявлення, у якому стані знаходиться моє сховище, і все страшно. Що мені робити зараз?
theonlygusti

47

Я вірю, що ти можеш зробити:

git reset HEAD@{1}

Щоб вчасно зробити один поступ вперед. Щоб перейти до декількох команд вперед, використовуйте HEAD @ {2}, HEAD @ {3} тощо.


20

Це те, що я використовую для навігації вперед і назад.

перехід до наступного комітету

function n() {
    git log --reverse --pretty=%H master | grep -A 1 $(git rev-parse HEAD) | tail -n1 | xargs git checkout
}

перехід до попереднього комітету

function p() {
    git checkout HEAD^1
}

Дякую! Я зараз це використовую! Примітки для інших початківців, як я : повторно приєднайте HEAD, git checkout <current branch>додається до останньої версії. git checkout -b <new-branch-name>з поточної фіксації дозволяє змінити нову галузь. git rebase -iтакож працює. Крім того , я назвав свою n()функцію, nx()щоб уникнути конфлікту з менеджером версій вузла "n". Не забудьте перевірити псевдоніми!
Стівен Чой

function () {...} призначений для створення файлу сценаріїв bash для Unix / Linux, я родом з Windows, трохи важко для мене, щоб спершу зрозуміти
IcyBrk,

9

Скажімо, F - це остання фіксація trunk(вставте тут своє власне відділення) ... ви можете посилатися на це як trunk~0(або просто trunk), E як trunk~1, D як trunk~2і т.д.

Подивіться у свій рефлог, щоб дізнатися ще про способи називати коміти.


1
~ повертається назад, а не вперед, багажник ~ 2 - A
EmmanuelMess

Так. Ця відповідь передбачає, що у вас є гілка, що називається стовбур F, і що ви знаєте, куди в історії тієї гілки ви хочете переїхати. Це не намагання рухатись вперед відносно HEAD, але менш віддалене відносно тулуба.
Марно

@EmmanuelMess як trunk~2A?
theonlygusti

@theonlygusti Ви двічі повертаєтеся з HEAD.
EmmanuelMess

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

3

Повернення назад тривіально, оскільки ви рухаєтесь по дереву, і завжди є один шлях

  function git_down
        git checkout HEAD^
  end

Під час руху вперед ви рухаєтесь вгору по дереву, тому вам потрібно чітко вказати, на яку гілку ви націлюєте:

  function git_up 
        git log --reverse --pretty=%H $argv | grep -A 1 (git rev-parse HEAD) | tail -n1 | xargs git checkout
  end

Використання: git down,git up <branch-name>


Повернення назад також не зовсім унікальне, коли задіяні злиття. Хоча HEAD^це зазвичай розумний дефолт.
kdb

2

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

git log --reverse COMMIT_HASH..

Приклад

Список хешей історії журналів:

A
B
C -> put this
D

використовуючи команду git log --reverse C.., на виході ви побачите , B і A .


1

Можливо, це не найприємніший спосіб, але ви можете скористатися git logдля перегляду списку комітетів, а потім git checkout [sha1 of D]перейдіть до D.


6
Я не розумію, якщо він знаходиться в С, то журнал git показуватиме лише йому C, B і A.
Bilthon

Гаразд, зрозумів, але вам доведеться зробити хитрий git-log, як зазначено у посиланні, поданому VonC
Bilthon

1

Я щойно робив тест на це. скажімо, наприклад, ви знаходитесь у головній галузі. Потім виконайте:

git checkout HEAD@{3}

Тож голова відривається, і ви можете спробувати ще раз, щоб перейти до будь-якої іншої комісії:

git checkout HEAD@{4}

Після того, як ви закінчите оглядатися, ви зможете повернутися до свого початкового стану, просто переглянувши цю гілку. У моєму прикладі: майстер відділення

git checkout master

Якщо ви не хочете переходити до початкового стану, а хочете зберегти один із завдань як голову і продовжувати звідти, тоді вам потрібно буде відділитися звідти. наприклад, після "git checkout HEAD @ {4}", ви можете оформити

git checkout -b MyNewBranch

0

Як вирішення, ви можете просто повернутися до HEAD за допомогою

git checkout <branch>

А потім перейдіть до зобов’язання, яке ви хочете, з

git checkout HEAD~<offset>

0

Якщо ви використовуєте vs code, то історія Git - це приголомшливий плагін, де ви можете ефективно бачити коміти та перевіряти їхній вміст у самому редакторі. перевірити посилання


0
branchName=master; commitInOrder=1; git checkout $(git log --pretty=%H "${branchName}" | tac | head -n "${commitInOrder}" | tail -n 1)

де:

branchName дорівнює назві філії

commitInOrder дорівнює фіксації для того, щоб зробити це з першого першого комітету у вибраній гілці (так 1 - це найперший фіксатор, 2 - це другий фіксатор у гілці тощо)

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