To pytanie jest źle zdefiniowane. Nie mówi wprost, że autor chce 1-2- (3 + 4) -5 lub 1-2-4-5
RandyTek
14
8 lat później nie mogę powiedzieć dokładnie, jaki problem próbowałem rozwiązać. Ale w git zawsze jest wiele sposobów na zrobienie czegoś i jest wiele odpowiedzi, które podobały się różnym ludziom, więc wydaje mi się, że dwuznaczność nie sprawia zbyt wielu ludziom trudności
1800 INFORMACJE
1
git rebase --onto 2 3 HEADwłaściwie oznacza rebase na 2, z zatwierdzeniami między 3 a HEAD (HEAD jest opcjonalny, lub 5 w tym przypadku)
neaumusic
Odpowiedzi:
76
Aby połączyć wersję 3 i 4 w jedną wersję, możesz użyć git rebase. Jeśli chcesz usunąć zmiany w wersji 3, musisz użyć polecenia edycji w interaktywnym trybie bazy. Jeśli chcesz połączyć zmiany w jedną wersję, użyj squasha.
Z powodzeniem zastosowałem tę technikę squasha, ale nigdy wcześniej nie musiałem usuwać wersji. Mam nadzieję, że dokumentacja git-rebase pod „Podziałem zobowiązań” powinna dać ci wystarczająco dużo pomysłu, aby to rozgryźć. (Lub ktoś inny może wiedzieć).
Rozpocznij od najstarszego zatwierdzenia, które chcesz zachować bez zmian:
git rebase -i <after-this-commit>
Zostanie uruchomiony edytor ze wszystkimi zatwierdzeniami w bieżącym oddziale (ignorując zatwierdzenia scalania), które pojawiają się po danym zatwierdzeniu. Możesz zmienić kolejność zatwierdzeń na tej liście do zawartości twojego serca i możesz je usunąć. Lista wygląda mniej więcej tak:
wybierz deadbee Oneline tego zatwierdzenia
pick fa1afe1 Oneline następnego zatwierdzenia
...
Opisy online są wyłącznie dla twojej przyjemności; git-rebase nie będzie na nie patrzył, ale na nazwy zatwierdzeń (w tym przykładzie „deadbee” i „fa1afe1”), więc nie usuwaj ani nie edytuj nazw.
Zastępując polecenie „pick” poleceniem „edit”, możesz powiedzieć git-rebase, aby przestał działać po zastosowaniu tego zatwierdzenia, abyś mógł edytować pliki i / lub komunikat zatwierdzenia, zmienić zatwierdzenie i kontynuować bazowanie.
Jeśli chcesz złożyć dwa lub więcej zatwierdzeń w jeden, zamień polecenie „pick” na „squash” dla drugiego i kolejnego zatwierdzenia. Jeśli zatwierdzenia miały różnych autorów, przypisuje zgniecione zatwierdzenie autorowi pierwszego zatwierdzenia.
-1 Pytanie dobrze zdefiniowane, ale ta odpowiedź nie jest tak jasna. Autor nie mówi, jakie jest dokładne rozwiązanie.
Aleksandr Levchuk
1
To jest zły trop. Sekcja ZGODNOŚCI ROZDZIELCZEJ jest nieprawidłowa. Chcesz przeczytać znacznie więcej w instrukcji - patrz odpowiedź @Rares Vernica.
Aleksandr Levchuk
1
@AleksandrLevchuk Pytanie nie jest dobrze zdefiniowane: nie jest jasne, w jaki sposób pytanie brzmi, czy zestaw zmian w 3 ma zostać zachowany, czy odrzucony. Zgadzam się, że jeśli zmiany mają zostać odrzucone, inne odpowiedzi oferują łatwiejsze podejście. Jeśli zmiany zostaną zachowane, będzie to operacja czysto kosmetyczna. Oba podejścia przepisują historię w sposób niebezpieczny, jeśli inni mogliby oprzeć swoją pracę na błędnej historii; w takim przypadku czyszczenie kosmetyczne nie powinno być wykonane, a usunięcie zmiany lepiej byłoby wykonać za pomocą git revert.
Theodore Murdock
124
Zgodnie z tym komentarzem (i sprawdziłem, że to prawda) odpowiedź rado jest bardzo bliska, ale pozostawia gita w stanie odłączonej głowy. Zamiast tego usuń HEADi użyj tego, aby usunąć <commit-id>z gałęzi, w której jesteś:
Gdybyś mógł mi powiedzieć, jak usunąć ten identyfikator z historii na podstawie samego identyfikatora, byłbyś moim bohaterem.
kayleeFrye_onDeck
Czy możesz dołączyć wyjaśnienie, co magiczne polecenie robi w odpowiedzi? Tj. Co oznacza każdy parametr?
alexandroid
to jest niesamowite, ale co jeśli chcę usunąć pierwsze zatwierdzenie w historii? (dlatego tu przybyłem: P)
Sterling Camden
2
Z jakiegoś powodu nic się nie dzieje, kiedy to uruchamiam. Jednak zmiana ^na ~1sprawiła, że działało.
Antimony
Znacznie późno, ale dodam, że jeśli napotkasz konflikty scalania, przerwij tworzenie bazy, a następnie uruchom ją ponownie --strategy-option theirsna końcu.
LastStar007
122
Oto sposób na usunięcie nieinteraktywnie określonego <commit-id>, znając tylko te <commit-id>, które chcesz usunąć:
Pracowałem też dla mnie. Przy okazji, co robi operator ^? Czy to oznacza następne zatwierdzenie po określonym?
hopia
3
@hopia oznacza (pierwszego) rodzica określonego zatwierdzenia. Zobacz „wersje pomocy git”
Emil Styrke
12
Zobacz zalecenie @ kareem w jego odpowiedzi, aby pominąć HEAD, aby uniknąć odłączenia głowy.
mklement0
1
Znacznie łatwiejsze niż ustalenie, ile osób zobowiązuje się do wyszukiwania.
Dana Woodman,
1
to jest niesamowite, ale co jeśli chcę usunąć pierwsze zatwierdzenie w historii? (dlatego tu przybyłem: P)
Sterling Camden
76
Jak wspomniano wcześniej, git-rebase (1) jest twoim przyjacielem. Zakładając, że zatwierdzenia znajdują się w twoim masteroddziale, zrobiłbyś:
git rebase --onto master~3 master~2 master
Przed:
1---2---3---4---5 master
Po:
1---2---4'---5' master
Z git-rebase (1):
Zakres zatwierdzeń można również usunąć za pomocą rebase. Jeśli mamy następującą sytuację:
E---F---G---H---I---J topicA
następnie polecenie
git rebase --onto topicA~5 topicA~3 topicA
spowodowałoby usunięcie zatwierdzeń F i G:
E---H'---I'---J' topicA
Jest to przydatne, jeśli F i G były w jakiś sposób wadliwe lub nie powinny być częścią tematu A. Zauważ, że argumentem --onto i parametrem może być dowolny poprawny zatwierdzenie.
Jeśli wszystko, co chcesz zrobić, to usunąć zmiany wprowadzone w wersji 3, możesz użyć git revert.
Git revert tworzy po prostu nową wersję ze zmianami, które cofają wszystkie zmiany w cofniętej wersji.
Oznacza to, że zachowujesz informacje zarówno o niechcianym zatwierdzeniu, jak i zatwierdzeniu, które usuwa te zmiany.
Jest to prawdopodobnie o wiele bardziej przyjazne, jeśli w ogóle możliwe jest, że ktoś wyciągnął z twojego repozytorium w międzyczasie, ponieważ przywracanie jest w zasadzie tylko standardowym zatwierdzeniem.
Niestety, nie jest to dla mnie dobre rozwiązanie, ponieważ ktoś przypadkowo przeznaczył 100 MB bzdur na repozytorium, powiększając rozmiar i spowalniając interfejs sieciowy.
Stephen Smith
18
Wszystkie dotychczasowe odpowiedzi nie uwzględniają problemu końcowego:
Czy istnieje skuteczna metoda, jeśli po usunięciu istnieją setki wersji?
Kroki są następujące, ale w celach informacyjnych załóżmy następującą historię:
C : zatwierdzenie tuż po zatwierdzeniu do usunięcia (wyczyść)
R : Zatwierdzenie do usunięcia
B : zatwierdzenie tuż przed zatwierdzeniem do usunięcia (podstawa)
Ze względu na ograniczenie „setek wersji” zakładam następujące warunki wstępne:
jest pewne żenujące zobowiązanie, którego nigdy nie chciałbyś istnieć
istnieją kolejne ZERO, które faktycznie zależą od tego żenującego zatwierdzenia (zero konfliktów przy przywróceniu)
nie obchodzi cię, że zostaniesz wymieniony jako „Committer” spośród setek interweniujących zmian („Autor” zostanie zachowany)
nigdy nie udostępniłeś repozytorium
lub rzeczywiście masz wystarczający wpływ na wszystkich ludzi, którzy kiedykolwiek sklonowali historię z tym zobowiązaniem, aby przekonać ich do korzystania z nowej historii
Jest to dość restrykcyjny zestaw ograniczeń, ale istnieje interesująca odpowiedź, która faktycznie działa w tym przypadku narożnika.
Oto kroki:
git branch base B
git branch remove-me R
git branch save
git rebase --preserve-merges --onto base remove-me
Jeśli naprawdę nie ma konfliktów, powinno to przebiegać bez dalszych zakłóceń. Jeśli występują konflikty, możesz je rozwiązać i / rebase --continuelub po prostu żyć z zażenowaniem i rebase --abort.
Teraz powinno być na masterktóre nie ma już popełnić R w nim. Te savepunkty odgałęzienia do miejsca, gdzie były wcześniej, w przypadku, gdy chcesz się pogodzić.
To, jak chcesz zorganizować przeniesienie wszystkich osób do nowej historii, zależy od Ciebie. Trzeba będzie zapoznać się z stash, reset --hard, i cherry-pick. I można usunąć base, remove-meoraz saveoddziały
Odpowiedzi rado i kareem nic dla mnie nie robią (pojawia się tylko komunikat „Aktualna gałąź jest aktualna.”). Być może dzieje się tak, ponieważ symbol „^” nie działa w konsoli Windows. Jednak zgodnie z tym komentarzem zastąpienie „^” przez „~ 1” rozwiązuje problem.
git rebase --onto 2 3 HEAD
właściwie oznacza rebase na 2, z zatwierdzeniami między 3 a HEAD (HEAD jest opcjonalny, lub 5 w tym przypadku)Odpowiedzi:
Aby połączyć wersję 3 i 4 w jedną wersję, możesz użyć git rebase. Jeśli chcesz usunąć zmiany w wersji 3, musisz użyć polecenia edycji w interaktywnym trybie bazy. Jeśli chcesz połączyć zmiany w jedną wersję, użyj squasha.
Z powodzeniem zastosowałem tę technikę squasha, ale nigdy wcześniej nie musiałem usuwać wersji. Mam nadzieję, że dokumentacja git-rebase pod „Podziałem zobowiązań” powinna dać ci wystarczająco dużo pomysłu, aby to rozgryźć. (Lub ktoś inny może wiedzieć).
Z dokumentacji git :
źródło
Zgodnie z tym komentarzem (i sprawdziłem, że to prawda) odpowiedź rado jest bardzo bliska, ale pozostawia gita w stanie odłączonej głowy. Zamiast tego usuń
HEAD
i użyj tego, aby usunąć<commit-id>
z gałęzi, w której jesteś:źródło
^
na~1
sprawiła, że działało.--strategy-option theirs
na końcu.Oto sposób na usunięcie nieinteraktywnie określonego
<commit-id>
, znając tylko te<commit-id>
, które chcesz usunąć:źródło
HEAD
, aby uniknąć odłączenia głowy.Jak wspomniano wcześniej, git-rebase (1) jest twoim przyjacielem. Zakładając, że zatwierdzenia znajdują się w twoim
master
oddziale, zrobiłbyś:Przed:
Po:
Z git-rebase (1):
źródło
--onto master~3 master~1
?MERGE CONFLICT
błąd. Użyłem scenariusza wymienionego w stackoverflow.com/questions/2938301/remove-specific-commit i nie mogę usunąć drugiego zatwierdzenia w tym przykładzie.Jeśli wszystko, co chcesz zrobić, to usunąć zmiany wprowadzone w wersji 3, możesz użyć git revert.
Git revert tworzy po prostu nową wersję ze zmianami, które cofają wszystkie zmiany w cofniętej wersji.
Oznacza to, że zachowujesz informacje zarówno o niechcianym zatwierdzeniu, jak i zatwierdzeniu, które usuwa te zmiany.
Jest to prawdopodobnie o wiele bardziej przyjazne, jeśli w ogóle możliwe jest, że ktoś wyciągnął z twojego repozytorium w międzyczasie, ponieważ przywracanie jest w zasadzie tylko standardowym zatwierdzeniem.
źródło
Wszystkie dotychczasowe odpowiedzi nie uwzględniają problemu końcowego:
Kroki są następujące, ale w celach informacyjnych załóżmy następującą historię:
C : zatwierdzenie tuż po zatwierdzeniu do usunięcia (wyczyść)
R : Zatwierdzenie do usunięcia
B : zatwierdzenie tuż przed zatwierdzeniem do usunięcia (podstawa)
Ze względu na ograniczenie „setek wersji” zakładam następujące warunki wstępne:
Jest to dość restrykcyjny zestaw ograniczeń, ale istnieje interesująca odpowiedź, która faktycznie działa w tym przypadku narożnika.
Oto kroki:
git branch base B
git branch remove-me R
git branch save
git rebase --preserve-merges --onto base remove-me
Jeśli naprawdę nie ma konfliktów, powinno to przebiegać bez dalszych zakłóceń. Jeśli występują konflikty, możesz je rozwiązać i /
rebase --continue
lub po prostu żyć z zażenowaniem irebase --abort
.Teraz powinno być na
master
które nie ma już popełnić R w nim. Tesave
punkty odgałęzienia do miejsca, gdzie były wcześniej, w przypadku, gdy chcesz się pogodzić.To, jak chcesz zorganizować przeniesienie wszystkich osób do nowej historii, zależy od Ciebie. Trzeba będzie zapoznać się z
stash
,reset --hard
, icherry-pick
. I można usunąćbase
,remove-me
orazsave
oddziałyźródło
Wylądowałem również w podobnej sytuacji. Użyj interaktywnej bazy za pomocą poniższego polecenia i podczas wybierania upuść trzeci zatwierdzenie.
źródło
Oto scenariusz, z którym miałem do czynienia i sposób jego rozwiązania.
oto
R
zatwierdzenie, które musiałem usunąć, iI
jest to jedno zatwierdzenie, które nastąpi późniejR
Zrobiłem rewizję i zmiażdżyłem je razem
Podczas interaktywnego squasha rebase ostatnie 2 zatwierdzenia.
źródło
Odpowiedzi rado i kareem nic dla mnie nie robią (pojawia się tylko komunikat „Aktualna gałąź jest aktualna.”). Być może dzieje się tak, ponieważ symbol „^” nie działa w konsoli Windows. Jednak zgodnie z tym komentarzem zastąpienie „^” przez „~ 1” rozwiązuje problem.
źródło