Git: Jak wycisnąć wszystkie zatwierdzenia na gałęzi


315

Tworzę nowy oddział masterz:

git checkout -b testbranch

Dokonuję w nim 20 zobowiązań.

Teraz chcę zmiażdżyć te 20 zobowiązań. Robię to z:

git rebase -i HEAD~20

A jeśli nie wiem, ile zatwierdzeń? Czy jest jakiś sposób na zrobienie czegoś takiego:

git rebase -i all on this branch

6
Można zrobić git rebase -i 58333012713fc168bd70ad00d191b3bdc601fa2dwich zrobi interaktywną rebase gdzie commitnumber jest ostatni popełnić który pozostaje niezmieniony
denns

@denns Korzystając z tej metody przy ostatnim zatwierdzeniu w gałęzi, z której korzystasz fantastycznie pracowałeś. Dzięki wielkie!
Joshua Pinter

Odpowiedzi:


392

Innym sposobem na zmiażdżenie wszystkich zatwierdzeń jest zresetowanie indeksu do wzorcowania:

 git checkout yourBranch
 git reset $(git merge-base master yourBranch)
 git add -A
 git commit -m "one commit on yourBranch"

Nie jest to idealne, ponieważ sugeruje, że wiesz, z której gałęzi pochodzi „twoja gałąź”.
Uwaga: odnalezienie gałęzi pochodzenia nie jest łatwe / możliwe w Git ( sposób wizualny jest często najłatwiejszy , jak widać tutaj ).


EDYCJA: będziesz musiał użyć git push --force


Karlotcha Hoa dodaje w komentarzach :

Aby zresetować, możesz to zrobić

git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD)) 

[To] automatycznie korzysta z gałęzi, w której aktualnie się znajdujesz.
Jeśli go użyjesz, możesz także użyć aliasu, ponieważ polecenie nie zależy od nazwy oddziału .


2
Lepiej do kasy, aby zatwierdzić, gdzie YourBranchjest obecnie. To pozostanie YourBranchnienaruszone, kiedy to zrobiszreset
Eugen Konkov

1
@Abdurrahim Lub otwórz git bash, a ty możesz skopiować i wkleić te polecenia!
VonC

3
Aby zresetować, możesz zrobić, git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))aby automatycznie użyć gałęzi, w której aktualnie się znajdujesz. Jeśli go użyjesz, możesz także użyć aliasu, ponieważ polecenie nie zależy od nazwy oddziału.
Karlotcha Hoa

1
@Druska W przypadku rozgałęzień w Simlpe nie powinno działać poprawnie.
VonC

1
@Shimmy tak, pod warunkiem, że wymusisz push po resecie: git push --force(i ostrzeż swoich współpracowników, jeśli jest kilka osób pracujących w tym oddziale)
VonC

112

Sprawdź gałąź, dla której chcesz zgnieść wszystkie zatwierdzenia w jednym zatwierdzeniu. Powiedzmy, jego nazwie, feature_branch.

git checkout feature_branch

Krok 1:

Wykonaj miękki reset origin/feature_branchswojego lokalnego masteroddziału (w zależności od potrzeb możesz zresetować również za pomocą Origin / Master). Spowoduje to zresetowanie wszystkich dodatkowych zatwierdzeń w feature_branchpliku, ale bez zmiany lokalnych zmian plików.

git reset --soft master

Krok 2:

Dodaj wszystkie zmiany w katalogu git repo do nowego zatwierdzenia, które ma zostać utworzone. I to samo z komunikatem.

git add -A && git commit -m "commit message goes here"


6
To było dla mnie najbardziej niezawodne rozwiązanie - nie powodowało błędów bazy ani nie łączyło konfliktów.
ANTARA

1
Ostrzeżenie: git dodaj -Dodaj WSZYSTKO, co masz w folderze lokalnym - do oddziału.
David H

uwielbiam to rozwiązanie! właśnie tego chciałem!
jacoballenwood,

1
Najlepsze rozwiązanie dla noob - nieniszczące i tylko chwilą nieoczekiwaną może być sprawdzanie za dużo, takich jak tajemnice aplikacji itp., Co nie powinno mieć znaczenia, jeśli masz odpowiedni plik
gitignore

@NSduToit Krótka odpowiedź: Nie, nie musisz. Po wykonaniu wyżej wymienionych kroków w mojej odpowiedzi skończysz na jednym zatwierdzeniu z pewnymi zmianami kodu. Możesz myśleć o tym jak o każdym innym zatwierdzeniu z pewnymi zmianami kodu. Możesz przekazać to do swojej zdalnej gałęzi bez -fflagi.
shanky

110

To, co robisz, jest podatne na błędy. Po prostu zrób:

git rebase -i master

co automatycznie spowoduje bazowanie tylko zatwierdzeń oddziału na bieżącym najnowszym systemie głównym.


5
dzięki, dostałem to, ale dlaczego mój system jest podatny na błędy
użytkownik3803850,

10
Prawdopodobnie dlatego, że łatwo pomylić numer?
Daniel Scott

13
Zgadzam się, że to twoje najlepsze rozwiązanie. ale kliknij ten link, ponieważ lepiej wyjaśnia, co musisz zrobić.
Christo

3
Zamiast zgniatać zatwierdzenia, możesz scalić gałąź z master i wykonać reset git do origin / master, aby cofnąć scenę wszystkich commits. Pozwoliłoby to zatwierdzić istniejący kod niestacjonarny za pomocącommit -am "the whole thing!"
nurettin

2
@nurettin Myślę, że reset origin/mastermetoda jest naprawdę zła, ponieważ jest to tak samo jak wykonywanie zatwierdzeń bezpośrednio na masterie - nie ma historii „scalania gałęzi”, nie ma opcji żądania ściągania. Odpowiedź @WaZaA jest bardziej zgodna z normalnym procesem pracy z gitem, myślę
Drenai

79

Kolejny prosty sposób: przejdź do gałęzi początkowej i zrób merge --squash. To polecenie nie wykonuje zatwierdzenia „zgniecionego”. kiedy to zrobisz, wszystkie wiadomości zatwierdzenia Twojej Oddziału zostaną zebrane.

$ git checkout master
$ git merge --squash yourBranch
$ git commit # all commit messages of yourBranch in one, really useful
 > [status 5007e77] Squashed commit of the following: ...

1
Prawdziwe. Wspomniałem o różnicy między scalaniem - quassem a rebase -i w stackoverflow.com/a/2427520/6309
VonC

1
Działa to, jeśli nie chcesz zgniatać gałęzi nadrzędnej, po prostu stwórz i przełącz się na nową gałąź opartą na gałęzi nadrzędnej i wykonaj scalenie squasha.
Charlotte,

Na zdrowie kolego, świetna wskazówka!
Nestor Milyaev

miły! tworzę gałąź „temp” z „master” najpierw do zgniatania „yourBranch”, a następnie łączę „temp” w „master”.
lazieburd

34

Zakładając, że rozgałęziasz się od mastera, nie musisz yourBranchcały czas wchodzić w krok resetowania:

git checkout yourBranch
git reset --soft HEAD~$(git rev-list --count HEAD ^master)
git add -A
git commit -m "one commit on yourBranch"

Objaśnienie :

  • git rev-list --count HEAD ^masterzlicza zatwierdzenia, ponieważ utworzono gałąź funkcji od wzorca, np. 20
  • git reset --soft HEAD~20wykona miękki reset ostatnich 20 zatwierdzeń. To pozostawia zmiany w plikach, ale usuwa zatwierdzenia.

Zastosowanie :

W moim profilu .bash dodałem alias, aby gisquashto zrobić za pomocą jednego polecenia:

# squash all commits into one
alias gisquash='git reset --soft HEAD~$(git rev-list --count HEAD ^master)'

Po zresetowaniu i zatwierdzeniu musisz zrobić git push --force.

Wskazówka :

Jeśli używasz Gitlab> = 11.0, nie musisz już tego robić, ponieważ ma opcję zgniatania podczas łączenia gałęzi. Opcja Gitlab Squashing


15

Opierając się na przeczytaniu kilku pytań Stackoverflow i odpowiedzi na temat squashingu, myślę, że jest to dobry jeden wiersz do zgniatania wszystkich zatwierdzeń w gałęzi:

git reset --soft $(git merge-base master YOUR_BRANCH) && git commit -am "YOUR COMMIT MESSAGE" && git rebase -i master

Zakłada się, że master jest gałęzią podstawową.


1
Bardzo dziękuję, firma ma wiele ograniczeń i nie mogła bazować w zwykły sposób z edytorem, ponieważ nie było głośno, aby zapisać. Nie można również użyć funkcji squash i merge w git, ponieważ ta gałąź idzie do Lead dev do scalenia i nie podoba mu się to. Ta 1 wkładka zadziałała i uratowała bóle głowy. Wspaniała praca.
L1ghtk3ira

10

Rozwiązanie dla osób, które wolą klikać:

  1. Zainstaluj sourcetree (jest bezpłatny)

  2. Sprawdź, jak wyglądają twoje zobowiązania. Najprawdopodobniej masz coś podobnego do tego wprowadź opis zdjęcia tutaj

  3. Kliknij prawym przyciskiem myszy na zatwierdzenie nadrzędne . W naszym przypadku jest to gałąź master.

wprowadź opis zdjęcia tutaj

  1. Możesz zgnieść zatwierdzenie z poprzednim, klikając przycisk. W naszym przypadku musimy kliknąć 2 razy. Możesz także zmienić komunikat zatwierdzenia wprowadź opis zdjęcia tutaj

  2. Rezultaty są niesamowite i jesteśmy gotowi do działania! wprowadź opis zdjęcia tutaj

Uwaga dodatkowa: Jeśli przepychałeś swoje częściowe zatwierdzenia do pilota, musisz użyć siły push po squashu


Dzięki za to!
Kryształ,

0

Innym rozwiązaniem byłoby zapisanie wszystkich dzienników zatwierdzeń w pliku

git log> branch.log

Teraz branch.log będzie miał wszystkie identyfikatory zatwierdzeń od początku. Przewiń w dół i weź pierwszy zatwierdzenie (będzie to trudne w terminalu) za pomocą pierwszego zatwierdzenia

git reset --soft

wszystkie zobowiązania zostaną zmiażdżone


0

Reset Git, jak wspomniano wcześniej w wielu odpowiedziach, jest zdecydowanie najlepszym i najprostszym sposobem na osiągnięcie tego, co chcesz. Używam go w następującym przepływie pracy:

(w dziale rozwoju)

git fetch
git merge origin/master  #so development branch has all current changes from master
git reset origin/master  #will show all changes from development branch to master as unstaged
git gui # do a final review, stage all changes you really want
git commit # all changes in a single commit
git branch -f master #update local master branch
git push origin master #push it

0

Cały ten reset gita, twardy, miękki i wszystko inne wspomniane tutaj prawdopodobnie działa (nie dla mnie), jeśli wykonasz kroki poprawnie i jakiś dżin.
Jeśli jesteś przeciętnym Joe smo, spróbuj tego:
Jak używać git merge - quash?


Uratowałem sobie życie, i pójdę do squasha, używam tego 4 razy, odkąd się o tym dowiedziałem. Prosty, czysty i w zasadzie 1 comamnd. W skrócie:


jeśli jesteś na gałęzi, nazwijmy to „moja_nowa_funkcja” wyłącz rozwijanie, a twoje żądanie ściągnięcia ma 35 zatwierdzeń (lub jak wiele) i chcesz, aby było 1.

A. Upewnij się, że twój oddział jest aktualny, kontynuuj rozwijaj, pobieraj najnowsze oraz łącz i rozwiązuj wszelkie konflikty z „my_new_feature”
(ten krok naprawdę powinieneś zrobić tak szybko, jak to możliwe przez cały czas)

B. B. Bądź na bieżąco z rozwijaniem i rozgałęzianiem się do nowego oddziału, nazywając go „my_new_feature_squashed”

C. magia jest tutaj.
Chcesz przenieść swoją pracę z „my_new_feature” do „my_new_feature_squashed”
Więc po prostu zrób to (podczas tworzenia nowego oddziału, rozwijamy się):
git merge --squash my_new_feature

Wszystkie twoje zmiany będą teraz w twoim nowym oddziale, nie krępuj się przetestować, a następnie po prostu wykonaj 1 zatwierdzenie, wypchnij, nowy PR tego oddziału - i poczekaj na powtórzenie następnego dnia.
Nie lubisz kodować? :)


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.