git удалить коммит слияния из истории

99

Моя история Git выглядит так:

История Git

Я хотел бы превратить фиолетовые коммиты в один. Я не хочу больше видеть их в моем журнале коммитов.

Я пытался сделать git rebase -i 1, но даже несмотря 1на то, что он находится на синей ветке (см. Рисунок), я все еще вижу каждую фиксацию в моей фиолетовой ветке.

Как я могу полностью удалить фиолетовую ветку (из журнала фиксации)?

Бенджамин Туег
источник
Ваше репо продвигается куда-нибудь, что другие люди извлекли из него?
Schleis
Оба филиала чисто местные.
Benjamin Toueg

Ответы:

102

Как git rebase -i <sha before the branches diverged>это позволит удалить слияние фиксации и журнал будет ни одной строки , как вы хотели. Вы также можете удалить любые коммиты, которые вам больше не нужны. Причина, по которой ваша перебазировка не работала, заключалась в том, что вы не возвращались достаточно далеко.

ВНИМАНИЕ: вы переписываете историю, делая это. Выполнение этого с изменениями, которые были отправлены в удаленное репо, вызовет проблемы. Я рекомендую делать это только с локальными коммитами.

Schleis
источник
4
Даже если я выберу ша до того, как ветви разойдутся, я увижу все коммиты фиолетовой ветви -_-
Benjamin Toueg
1
Да, затем вы удаляете их в редакторе, который появляется, git rebaseи они будут удалены.
Schleis
4
Удаление коммитов привело к потере всех модификаций слияния. Но я сделал мягкий сброс и смог получить что-то совсем то, что хотел (порядок не соответствует первоначальным ожиданиям).
Benjamin Toueg
2
этот ответ неполон, из какой ветви вы инициируете перебазирование?
grgry
3
Совершенно уверен, что вы не хотите «удалять» коммиты. «удалить» нельзя в rebase, но удалить можно. если вы удалите фиксацию, вы потеряете внесенные в нее изменения. Вы хотите раздавить коммиты.
thecoshman
71

Начиная с репо в исходном состоянии

Оригинальная история репо

Чтобы удалить фиксацию слияния и сжать ветку в одну фиксацию в основной ветке

Сжатые коммиты, без слияния

Используйте эти команды (заменив 5 и 1 на SHA соответствующих коммитов):

git checkout 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git rebase HEAD master

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

Сжатые коммиты, сохраненные коммиты слияния

Используйте эти команды (заменив 5, 1 и C на SHA соответствующих коммитов):

git checkout -b tempbranch 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git checkout C
git merge --no-ff tempbranch
git rebase HEAD master

Чтобы удалить коммит слияния и заменить его отдельными коммитами из ветки

Ветвь перемещена в основную линию, без фиксации слияния

Просто сделайте (заменив 5 на SHA соответствующего коммита):

git rebase 5 master

И наконец, чтобы полностью удалить ветку

Филиал полностью удален

Используйте эту команду (заменив C и D на SHA соответствующих коммитов):

git rebase --onto C D~ master
Аллен Люс
источник
в git rebase 5 masterслучае, почему это не порядок "ABC 1 2 3 4 5 D ..."?
Рой
1
Эта команда берет коммиты, которые masterне имеют ничего общего с 5ними, и накладывает их поверх 5. Коммит в Cне является частью линии 5, он первым перемещается поверх 5.
Allen Luce
2
Если вы хотите закончить с «ABC 1 2 3 4 5 D ...», вы можете сделать:git rebase C 5; git rebase 5 master
Аллен Люс
19

Чтобы просто удалить фиксацию слияния

Если все, что вы хотите сделать, это удалить фиксацию слияния (2), чтобы этого не произошло, команда будет выглядеть следующим образом

git rebase --onto <sha of 1> <sha of 2> <blue branch>

И теперь фиолетовой ветки нет в журнале фиксации синего цвета, и у вас снова есть две отдельные ветки. Затем вы можете раздавить фиолетовый цвет независимо и выполнять любые другие манипуляции, которые вам нужны, без фиксации слияния.

Уоррен
источник
1
Я считаю, что это самый простой и самый простой из всех ответов. Спасибо.
Рошамбо
16

Есть два способа решить эту проблему в зависимости от того, что вы хотите:

Решение 1. Удалите фиолетовые коммиты, сохраняя историю (на случай, если вы хотите откатиться)

git revert -m 1 <SHA of merge>

-m 1 указывает, какую родительскую строку выбрать

Фиолетовые коммиты останутся в истории, но, поскольку вы вернулись, вы не увидите код этих коммитов.


Решение 2. Полностью удалите фиолетовые коммиты (нарушение работы при совместном использовании репо)

git rebase -i <SHA before branching out>

и удалите (удалите строки), соответствующие фиолетовым коммитам.

Это было бы менее сложно, если бы после слияния не производились коммиты. Дополнительные коммиты увеличивают вероятность конфликтов во время revert/rebase.

Прем
источник
Это звучит неправильно. Оставляя в стороне тот факт, что трудно сказать, что исходный плакат хотел сделать с фиолетовыми коммитами в первую очередь, если вы отмените слияние, это нормально, это сделает обратный патч изменений из этого коммита и добавит его как другой коммит, отменяющий фиолетовый коммит. Это как 1 - 1 = 0. Но если вы затем удалите фиолетовые коммиты, вы оставите возвращенный патч, если вы не удалите и его. Если вы этого не сделаете, это как применить -1к своей истории, а не 0, так что вы оставите изменения, которые вам не нужны.
@Cupcake, были предоставлены два отдельных ответа. Я изменил ответ, чтобы он был менее запутанным: P
prem
AFAIK, это не то, о чем просит OP. Он хочет сохранить изменения, но убрать шум из журнала. Для этого ему нужно сжать коммиты, удаление приведет к удалению изменений.
thecoshman 02
Правда, похоже, первоначальный вопрос перефразирован. Этот ответ не относится к проблеме OP.
прет