Как мне использовать 'git rebase -i', чтобы отменить все изменения в ветке? - PullRequest
53 голосов
/ 12 декабря 2008

Вот пример:

>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, чтобы найти первый коммит sha1. Есть идеи?

Ответы [ 8 ]

61 голосов
/ 17 ноября 2010

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

Эта маленькая команда git называется merge-base. Он берет два коммита и дает вам первого общего предка обоих. Итак ...

git merge-base feature master

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

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

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

52 голосов
/ 29 мая 2015

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

git rebase -i XYZ

Вы делаете ребаз только начиная со 2-го коммита.

Если вы хотите выполнить ребазинг с первого сделанного коммита:

git rebase -i --root
38 голосов
/ 12 декабря 2008

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

20 голосов
/ 13 декабря 2008

Используйте gitk (* nix), или gitx (OS X) или аналогичные на других платформах, и посмотрите, какой коммит был корнем вашей ветви. Затем запустите:

git rebase -i <the SHA hash of the root commit>

Например, у меня есть репозиторий, который я проверял с помощью gitx:

gitx screencap

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

git rebase -i 38965ed29d89a4136e47b688ca10b522b6bc335f

И мой редактор всплывает с этим, и я могу изменить / squash / что угодно, как мне захочется.

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 автоматически определить корень дерева, но я не знаю, что это такое.

РЕДАКТИРОВАТЬ: Это магия это:

git log master..other_feature | cat

Который покажет вам все коммиты в этой ветке, а пайп к кошке отключит пейджер, поэтому вы сразу увидите первый коммит.

РЕДАКТИРОВАТЬ: сочетание вышеупомянутого дает полностью автоматизированное решение:

git rebase -i  `git log master..other_feature --pretty=format:"%h" | tail -n 1`~
7 голосов
/ 24 июня 2015

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

Проблема с git rebase -i master заключается в том, что у вас могут возникнуть конфликты слияния, с которыми вы не обязательно хотите иметь дело в данный момент, или вы можете исправить конфликт в одном коммите, только чтобы исправить его снова в другом коммите во время ход ребаз.

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

Вся проблема здесь в том, что вы должны знать , на какое обязательство вы должны ссылаться, либо по его SHA, либо по HEAD ~ x, и т. Д. Это только незначительное раздражение, но это раздражение .

Лучший способ

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

rbi = !sh -c \"git rebase -i `git merge-base $1 HEAD`\" -

Usage

git rbi parentBranch

Как это работает

Этот псевдоним - всего лишь сценарий оболочки, использующий аргумент, который ссылается на родительскую ветвь. Этот аргумент передается в git merge-base для определения самой последней общей фиксации между этой ветвью и текущей ветвью.

4 голосов
/ 05 мая 2015

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

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

Для получения более подробной информации см. Документы для git rebase :

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

2 голосов
/ 30 августа 2012

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

git rebase -i @{upstream}

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

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

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

1 голос
/ 23 июня 2014
git rebase -i --onto @{u}... @{u}

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

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

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