Вопрос

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

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

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

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

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

Есть идеи?

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

Это было полезно?

Решение

Самый простой способ — найти главный коммит ветки, который был непосредственно перед началом перебазирования в файле перерегистрировать...

git reflog

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

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

git reset --hard HEAD@{5}

В Windows вам может потребоваться процитировать ссылку:

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

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

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

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

[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”.

git reflog покажет вам все изменения до и после перебазирования и позволит вам найти правильный вариант для сброса.Но я удивлен, что никто еще не упомянул здесь еще один очень простой способ:

Rebase оставляет старое состояние как ORIG_HEAD, поэтому вы можете отменить последнюю перезагрузку, выполнив:

git reset --hard ORIG_HEAD

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

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

git rebase --onto 0deadbeef master topic

Это возьмет на себя все коммиты topic этого нет master и воспроизвести их поверх 0deadbeef.

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

Веселиться.:-)

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

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

В случае вы отправили свою ветку в удаленный репозиторий (обычно это источник), а затем вы выполнили успешное перебазирование (без слияния) (git rebase --abort выдает «Перебазирование не выполняется»), вы можете легко сбросить ветку Использование команды:

git reset --hard origin/{имя ветки}

Пример:

$ ~/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

С использованием 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 # проверка до последнего состояния, происхождение которого известно
  • 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

Интерактивное перебазирование для последнего 31 коммита (не повредит, если вы выберете слишком много).

Просто возьмите коммиты, от которых вы хотите избавиться, и отметьте их буквой «d» вместо «pick».Теперь коммиты удаляются, что фактически отменяет перебазирование (если вы удаляете только те коммиты, которые вы только что получили при перебазировании).

Если вы находитесь в ветке, вы можете использовать:

git reset --hard @{1}

Существует не только справочный журнал для HEAD (полученный git reflog), для каждой ветки также есть релоги (полученные git reflog <branch>).Итак, если вы находитесь на master затем git reflog master перечислит все изменения в этой ветке.Вы можете обратиться к этим изменениям, master@{1}, master@{2}, и т. д.

git rebase обычно меняет HEAD несколько раз, но текущая ветка будет обновлена ​​только один раз.

@{1} это просто ярлык для текущей ветки, поэтому оно равно master@{1} если ты включен master.

git reset --hard ORIG_HEAD не будет работать, если вы использовали git reset во время интерактивного rebase.

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

git reflog

Найдите коммит непосредственно перед тем, как вы начали перебазирование.Возможно, вам придется прокрутить страницу вниз, чтобы найти его (нажмите Enter или PageDown).Обратите внимание на номер HEAD и замените 57:

git checkout HEAD@{57}

Просмотрите ветку/коммит, если она выглядит хорошо, создайте новую ветку, используя этот HEAD:

git checkout -b new_branch_name

git reset --hard origin/{имя ветки}

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

Обычно я делаю следующее:git reset #commit_hash

до последнего коммита, где, я думаю, перебазирование не имело никакого эффекта.

затем git pull

Теперь ваша ветка должна совпадать с основной, и в ней не должно быть перебазированных коммитов.

Теперь можно просто выбрать коммиты в этой ветке.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top