Jak zmiażdżyć moje ostatnie X zatwierdzeń razem w jednym zatwierdzeniu za pomocą Git?
Jak zmiażdżyć moje ostatnie X zatwierdzeń razem w jednym zatwierdzeniu za pomocą Git?
Odpowiedzi:
Użyj git rebase -i <after-this-commit>
i zamień „pick” na drugim i kolejnych zatwierdzeniach na „squash” lub „fixup”, jak opisano w instrukcji .
W tym przykładzie <after-this-commit>
jest skrótem SHA1 lub względną lokalizacją HEAD bieżącej gałęzi, z której analizowane są zatwierdzenia dla polecenia rebase. Na przykład, jeśli użytkownik chce wyświetlić 5 zatwierdzeń z bieżącego HEAD w przeszłości, polecenie to git rebase -i HEAD~5
.
<after-this-commit>
?
<after-this-commit>
to zatwierdzenie X + 1, tj. rodzic najstarszego zatwierdzenia, które chcesz zgnieść.
rebase -i
podejściem a tym reset --soft
, rebase -i
pozwala mi zachować autora zatwierdzenia, a jednocześnie reset --soft
pozwala na ponowne uruchomienie. Czasami muszę zmiażdżyć zatwierdzenia żądań ściągnięcia, ale zachowując informacje o autorze. Czasami muszę zresetować soft na własne zobowiązania. Tak czy inaczej, przychylność obu wspaniałych odpowiedzi.
Możesz to zrobić dość łatwo bez git rebase
lub git merge --squash
. W tym przykładzie zgniecimy 3 ostatnie zatwierdzenia.
Jeśli chcesz napisać nowy komunikat zatwierdzenia od zera, wystarczy:
git reset --soft HEAD~3 &&
git commit
Jeśli chcesz rozpocząć edycję nowego komunikatu zatwierdzenia z konkatenacją istniejących komunikatów zatwierdzenia (tj. Podobnie jak w przypadku git rebase -i
listy instrukcji pick / squash / squash /… / squash ), musisz wyodrębnić te wiadomości i przekazać je do git commit
:
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
Obie te metody zgniatają ostatnie trzy zatwierdzenia w jeden nowy zatwierdzenie w ten sam sposób. Miękki reset powoduje ponowne skierowanie HEAD do ostatniego zatwierdzenia, którego nie chcesz zgnieść. Miękki reset nie dotyka ani indeksu, ani drzewa roboczego, pozostawiając indeks w pożądanym stanie dla nowego zatwierdzenia (tzn. Ma już wszystkie zmiany względem zatwierdzeń, które zamierzasz „wyrzucić”).
git rebase --squash-recent
, a nawet git commit --amend-many
.
branch@{upstream}
(lub tylko @{upstream}
dla bieżącego oddziału; w obu przypadkach ostatnia część może być skrócona @{u}
; zobacz gitrevisions ). To może różnić się od twojego „ostatniego wciśnięcia zatwierdzenia” (np. Jeśli ktoś inny nacisnął coś, co zbudowało na twoim ostatnim pushie, a potem to pobrałeś), ale wydaje się, że może być blisko tego, czego chcesz.
push -f
ale poza tym było cudowne, dzięki.
git push --force
później, aby zabrał zatwierdzenie
Możesz użyć git merge --squash
do tego, który jest nieco bardziej elegancki niż git rebase -i
. Załóżmy, że jesteś mistrzem i chcesz zmiażdżyć ostatnie 12 zmian w jednym.
OSTRZEŻENIE: Najpierw upewnij się, że wykonałeś pracę - sprawdź, czy git status
jest czysta (ponieważ git reset --hard
odrzuci zmiany etapowe i nieetapowe)
Następnie:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12
# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}
# Commit those squashed changes. The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
Dokumentacjagit merge
opisuje --squash
opcję w sposób bardziej szczegółowy.
Aktualizacja: jedyną prawdziwą przewagą tej metody nad prostotą git reset --soft HEAD~12 && git commit
sugerowaną przez Chrisa Johnsena w jego odpowiedzi jest to, że komunikat zatwierdzenia jest wypełniany z każdą wiadomością zatwierdzenia, którą zgniatasz.
git rebase -i
, ale nie podajesz powodu dlaczego. Wstępnie -1 to, ponieważ wydaje mi się, że w rzeczywistości jest odwrotnie i jest to hack; czy nie wykonujesz więcej poleceń, niż jest to konieczne tylko po to, aby zmusić się git merge
do wykonania jednej z rzeczy, które git rebase
są specjalnie zaprojektowane?
git merge --squash
jest również łatwiejsze w użyciu w skrypcie. Zasadniczo powodem było to, że wcale nie potrzebujesz do tego „interaktywności” git rebase -i
.
git merge --squash
rzadziej wywołuje konflikty scalania w obliczu ruchów / usuwania / zmian nazw w porównaniu do zmiany bazy, szczególnie jeśli łączysz się z lokalnym oddziałem. (zrzeczenie się: na podstawie tylko jednego doświadczenia, popraw mnie, jeśli nie jest to prawdą w ogólnym przypadku!)
HEAD@{1}
aby po prostu być bezpiecznym, np. Gdy przepływ pracy jest przerywany na godzinę z powodu przerwy w dostawie prądu itp.
git reset
Jeśli to możliwe, zalecam unikanie - szczególnie dla nowicjuszy Git. Chyba że naprawdę potrzebujesz zautomatyzować proces oparty na wielu zatwierdzeniach, istnieje mniej egzotyczny sposób ...
git merge --squash (working branch name)
git commit
Komunikat zatwierdzenia zostanie wstępnie wypełniony na podstawie squasha.
gitk
celu oznaczenia linii kodu, który zgniatasz, a także oznaczenia podstawy, na której chcesz zgnieść. W normalnym przypadku obie te etykiety już będą istnieć, więc krok (1) można pominąć.
git branch your-feature && git reset --hard HEAD~N
najwygodniejszy sposób. Wymaga to jednak ponownego uruchomienia git, czego ta odpowiedź próbowała uniknąć.
Na podstawie odpowiedzi na Chrisa Johnsen ,
Dodaj globalny alias „squash” z bash: (lub Git Bash w systemie Windows)
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
... lub za pomocą wiersza polecenia systemu Windows:
git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Twój ~/.gitconfig
powinna zawierać ten alias:
[alias]
squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Stosowanie:
git squash N
... Który automatycznie zgniata ostatnie N
zatwierdzenia włącznie.
Uwaga: Wynikowy komunikat zatwierdzenia jest kombinacją wszystkich zgniecionych zatwierdzeń, w kolejności. Jeśli nie jesteś zadowolony z tego, zawsze możesz git commit --amend
go zmodyfikować ręcznie. (Lub edytuj alias zgodnie ze swoimi upodobaniami).
git squash -m "New summary."
i N
ustalić automatycznie jako liczbę nieprzypisanych zatwierdzeń.
git commit --amend
do dalszej zmiany wiadomości, ale ten alias pozwala na dobry początek tego, co powinno być w komunikacie zatwierdzenia.
Dzięki temu przydatnemu wpisowi na blogu odkryłem, że możesz użyć tego polecenia, aby zgnieść 3 ostatnie zatwierdzenia:
git rebase -i HEAD~3
Jest to przydatne, ponieważ działa nawet wtedy, gdy jesteś w lokalnym oddziale bez informacji o śledzeniu / zdalnym repo.
Polecenie otworzy interaktywny edytor bazy, który następnie pozwala na zmianę kolejności, squash, przeredagowanie itp. Zgodnie z normą.
Za pomocą interaktywnego edytora bazy danych:
Interaktywny edytor bazy danych pokazuje trzy ostatnie zatwierdzenia. To ograniczenie zostało określone przez HEAD~3
uruchomienie polecenia git rebase -i HEAD~3
.
Ostatnie zatwierdzenie, HEAD
jest wyświetlane jako pierwsze w wierszu 1. Wiersze rozpoczynające się od a #
to komentarze / dokumentacja.
Wyświetlana dokumentacja jest dość przejrzysta. W dowolnym wierszu możesz zmienić polecenie z pick
na dowolnie wybrane.
Wolę używać polecenia, fixup
ponieważ to „zgniata” zmiany zatwierdzenia do zatwierdzenia w wierszu powyżej i odrzuca komunikat zatwierdzenia.
Ponieważ zatwierdzenie w wierszu 1 jest HEAD
, w większości przypadków pozostawiłbyś to jako pick
. Nie można użyć squash
lub, fixup
ponieważ nie ma innego zatwierdzenia do zgniecenia.
Możesz także zmienić kolejność zatwierdzeń. Pozwala to zgnieść lub naprawić zatwierdzenia, które nie sąsiadują chronologicznie.
Praktyczny przykład na co dzień
Niedawno wprowadziłem nową funkcję. Od tego czasu wprowadziłem dwie poprawki błędów. Ale teraz odkryłem błąd (a może po prostu błąd pisowni) w nowej funkcji, którą popełniłem. Jak denerwujące! Nie chcę, aby nowe zatwierdzenie zanieczyszczało moją historię zatwierdzeń!
Pierwszą rzeczą, którą robię, jest naprawienie błędu i dokonanie nowego zatwierdzenia z komentarzem squash this into my new feature!
.
Następnie uruchamiam git log
lub gitk
otrzymuję zatwierdzenie SHA nowej funkcji (w tym przypadku 1ff9460
).
Następnie uruchamiam interaktywny edytor bazy danych git rebase -i 1ff9460~
. ~
Po commit SHA mówi edytor zawierać że popełnić w edytorze.
Następnie przesuwam zatwierdzenie zawierające fix ( fe7f1e0
) do poniżej zatwierdzenia funkcji i zmieniam pick
na fixup
.
Po zamknięciu edytora poprawka zostanie zgnieciona w funkcji zatwierdzania funkcji, a moja historia zmian będzie wyglądać ładnie i czysto!
Działa to dobrze, gdy wszystkie zatwierdzenia są lokalne, ale jeśli spróbujesz zmienić jakiekolwiek zatwierdzenia już przekazane do pilota, możesz naprawdę powodować problemy dla innych deweloperów, którzy sprawdzili ten sam oddział!
pick
w wierszu 1. Jeśli wybierzesz squash
lub fixup
dla zatwierdzenia w wierszu 1, git wyświetli komunikat „błąd: nie można„ naprawić ”bez wcześniejszego zatwierdzenia”. Następnie pojawi się opcja naprawy: „Możesz to naprawić za pomocą„ git rebase --edit-todo ”, a następnie uruchomić„ git rebase --continue ”.” lub możesz po prostu przerwać i zacząć od nowa: „Lub możesz przerwać rebase za pomocą„ git rebase --abort ”.”.
Jeśli używasz TortoiseGit, możesz użyć funkcji Combine to one commit
:
Show Log
Combine to one commit
z menu kontekstowegoTa funkcja automatycznie wykonuje wszystkie niezbędne kroki pojedynczego git. Niestety dostępne tylko dla systemu Windows.
Aby to zrobić, możesz użyć następującego polecenia git.
git rebase -i HEAD~n
n (= 4 tutaj) to liczba ostatniego zatwierdzenia. Następnie masz następujące opcje,
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
Zaktualizuj jak poniżej pick
jednego zatwierdzenia, a squash
pozostałe do najnowszego,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
Aby uzyskać szczegółowe informacje, kliknij link
Na podstawie tego artykułu uznałem tę metodę za łatwiejszą w moim przypadku użycia.
Moja gałąź „dev” wyprzedziła „origin / dev” o 96 commits (więc te commity nie zostały jeszcze wypchnięte do pilota).
Chciałem zmiażdżyć te rewizje w jeden przed wprowadzeniem zmiany. Wolę zresetować gałąź do stanu „origin / dev” (spowoduje to pozostawienie wszystkich zmian z 96 commits bez scen), a następnie zatwierdzić zmiany od razu:
git reset origin/dev
git add --all
git commit -m 'my commit message'
W gałęzi, w której chcesz połączyć zatwierdzenia, uruchom:
git rebase -i HEAD~(n number of commits back to review)
przykład:
git rebase -i HEAD~1
Spowoduje to otwarcie edytora tekstu i musisz przełączyć „pick” przed każdym zatwierdzeniem na „squash”, jeśli chcesz, aby te commity zostały połączone. Z dokumentacji:
Na przykład, jeśli chcesz scalić wszystkie zatwierdzenia w jeden, „pick” jest pierwszym dokonanym zatwierdzeniem, a wszystkie przyszłe (umieszczone poniżej pierwszego) powinny być ustawione na „squash”. Jeśli używasz vima, użyj : xw trybie wstawiania, aby zapisać i wyjść z edytora.
Następnie, aby kontynuować rebase:
git rebase --continue
Więcej informacji o tym i innych sposobach przepisywania historii zmian znajdziesz w tym pomocnym poście
--continue
i vim :x
.
git add
poprawnej konfiguracji w plikach używasz git rebase --continue
do przejścia do następnego zatwierdzenia i rozpoczęcia scalania. :x
to jedno polecenie, które zapisze zmiany pliku podczas korzystania z vima zobacz to
Odpowiedź na anomie jest dobra, ale czułem się niepewnie, więc postanowiłem dodać kilka zrzutów ekranu.
Zobacz, gdzie jesteś git log
. Co najważniejsze, znajdź skrót zatwierdzenia pierwszego zatwierdzenia, którego nie chcesz zgnieść. Więc tylko:
Wykonaj git rebase -i [your hash]
w moim przypadku:
$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d
W moim przypadku chcę zmiażdżyć wszystko przy zatwierdzeniu, które było po raz pierwszy. Kolejność jest od początku do końca, więc dokładnie w drugą stronę git log
. W moim przypadku chcę:
Jeśli wybrałeś tylko jedno zatwierdzenie, a resztę zmiażdżyłeś, możesz dostosować jedną wiadomość zatwierdzenia:
Otóż to. Po zapisaniu tego ( :wq
), gotowe. Spójrz na to z git log
.
git log
1) Zidentyfikuj krótki skrót zatwierdzenia
# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....
Tutaj nawet git log --oneline
można go użyć do uzyskania krótkiego skrótu.
2) Jeśli chcesz zgnieść (scalić) ostatnie dwa zatwierdzenia
# git rebase -i deab3412
3) Otwiera nano
edytor do łączenia. I wygląda jak poniżej
....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....
4) Zmiana nazwy słowo pick
do squash
których jest obecny przed abcd1234
. Po zmianie nazwy powinno to wyglądać jak poniżej.
....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....
5) Teraz zapisz i zamknij nano
edytor. Naciśnij ctrl + o
i naciśnij, Enter
aby zapisać. A następnie naciśnij, ctrl + x
aby wyjść z edytora.
6) Następnie nano
ponownie otwiera się edytor do aktualizacji komentarzy, w razie potrzeby zaktualizuj go.
7) Teraz jest pomyślnie zgnieciony, możesz go zweryfikować, sprawdzając dzienniki.
# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....
8) Teraz naciśnij przycisk repo. Uwaga, aby dodać +
znak przed nazwą oddziału. Oznacza to wymuszone pchanie.
# git push origin +master
Uwaga: Jest to oparte na użyciu git na ubuntu
powłoce. Jeśli używasz innego systemu operacyjnego ( Windows
lub Mac
), powyższe polecenia są takie same, z wyjątkiem edytora. Możesz dostać innego edytora.
git add <files>
--fixup
opcji i OLDCOMMIT
powinno być to, na którym musimy scalić (zgnieść) to zatwierdzenie.git commit --fixup=OLDCOMMIT
Teraz tworzy nowe zatwierdzenie na HEAD za pomocą fixup1 <OLDCOMMIT_MSG>
.
OLDCOMMIT
.git rebase --interactive --autosquash OLDCOMMIT^
Tutaj ^
oznacza poprzedni zobowiązać się OLDCOMMIT
. To rebase
polecenie otwiera interaktywne okno w edytorze (vim lub nano), w którym nie musimy nic robić, wystarczy zapisać i wyjście jest wystarczające. Ponieważ opcja przekazana do tego spowoduje automatyczne przeniesienie ostatniego zatwierdzenia do następnego zatwierdzenia i zmianę operacji na fixup
(równoważne squashowi). Następnie rebase kontynuuje i kończy.
--amend
można użyć środków z git-commit
. # git log --pretty=oneline --abbrev-commit
cdababcd Fix issue B
deab3412 Fix issue A
....
# git add <files> # New changes
# git commit --amend
# git log --pretty=oneline --abbrev-commit
1d4ab2e1 Fix issue B
deab3412 Fix issue A
....
Tutaj --amend
scala nowe zmiany do ostatniego zatwierdzenia cdababcd
i generuje nowy identyfikator zatwierdzenia1d4ab2e1
Aby zmiażdżyć ostatnie 10 zmian w jednym zatwierdzeniu:
git reset --soft HEAD~10 && git commit -m "squashed commit"
Jeśli chcesz również zaktualizować gałąź zdalną za pomocą zgniatanego zatwierdzenia:
git push -f
Jeśli znajdujesz się na zdalnej gałęzi (nazywanej feature-branch
) sklonowanej ze Złotego repozytorium ( golden_repo_name
), oto technika zgniatania twoich commits w jeden:
Sprawdź złote repozytorium
git checkout golden_repo_name
Utwórz z niego nową gałąź (złote repozytorium) w następujący sposób
git checkout -b dev-branch
Squash łączy się z lokalnym oddziałem, który już masz
git merge --squash feature-branch
Zatwierdź zmiany (będzie to jedyne zatwierdzenie, które wejdzie w gałąź programistów)
git commit -m "My feature complete"
Wciśnij gałąź do lokalnego repozytorium
git push origin dev-branch
Co może być naprawdę wygodne:
Znajdź, na przykład, skrót zatwierdzenia, który chcesz zgnieść d43e15
.
Teraz użyj
git reset d43e15
git commit -am 'new commit name'
To kludgy super-duper, ale w pewien fajny sposób, więc po prostu wrzucę to na pierścień:
GIT_EDITOR='f() { if [ "$(basename $1)" = "git-rebase-todo" ]; then sed -i "2,\$s/pick/squash/" $1; else vim $1; fi }; f' git rebase -i foo~5 foo
Tłumaczenie: podaj nowy „edytor” dla git, jeśli nazwa pliku do edycji to git-rebase-todo
(interaktywny monit rebase), zmienia wszystko oprócz pierwszego „wybierz” na „squash”, a w przeciwnym razie odradza vim - tak, że gdy pojawi się monit aby edytować komunikat zgniatanego zatwierdzenia, otrzymujesz vim. (I oczywiście zgniatałem ostatnie pięć zmian w gałęzi foo, ale możesz to zmienić, jak chcesz.)
Prawdopodobnie zrobiłbym to, co zasugerował Mark Longair .
Jeśli chcesz podzielić każde zatwierdzenie na jedno zatwierdzenie (np. Podczas publicznego publikowania projektu po raz pierwszy), spróbuj:
git checkout --orphan <new-branch>
git commit
Myślę, że najłatwiejszym sposobem jest zrobienie z gałęzi nowego oddziału i scalenie - potknięcie gałęzi funkcji.
git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch
Następnie wszystkie zmiany są gotowe do zatwierdzenia.
Prosty jednowierszowy, który zawsze działa, biorąc pod uwagę, że aktualnie znajdujesz się w gałęzi, którą chcesz zgnieść, master jest gałęzią, z której pochodzi, a najnowsze zatwierdzenie zawiera komunikat zatwierdzenia i autora, którego chcesz użyć:
git reset --soft $(git merge-base HEAD master) && git commit --reuse-message=HEAD@{1}
jeśli na przykład chcesz zgnieść ostatnie 3 zatwierdzenia do pojedynczego zatwierdzenia w oddziale (zdalne repozytorium) na przykład: https://bitbucket.org
To co zrobiłem jest
(MASTER)
Fleetwood Mac Fritz
║ ║
Add Danny Lindsey Stevie
Kirwan Buckingham Nicks
║ ╚═══╦══════╝
Add Christine ║
Perfect Buckingham
║ Nicks
LA1974══════════╝
║
║
Bill <══════ YOU ARE EDITING HERE
Clinton (CHECKED OUT, CURRENT WORKING DIRECTORY)
W tej bardzo skróconej historii repozytorium https://github.com/fleetwood-mac/band-history otworzyłeś prośbę o połączenie w celu zatwierdzenia Billa Clintona z pierwotnym ( MASTER
) zatwierdzeniem Fleetwood Mac.
Otworzyłeś żądanie ściągnięcia i na GitHub widzisz to:
Cztery zobowiązania:
Myśląc, że nikt nigdy nie chciałby przeczytać pełnej historii repozytorium. (W rzeczywistości istnieje repozytorium, kliknij powyższy link!) Decydujesz się zmiażdżyć te zmiany. Więc idź i biegnij git reset --soft HEAD~4 && git commit
. To tygit push --force
przejdź na GitHub, aby wyczyścić swój PR.
A co się stanie Właśnie dokonałeś pojedynczego zatwierdzenia, które dostało się od Fritza do Billa Clintona. Ponieważ zapomniałeś, że wczoraj pracowałeś nad wersją tego projektu Buckingham Nicks. I git log
nie pasuje do tego, co widzisz na GitHub.
git checkout
ichgit reset --soft
togit commit
który wypacza bezpośrednio od z do dogit rebase -i HEAD^^
gdzie liczba ^ to X
(w tym przypadku zmiażdż dwa ostatnie zatwierdzenia)
Oprócz innych doskonałych odpowiedzi, chciałbym dodać, jak git rebase -i
zawsze myli mnie z kolejnością zatwierdzania - starszą na nowszą lub odwrotnie? Oto mój obieg pracy:
git rebase -i HEAD~[N]
, gdzie N jest liczbą zatwierdzeń, które chcę dołączyć, zaczynając od najnowszej . Więcgit rebase -i HEAD~5
Oznaczałoby to „zgniecenie ostatnich 5 zmian w nowy”;Co powiesz na odpowiedź na pytanie związane z takim przepływem pracy?
merge --squash
po PR, ale zespół pomyślał, że to spowolni proces).Na tej stronie nie widziałem takiego przepływu pracy. (To mogą być moje oczy.) Jeśli dobrze rozumiem rebase
, wiele połączeń wymagałoby rozwiązania wielu konfliktów . Nie chcę nawet o tym myśleć!
Wydaje się to dla nas działać.
git pull master
git checkout -b new-branch
git checkout -b new-branch-temp
git checkout new-branch
git merge --squash new-branch-temp
// umieszcza wszystkie zmiany na etapiegit commit 'one message to rule them all'
git push
Uważam, że bardziej ogólnym rozwiązaniem nie jest określanie zatwierdzeń „N”, ale identyfikator gałęzi / zatwierdzenia, który chcesz zgnieść na wierzchu. Jest to mniej podatne na błędy niż liczenie zatwierdzeń do konkretnego zatwierdzenia - wystarczy podać tag bezpośrednio, a jeśli naprawdę chcesz policzyć, możesz podać HEAD ~ N.
W moim przepływie pracy uruchamiam gałąź, a moje pierwsze zatwierdzenie w tej gałęzi podsumowuje cel (tj. Zwykle to, co pcham jako „końcową” wiadomość dla funkcji do publicznego repozytorium). Więc kiedy skończę, wszystko Chcę to zrobić git squash master
wrócić do pierwszej wiadomości, a następnie jestem gotowy do wysłania.
Używam aliasu:
squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i
Spowoduje to zrzucenie historii, która jest zmiażdżona, zanim to zrobi - daje to szansę na odzyskanie poprzez pobranie starego identyfikatora zatwierdzenia z konsoli, jeśli chcesz przywrócić. (Użytkownicy systemu Solaris zauważają, że korzysta z -i
opcji GNU sed , użytkownicy komputerów Mac i Linux powinni się z tym pogodzić).
git squash master
gdy jesteśmy sprawdzani na slave. co się stanie ukryjemy konflikt?
Pytanie może być dwuznaczne, co oznacza „ostatni”.
na przykład git log --graph
generuje następujące (uproszczone):
* commit H0
|
* merge
|\
| * commit B0
| |
| * commit B1
| |
* | commit H1
| |
* | commit H2
|/
|
Następnie ostatnie zatwierdzenia według czasu to H0, scalenie, B0. Aby je zmiażdżyć, musisz zmienić bazę połączonego oddziału na zatwierdzenie H1.
Problem polega na tym, że H0 zawiera H1 i H2 (i ogólnie więcej zatwierdzeń przed scaleniem i po rozgałęzieniu), podczas gdy B0 nie. Musisz więc zarządzać zmianami przynajmniej od H0, scalania, H1, H2, B0.
Możliwe jest użycie rebase, ale w inny sposób niż w innych wymienionych odpowiedziach:
rebase -i HEAD~2
Spowoduje to wyświetlenie opcji wyboru (jak wspomniano w innych odpowiedziach):
pick B1
pick B0
pick H0
Ustaw squash zamiast pick na H0:
pick B1
pick B0
s H0
Po zapisaniu i wyjściu rebase zastosuje zatwierdzenia po H1. Oznacza to, że poprosi cię o ponowne rozwiązanie konfliktu (gdzie HEAD będzie najpierw H1, a następnie gromadzi zatwierdzenia w miarę ich stosowania).
Po zakończeniu rebase możesz wybrać wiadomość dla zgniecionych H0 i B0:
* commit squashed H0 and B0
|
* commit B1
|
* commit H1
|
* commit H2
|
PS Jeśli po prostu zresetujesz BO: (na przykład użycie reset --mixed
tego wyjaśniono bardziej szczegółowo tutaj https://stackoverflow.com/a/18690845/2405850 ):
git reset --mixed hash_of_commit_B0
git add .
git commit -m 'some commit message'
następnie zgniatasz w B0 zmiany H0, H1, H2 (całkowite utracenie zatwierdza zmiany po rozgałęzieniu i przed scaleniem.