Git: получить преимущества `git rebase --interactive` для выбора вишни
Я хотел бы иметь возможность сделать это:
git cherry-pick --interactive hash-0..hash-n-1 # fantasy command
и получить тот же рабочий процесс, что и интерактивная rebase: появляется буфер редактора, содержащий:
pick hash-0
pick hash-1
pick hash-2
...
pick hash-n-1
где я могу удалить любые нежелательные коммиты, squash
их вместе или edit
, чтобы сделать паузу между выборами, чтобы выполнить некоторую ручную фиксацию (например, commit --amend
) и все такое.
Обратите внимание на то, что pick
интерактивной перестановки таналогично похожа на cherry-pick
.
Теперь вышеуказанную операцию можно выполнить, выполнив сначала вишневый выбор, а затем интерактивную перестановку, что неудобно. То есть:
$ git tag old-head # mark starting point for later rebase
$ git cherry-pick hash-0..hash-n-1 # get everything first
$ git rebase --interactive old-head # okay now rebase "in-branch" to fix it up
Это не только неудобно из-за двух шагов, но и потому, что может потребовать разрешения конфликтов в коммитах, вы даже не хотите, чтобы они были отброшены на этапе переустановки.
Ответы
Ответ 1
Хорошо, понял хороший хак.
Запустите тривиальный rebase --interactive HEAD^
по одному фиксатору в текущей ветке. Вы получаете что-то вроде:
pick 1efd396b * Fixed a bug in frob function
Теперь просто вставьте дополнительные хэши, которые вы хотите выбрать:
pick 1efd396b * Fixed a bug in frob function
pick f01934db * Awesome feature added
pick 6fd109c1 * Refactored the widgets layer
squash 3900fd77 * Refactored the widgets layer s'more
Сохраните и выйдите, и wee: мульт rebase
любезно возьмет дополнительный крут, который вы загрузили на его спину, и включит его в текущую ветвь в соответствии с командами.
На самом деле вы можете сделать пустую перезагрузку с помощью:
git rebase --interactive HEAD
вы получаете буфер, содержащий
noop
Вам не нужно удалять это; просто добавьте свои выборы после этого.
Добавление: Чтобы создать списки выбора для этого метода, используйте git log --oneline --reverse from..to
, затем обрезайте требуемый вывод и добавьте команды переадресации в каждую строку: pick
, squash
,...
Ответ 2
Хорошо, следуя предложению Карла Норума, я просмотрел аргумент --onto
git rebase
.
Вариант использования может быть выполнен таким образом, что является улучшением, хотя все еще связано с несколько чрезмерным количеством шагов.
Основная проблема заключается в том, что rebase нуждается в текущей ветки для выбора, поэтому мы должны перенести наши координаты на временную ветвь, а затем обработать исходную ветвь ветки и удалить временную ветвь.
Поток выглядит следующим образом:
# We are originally on "mybranch"
# We create a temp-branch pointing to the last commit to be picked: hash-n-1
$ git checkout -b temp-branch hash-n-1 # create branch at last hash
# Then we rebase from the point before the first hash, onto our original branch
$ git rebase --interactive hash-0^ --onto mybranch
# The above rebase should make "temp-branch" into the very object that
# we want "mybranch" to be. If it looks that way, then all that is left is
# make it so:
$ git checkout mybranch
$ git reset --hard temp-branch
$ git branch -D temp-branch
git rebase --interactive hash-0^ --onto mybranch
использует фиксацию до hash-0
как "восходящий" для rebase, беря все коммиты из текущей ветки (на основе hash-n-1
), которые не находятся в восходящем потоке. Эти коммиты, конечно, hash-0
через hash-n-1
. Они переустанавливаются на головку mybranch
, но текущий temp-branch
, который reset --hard
отслеживает результат. Поэтому нам просто нужно назначить этот указатель на mybranch
и удалить temp-branch
.
Это довольно неуклюжий, но устраняет дублируемую вишневую подборку и легко восстанавливается в любое время только с помощью git reset --hard mybranch
.
(Может ли это быть улучшено.)
Ответ 3
Возможно, лучший ответ есть, но это может сработать для вас.
git cherry | awk '$0=$2' > cherry.txt
"$EDITOR" cherry.txt
git cherry-pick --stdin < cherry.txt
Пример