git remove merge commit z historii

99

Moja historia Gita wygląda tak:

Historia Gita

Chciałbym zmiażdżyć fioletowe commity w jedną. Nie chcę ich już nigdy widzieć w moim dzienniku zmian.

Próbowałem zrobić git rebase -i 1, ale mimo że 1znajduje się na niebieskiej gałęzi (por. Zdjęcie), nadal widzę każde zatwierdzenie na mojej fioletowej gałęzi.

Jak mogę całkowicie usunąć fioletową gałąź (z dziennika zatwierdzeń)?

Benjamin Toueg
źródło
Czy Twoje repozytorium zostało przesunięte w dowolne miejsce, z którego wyciągnęli je inni ludzie?
Schleis,
Obie gałęzie mają charakter wyłącznie lokalny.
Benjamin Toueg,

Odpowiedzi:

102

Zrób git rebase -i <sha before the branches diverged>to, aby usunąć zatwierdzenie merge, a dziennik będzie jednym wierszem, tak jak chciałeś. Możesz także usunąć wszystkie zmiany, których już nie chcesz. Powodem, dla którego twoja rebase nie działał, był fakt, że nie cofałeś się wystarczająco daleko.

OSTRZEŻENIE: w ten sposób przepisujesz historię. Robienie tego ze zmianami, które zostały przeniesione do zdalnego repozytorium, spowoduje problemy. Zalecam robić to tylko z lokalnymi zatwierdzeniami.

Schleis
źródło
4
Nawet jeśli wybiorę sha, zanim gałęzie się rozejdą, widzę wszystkie zatwierdzenia fioletowej gałęzi -_-
Benjamin Toueg
1
Tak, następnie usuniesz je w edytorze, który się pojawi, git rebasea zostaną one usunięte.
Schleis,
4
Usunięcie zatwierdzeń spowodowało utratę wszystkich modyfikacji scalenia. Ale zrobiłem miękki reset i mogłem mieć coś takiego, jak chciałem (kolejność nie odpowiada początkowym oczekiwaniom).
Benjamin Toueg
2
ta odpowiedź jest niekompletna, z której gałęzi należy zainicjować rebase?
grgry
3
Dość pewien, że nie chcesz „usuwać” zatwierdzeń. „Usuń” nie jest opcją w rebase, ale usuń tak. jeśli usuniesz zatwierdzenie, utracisz wprowadzone przez nie zmiany. Chcesz zmiażdżyć zatwierdzenia.
thecoshman
71

Rozpoczynając od repozytorium w stanie pierwotnym

Oryginalna historia repo

Aby usunąć merge, zatwierdzić i zgnieść gałąź do pojedynczego zatwierdzenia w głównej linii

Zgniecione zatwierdzenia, brak zatwierdzenia scalenia

Użyj tych poleceń (zastępując 5 i 1 wartościami SHA odpowiednich zatwierdzeń):

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

Aby zachować zatwierdzenie scalające, ale zgnieść zmiany gałęzi w jedną:

Zgniecione zatwierdzenia, zachowane zatwierdzenie scalające

Użyj tych poleceń (zastępując 5, 1 i C wartościami SHA odpowiednich zatwierdzeń):

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

Aby usunąć zatwierdzenie scalające i zastąpić je indywidualnymi zatwierdzeniami z gałęzi

Branch został przeniesiony do mainline, bez zatwierdzenia scalenia

Po prostu zrób (zastępując 5 wartością SHA odpowiedniego zatwierdzenia):

git rebase 5 master

I wreszcie, aby całkowicie usunąć gałąź

Oddział został całkowicie usunięty

Użyj tego polecenia (zastępując C i D SHA odpowiednich zatwierdzeń):

git rebase --onto C D~ master
Allen Luce
źródło
w git rebase 5 masterprzypadku, dlaczego nie jest to zamówienie „ABC 1 2 3 4 5 D ...”?
Roy
1
To polecenie przyjmuje zatwierdzenia, które masternie mają nic wspólnego z, 5i umieszcza je na wierzchu 5. Zatwierdzenie w Cnie jest częścią linii 5, jest pierwszym, które zostanie przeniesione na górę 5.
Allen Luce
2
Jeśli chcesz skończyć z "ABC 1 2 3 4 5 D ...", możesz zrobić:git rebase C 5; git rebase 5 master
Allen Luce
19

Aby po prostu usunąć polecenie scalenia

Jeśli wszystko, co chcesz zrobić, to usunąć zatwierdzenie merge (2), aby wyglądało na to, że nigdy się nie wydarzyło, polecenie jest po prostu następujące

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

A teraz fioletowej gałęzi nie ma w ogóle w dzienniku zmian koloru niebieskiego i znowu masz dwie oddzielne gałęzie. Następnie możesz samodzielnie zmiażdżyć fiolet i wykonywać dowolne inne manipulacje bez konieczności scalania.

Królikarnia
źródło
1
Ze wszystkich odpowiedzi uważam, że jest to zarówno najprostsze, jak i najłatwiejsze do zrobienia. Dziękuję Ci.
Roshambo
16

Istnieją dwa sposoby rozwiązania tego problemu w zależności od tego, czego chcesz:

Rozwiązanie 1 : Usuń fioletowe zatwierdzenia, zachowując historię (na wypadek, gdybyś chciał cofnąć)

git revert -m 1 <SHA of merge>

-m 1 określa, którą linię nadrzędną wybrać

Purpurowe zatwierdzenia nadal będą istniały w historii, ale ponieważ zostały przywrócone, nie zobaczysz kodu z tych zatwierdzeń.


Rozwiązanie 2 : Całkowicie usuń fioletowe zatwierdzenia (zmiana destrukcyjna, jeśli repozytorium jest udostępniane)

git rebase -i <SHA before branching out>

i usuń (usuń linie) odpowiadające fioletowym zatwierdzeniom.

Byłoby to mniej skomplikowane, gdyby zmiany nie były wykonywane po scaleniu. Dodatkowe zatwierdzenia zwiększają ryzyko konfliktów podczas revert/rebase.

prem
źródło
To nie brzmi dobrze. Pomijając fakt, że trudno powiedzieć, co pierwotny plakat chciał zrobić z fioletowymi zatwierdzeniami w pierwszej kolejności, jeśli cofniesz scalanie, to w porządku, to zrobi odwrotną łatkę zmian z tego zatwierdzenia i doda ją jako kolejne zatwierdzenie, anulowanie fioletowych zatwierdzeń. To jest jak 1 - 1 = 0. Ale jeśli następnie zmienisz bazę fioletowych zatwierdzeń, pozostawisz cofniętą łatkę, chyba że ją również zmienisz. Jeśli tego nie zrobisz, to tak, jakbyś zastosował się -1do swojej historii, a nie 0, więc zostawisz zmiany, których nie chcesz.
@Cupcake, podano dwie oddzielne odpowiedzi. Poprawiłem odpowiedź, aby była mniej zagmatwana: P
prem
AFAIK nie o to prosi PO. Chce zachować zmiany, ale usunąć hałas z dziennika. W tym celu musi zmniejszyć liczbę zatwierdzeń, a usunięcie usunie zmiany.
thecoshman
To prawda, wygląda na to, że oryginalne pytanie zostało przeformułowane. Ta odpowiedź nie dotyczy problemu PO.
prem