Ответ 1
Вы пробовали: git rebase -i master
?
Вот пример:
>git status
# On branch master
nothing to commit (working directory clean)
>git checkout -b test-branch
>vi test.c
>git add test.c
>git commit -m "modified test.c"
>vi README
>git add README
>git commit -m "modified README"
Теперь я хочу сделать "git rebase -i
", что позволит мне переустановить все коммиты для этой ветки. Есть что-то вроде "git rebase -i HEAD~MASTER
" или аналогичного. Я полагаю, что могу сделать "git rebase -i HEAD~2
", но я действительно не хочу подсчитывать, сколько было сделано. Я также мог бы сделать "git rebase -i sha1
", но я не хочу расчесывать журнал git, чтобы найти первый commit sha1. Любые идеи?
Вы пробовали: git rebase -i master
?
Хорошо, я предполагаю, что ветвь называется "особенностью", и она была разветвлена от "мастера".
Вот эта небольшая команда git, называемая merge-base. Он требует двух коммитов и дает вам первого общего предка обоих из них. Так что...
git merge-base feature master
... даст вам первый общий предок этих двух коммитов. Угадайте, что происходит, когда вы передаете эту фиксацию на git rebase -i, например...
git rebase -i `git merge-base feature master`
Интерактивная перестановка от первого общего предка как основной, так и функциональной ветки. Прибыль!;)
Проблема со всеми предоставленными решениями заключается в том, что они не позволяют вам переустанавливать с самого первого коммита. Если первый хэш-код фиксации - XYZ, и вы делаете:
git rebase -i XYZ
Вы только перезагружаетесь, начиная со второго фиксации.
Если вы хотите переустановить первую транзакцию, выполните следующие действия:
git rebase -i --root
Используйте gitk (* nix) или gitx (OS X) или аналогичные на других платформах, и посмотрите, какой коммит был корнем вашего ветки. Затем запустите:
git rebase -i <the SHA hash of the root commit>
Например, у меня есть репозиторий, который я проверил с помощью gitx:
gitx screencap http://img.skitch.com/20081213-mq7qpp5nhceksdhfx14rerjgyx.jpg
Теперь, когда я знаю корневой хеш, я могу запустить это:
git rebase -i 38965ed29d89a4136e47b688ca10b522b6bc335f
И мой редактор всплывает с этим, и я могу изменить/сквош/как угодно.
pick 50b2cff File 1 changes.
pick 345df08 File 2 changes.
pick 9894931 File 3 changes.
pick 9a62b92 File 4 changes.
pick 640b1f8 File 5 changes.
pick 1c437f7 File 6 changes.
pick b014597 File 7 changes.
pick b1f52bc File 8 changes.
pick 40ae0fc File 9 changes.
# Rebase 38965ed..40ae0fc onto 38965ed
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Я уверен, что есть какой-то волшебный способ убедить git правильно определить корень дерева, но я не знаю, что это такое.
EDIT: Эта магия такова:
git log master..other_feature | cat
Что покажет вам все коммиты на этой ветке, а piping to cat отключит пейджер, чтобы вы сразу увидели первую фиксацию.
EDIT: объединение приведенного выше дает полностью автоматическое решение:
git rebase -i `git log master..other_feature --pretty=format:"%h" | tail -n 1`~
Так как Git v1.7.10, вы можете просто запустить git rebase
без аргумента, и он найдет точку fork и изменит ваши локальные изменения в ветке вверх по течению.
Вам нужно настроить ветвь вверх по течению, чтобы это работало (т.е. git pull
без аргумента должно работать).
Подробнее см. в документах для git rebase:
Если не указано, восходящий поток настроен в branch.remote и branch..merge будут использоваться (см. git -config [1] для получения подробной информации), и предполагается опция --fork-point. Если вы в настоящее время не находитесь в какой-либо отрасли или если текущая ветка не иметь настроенный вверх по течению, rebase прервется.
Проблема с переустановкой из другой ветки
Проблема с git rebase -i master
заключается в том, что у вас могут быть конфликты слияния, с которыми вы не всегда хотите иметь дело в данный момент, или вы можете исправить конфликт в одном коммите, только чтобы исправить его еще раз в другом коммите во время курс ребазы.
Проблема с переустановкой из известной фиксации
Вся проблема здесь в том, что вы должны знать, к какой фиксации вы должны обратиться, либо ее SHA, либо HEAD ~ x и т.д. Это лишь незначительная досада, но это раздражение.
Лучший способ
Если вы хотите переустановить все коммиты в своей текущей ветке, так как последняя фиксация, которую он разделяет с родительской ветвью, вы можете добавить следующий псевдоним в .gitconfig:
rbi = !sh -c \"git rebase -i `git merge-base $1 HEAD`\" -
Использование
git rbi parentBranch
Как это работает
Этот псевдоним - это всего лишь оболочка script, которая использует аргумент, который относится к родительской ветке. Этот аргумент передается в git merge-base
, чтобы определить самую последнюю совместную фиксацию между этой веткой и текущей ветвью.
Общее решение (если вы не знаете имя ветки вверху):
git rebase -i @{upstream}
Обратите внимание, что если ваш восходящий поток (возможно, ветвь отслеживания) обновлен с момента последнего переустановки, вы получите новые коммиты от восходящего потока. Если вы не хотите использовать новые коммиты, используйте
git rebase -i `git merge-base --all HEAD @{upstream}`
но это немного глоток.
git rebase -i --onto @{u}... @{u}
Интерактивная перебазировка, начиная с единственной точки слияния HEAD и ее восходящего потока, включая все коммиты в HEAD, которые не находятся в своем восходящем потоке.
Другими словами, именно то, что вы хотите.