Как использовать 'git rebase -i' для восстановления всех изменений в ветке?

Вот пример:

>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. Любые идеи?

Ответ 1

Вы пробовали: git rebase -i master?

Ответ 2

Хорошо, я предполагаю, что ветвь называется "особенностью", и она была разветвлена ​​от "мастера".

Вот эта небольшая команда git, называемая merge-base. Он требует двух коммитов и дает вам первого общего предка обоих из них. Так что...

git merge-base feature master

... даст вам первый общий предок этих двух коммитов. Угадайте, что происходит, когда вы передаете эту фиксацию на git rebase -i, например...

git rebase -i `git merge-base feature master`

Интерактивная перестановка от первого общего предка как основной, так и функциональной ветки. Прибыль!;)

Ответ 3

Проблема со всеми предоставленными решениями заключается в том, что они не позволяют вам переустанавливать с самого первого коммита. Если первый хэш-код фиксации - XYZ, и вы делаете:

git rebase -i XYZ

Вы только перезагружаетесь, начиная со второго фиксации.

Если вы хотите переустановить первую транзакцию, выполните следующие действия:

git rebase -i --root

Ответ 4

Используйте 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`~

Ответ 5

Так как Git v1.7.10, вы можете просто запустить git rebase без аргумента, и он найдет точку fork и изменит ваши локальные изменения в ветке вверх по течению.

Вам нужно настроить ветвь вверх по течению, чтобы это работало (т.е. git pull без аргумента должно работать).

Подробнее см. в документах для git rebase:

Если не указано, восходящий поток настроен в branch.remote и branch..merge будут использоваться (см. git -config [1] для получения подробной информации), и предполагается опция --fork-point. Если вы в настоящее время не находитесь в какой-либо отрасли или если текущая ветка не иметь настроенный вверх по течению, rebase прервется.

Ответ 6

Проблема с переустановкой из другой ветки

Проблема с 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, чтобы определить самую последнюю совместную фиксацию между этой веткой и текущей ветвью.

Ответ 7

Общее решение (если вы не знаете имя ветки вверху):

git rebase -i @{upstream}

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

git rebase -i `git merge-base --all HEAD @{upstream}`

но это немного глоток.

Ответ 8

git rebase -i --onto @{u}... @{u}

Интерактивная перебазировка, начиная с единственной точки слияния HEAD и ее восходящего потока, включая все коммиты в HEAD, которые не находятся в своем восходящем потоке.

Другими словами, именно то, что вы хотите.