полностью написанным образом. В идеале, если своп не удался, он должен либо позволить мне исправить его в интерактивном режиме, либо просто сдаться и сказать мне сделать это вручную.
Ответ 2
Поскольку вы хотите делать это часто, я предполагаю, что вы захотите перейти к одноэтапному процессу. Я сделаю это немного учебным, хотя и сломаю его.
ВАЖНО
Не делайте такого рода вещи на любых коммитах, которые уже были переданы другому разработчику, или нажаты на удаленный. Переписывание общей истории - это рецепт катастрофы.
Отказ публичной службы в стороне...
Шаг 1
A---B---C---D (master, HEAD, ORIG_HEAD)
git rebase --quiet --onto HEAD~2 HEAD~1 HEAD
Это занимает то, что находится в HEAD, которое не находится в HEAD ~ 1, и применяет его к HEAD ~ 2. После выполнения этой rebase у вас будет эта история. Имейте в виду, что git-rebase --onto
превратит вас в безголовое состояние. (У меня там --quiet
, так что последняя команда не плюет на экран текст на стене).
A---B---C---D (master, ORIG_HEAD)
\
D' (HEAD)
Теперь нам нужно получить C
, примененный после D'
, для этого мы можем использовать git-cherry-pick
. Когда выполняется git-rebase --onto
, как было указано выше, исходная история фиксации перед сохранением сохраняется в ORIG_HEAD
, потому что git не изменит ее, пока вы не выполните какое-либо другое действие. Это полезно, если вы испортите rebase, но мы будем использовать его здесь для вишневого выбора.
Шаг 2
git cherry-pick ORIG_HEAD~1
A---B---C---D (master, ORIG_HEAD)
\
D'---C' (HEAD)
Состояние HEAD теперь точно так, как вы хотели, всего двумя командами. Я предполагаю, что это обычно происходит изнутри ветки и что вы захотите обновить эту ветвь с новым порядком фиксаций. Если я ошибаюсь в этом, то это и ваше дело. Если вы хотите обновить ветку, в которой вы были, есть несколько способов сделать это.
Простейшим способом сделать вручную будет следующее:
git log -1 ###copy the the SHA1
git checkout master
git reset --hard <SHA1>
Однако все дело в автоматизации, и есть способы сделать это менее очевидным, но требуют меньше команд.
Шаг 3
git update-ref refs/heads/master $(git rev-parse HEAD)
Используя git-rev-parse
, я получаю только фиксацию HEAD и ничего больше. Применяя это к git -update-ref, я могу "reset" мастер-ветку, не проверяя ее сначала. Теперь, когда мастер установлен правильно, я могу идти вперед и мастер проверки (точка обновления-ref заключается в уменьшении количества шагов для возможного псевдонима /bash script).
Шаг 4
git checkout --quiet master
Снова, я передаю --quiet
, чтобы уменьшить количество текста, сбрасываемого на экране после каждой команды.
Bash Script
Если вы хотите сделать это как bash script, вы можете еще больше автоматизировать весь процесс и заставить его работать динамически на любой ветки, которую вы хотите, а не только на мастере.
#!/bin/bash
branch=$(git name-rev --name-only HEAD)
git rebase --onto HEAD~2 HEAD~1 HEAD
git cherry-pick ORIG_HEAD~1
git update-ref refs/heads/$branch $(git rev-parse HEAD)
git checkout --quiet $branch
Git Псевдоним
Тем не менее, это так же легко сбрасывается в псевдоним git, не создавая фактически файл для bash script. Создание файла и настройка псевдонима не являются какими-либо средствами, но это еще одна вещь, которую нужно понять, и многие люди этого не делают. Здесь простой псевдоним git, выполните эту команду один раз..
git config --global alias.flip-last "!branch=$(git name-rev --name-only HEAD); git rebase --quiet --onto HEAD~2 HEAD~1 HEAD; git cherry-pick ORIG_HEAD~1; git update-ref refs/heads/$branch $(git rev-parse HEAD); git checkout --quiet $branch"
Теперь в любое время, когда вы хотите перевернуть свои последние две коммиты, просто используйте...
git flip-last
GitHub Gist
Это был интересный маленький script, чтобы написать, я бросил его на github gist. Не стесняйтесь разветвлять его, вносить изменения, ставить его, что угодно.
https://gist.github.com/eddiemoya/5456992