Отмена git rebase

кто-нибудь знает, как легко отменить git rebase?

единственный способ, который приходит на ум, - это сделать это вручную:

  • git checkout фиксация родителя для обеих ветвей
  • затем создайте ветку temp оттуда
  • cherry-pick все коммиты вручную
  • замените ветку, в которой я перебазировался вручную созданной веткой

в моей текущей ситуации это сработает, потому что я могу легко spot commits из обеих ветвей (один был моим материалом, другой-материалом моего коллеги).

однако мой подход поражает меня как неоптимальный и подверженный ошибкам (скажем, я только что перезагрузился с 2 из моих собственных ветвей).

какие идеи?

уточнение: я говорю о ребазе, во время которого была воспроизведена куча коммитов. Не только один.

15 ответов


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

git reflog

и сбросить текущую ветку на нее (с обычными предостережениями о том, чтобы быть абсолютно уверенным перед сбросом с ).

предположим, что старый commit был HEAD@{5} в журнале Реф:

git reset --hard HEAD@{5}

в Windows, вы можете закавычить ссылка:

git reset --hard "HEAD@{5}"

вы можете проверить историю кандидата старого руководителя, просто сделав git log HEAD@{5} ( Windows: git log "HEAD@{5}").

если вы не отключили для каждой ветви reflogs, вы должны быть в состоянии просто сделать git reflog branchname@{1} как перебазировать отсоединяется руководитель отделения перед установкой к окончательной голове. Я бы дважды проверил это, хотя, поскольку я не проверял это в последнее время.

по умолчанию все reflogs активируются для не-голых репозитории:

[core]
    logAllRefUpdates = true

на самом деле, rebase сохраняет начальную точку в ORIG_HEAD так это обычно так:

git reset --hard ORIG_HEAD
на reset, rebase и merge все сохранить оригинал HEAD указатель на ORIG_HEAD Так что, если вы сделали любой из этих команд с перебазировать вы пытаетесь отменить то вам придется использовать reflog.

Чарльз работает, но вы можете сделать это:

git rebase --abort

убирать после reset.

в противном случае вы можете получить сообщение:"Interactive rebase already started".


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

предположим, у вас была ветка темы, образно называемая topic, что вы ответвившийся master когда верхушка master был 0deadbeef commit. В какой-то момент, находясь на topic ветку, сделал git rebase master. Теперь ты хочешь все исправить. Вот как:

git rebase --onto 0deadbeef master topic

это займет все коммиты на topic, не на master и воспроизвести их поверх 0deadbeef.

С --onto, вы можете изменить свою историю в значительной степени каких бы то ни было форме.

получать удовольствие. :-)


Я на самом деле поставил резервный тег на ветку, прежде чем делать какие-либо нетривиальные операции (большинство ребазов тривиальны, но я бы сделал это, если бы он выглядел сложным).

тогда восстановление так же просто, как git reset --hard BACKUP.


в случае вы подтолкнули свою ветку к удаленному репозиторию (обычно это origin), а затем вы сделали успешную ребазу (без слияния) (git rebase --abort дает "нет rebase в процессе") вы можете легко сброс филиала используя команда:

сброс git --hard origin / {branchName}

пример:

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.

nothing to commit, working directory clean

в случае, если вы не закончили перебазирование и в середине его, следующие работы:

git rebase --abort

Я удивлен, что никто не упомянул еще здесь. Rebase покидает старое состояние как ORIG_HEAD, Так что вы можете отменить последнее перемещение с помощью команды:

git reset --hard ORIG_HEAD

используя reflog не работает для меня.

то, что работало для меня, было похоже на описанное здесь. Откройте файл .git/logs / refs назван в честь ветви, которая была перезагружена, и найдите строку, содержащую "rebase finsihed", что-то вроде:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

проверка второй фиксации, указанной в строке.

git checkout 88552c8f

как только я убедился, что это содержит мои потерянные изменения, я разветвился и вздохнул с облегчением.

git log
git checkout -b lost_changes

для нескольких коммитов помните, что любая фиксация ссылается на всю историю, ведущую к этой фиксации. Поэтому в ответе Чарльза прочитайте " старый коммит "как"самый Новый из старых коммитов". Если вы сбросите эту фиксацию, то вся история, ведущая к этой фиксации, снова появится. Это должно сделать то, что ты хочешь.


следуя решению @Allan и @Zearin, я хотел бы просто сделать комментарий, но мне не хватает репутации, поэтому я использовал следующую команду:

вместо git rebase -i --abort (обратите внимание на ) Я должен был просто сделать git rebase --abort (без на ).

используя как -i и --abort в то же время вызывает Git, чтобы показать мне список использования/параметры.

Итак, мой предыдущий и текущий статус филиала с это решение:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

если вы успешно перезагрузились против удаленной ветви и не можете git rebase --abort вы все еще можете сделать некоторые уловки, чтобы сохранить свою работу и не заставили толкает. Предположим, ваша текущая ветвь, которая была перебазирована по ошибке, называется your-branch и отслеживая origin/your-branch

  • git branch -m your-branch-rebased # переименовать текущую ветку
  • git checkout origin/your-branch # проверка на последнее состояние, которое известно origin
  • git checkout -b your-branch
  • Регистрация git log your-branch-rebased для всех git log your-branch и определить коммиты, которые отсутствуют в your-branch
  • git cherry-pick COMMIT_HASH для каждого коммита в your-branch-rebased
  • толкать свои изменения. Обратите внимание, что две локальные ветви связаны с remote/your-branch и вы должны нажать только your-branch

предположим, я перебазирую master в свою ветку функций, и я получаю 30 новых коммитов, которые что-то ломают. Я обнаружил, что часто проще всего просто удалить плохие коммиты.

git rebase -i HEAD~31

Interactive rebase для последних 31 коммитов (это не больно, если вы выбираете слишком много).

просто возьмите коммиты, от которых вы хотите избавиться, и отметьте их "d" вместо "pick". Теперь коммиты удаляются эффективно отмена перебазировать (если удалить только коммиты вы просто когда перебазирования).


Если вы что-то испортите в git rebase, например git rebase --abort, в то время как у вас есть незафиксированные файлы, они будут потеряны и git reflog не поможет. Это случилось со мной, и вам нужно будет подумать вне коробки здесь. Если Вам повезет, как мне, и использовать IntelliJ Webstorm, то вы можете right-click->local history и может вернуться к предыдущему состоянию вашего файла / папок независимо от того, какие ошибки вы сделали с версиями программного обеспечения. Всегда хорошо иметь другой failsafe бег.


для отмены можно ввести следующую команду:

git -c core.quotepath=false rebase --abort