Git 2.18 (Q2 2018) znacznie poprawi tę --preserve-merge
opcję, dodając nową opcję.
„ git rebase
” Dowiedział się „ --rebase-merges
”, aby przeszczepić całą topologię popełnić wykres gdzie indziej .
(Uwaga: Git 2.22, drugi kwartał 2019 r. , Przestaje być aktualny --preserve-merge
, a Git 2.25, pierwszy kwartał 2020 r., Przestaje reklamować go w wynikach „ git rebase --help
” )
Patrz popełnienia 25cff9f , popełnienia 7543f6f , popełnienia 1131ec9 , popełnienia 7ccdf65 , popełnienia 537e7d6 , popełnienia a9be29c , popełnienia 8f6aed7 , popełnienia 1644c73 , popełnienia d1e8b01 , popełnienia 4c68e7d , popełnienia 9055e40 , popełnienia cb5206e , popełnienia a01c2a5 , popełnienia 2f6b1d1 , popełnienia bf5c057 (25 Maj 2018) autor: Johannes Schindelin ( dscho
) .
Zobacz commit f431d73 (25 kwietnia 2018 r.) Autor: Stefan Beller ( stefanbeller
) .
Zobacz zatwierdzenie 2429335 (25 kwietnia 2018 r.) Autor: Phillip Wood ( phillipwood
) .
(Połączone przez Junio C Hamano - gitster
- w commit 2c18e6a , 23 maja 2018 r.)
pull
: zaakceptuj, --rebase-merges
aby odtworzyć topologię gałęzi
Podobnie do preserve
trybu po prostu przekazującego --preserve-merges
opcję do rebase
polecenia, merges
tryb po prostu przekazuje
--rebase-merges
opcję.
Umożliwi to użytkownikom wygodne bazowanie na nietrywialnych topologiach zatwierdzania podczas pobierania nowych zatwierdzeń, bez ich spłaszczania.
git rebase
strona man ma teraz pełną sekcję poświęconą ponownej publikacji historii przy scalaniu .
Wyciąg:
Istnieją uzasadnione powody, dla których deweloper może chcieć odtworzyć zatwierdzenia scalania: aby zachować strukturę gałęzi (lub „topologię zatwierdzenia”) podczas pracy nad wieloma powiązanymi ze sobą gałęziami.
W poniższym przykładzie programista pracuje w gałęzi tematu, która refaktoryzuje sposób definiowania przycisków, oraz w innej gałęzi tematu, która używa tego refaktoryzacji do zaimplementowania przycisku „Zgłoś błąd”.
Dane wyjściowegit log --graph --format=%s -5
mogą wyglądać następująco:
* Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one
Deweloper może chcieć zmienić te zatwierdzenia na nowsze master
, zachowując topologię gałęzi, na przykład gdy oczekuje się, że pierwsza gałąź tematu zostanie zintegrowana z master
dużo wcześniejszą niż druga, powiedzmy, w celu rozwiązania konfliktów scalania ze zmianami w
DownloadButton
klasie, która dokonała to w master
.
Ta zmiana bazy może być wykonana przy użyciu --rebase-merges
opcji.
Zobacz mały przykład, patrz 1644c73 :
rebase-helper
--make-script
: wprowadź flagę, aby rozłączyć bazy
Sekwencer właśnie nauczył się nowych poleceń mających na celu odtworzenie struktury gałęzi ( podobnej w duchu do--preserve-merges
, ale o znacznie mniej zepsutym projekcie ).
Pozwólmy na rebase--helper
generowanie list czynności do wykonania z wykorzystaniem tych poleceń, uruchamianych przez nową --rebase-merges
opcję.
W przypadku topologii zatwierdzania takiej jak ta (gdzie HEAD wskazuje na C):
- A - B - C (HEAD)
\ /
D
wygenerowana lista czynności do wykonania wygląda następująco:
# branch D
pick 0123 A
label branch-point
pick 1234 D
label D
reset branch-point
pick 2345 B
merge -C 3456 D # C
Jaka jest różnica --preserve-merge
?
Commit 8f6aed7 wyjaśnia:
Dawno, dawno temu ten programista pomyślał: czy nie byłoby miło, gdyby, powiedzmy, łatki Git dla Windows na rdzeniu Git mógł być reprezentowany jako gąszcz gałęzi i zostać ponownie oparty na rdzeniu Gita, aby utrzymywać zestaw łatek do wyboru?
Pierwotna próba odpowiedzi na to była: git rebase --preserve-merges
.
Jednak eksperyment ten nigdy nie był zamierzony jako opcja interaktywna, a jego wsparcie polegało na git rebase --interactive
tym, że implementacja tego polecenia wyglądała już bardzo, bardzo znajomo: została zaprojektowana przez tę samą osobę, która zaprojektowała --preserve-merges
: naprawdę.
I przez „twoje naprawdę” autor odnosi się do siebie: Johannes Schindelin ( dscho
) , który jest głównym powodem (wraz z kilkoma innymi bohaterami - Hannes, Steffen, Sebastian, ...), że mamy Git For Windows (chociaż w ciągu dnia - 2009 - to nie było łatwe ).
Pracuje w firmie Microsoft od września 2015 r. , Co ma sens, biorąc pod uwagę, że Microsoft intensywnie korzysta z Git i potrzebuje jego usług. Trend
ten rozpoczął się w 2013 r. Wraz z TFS . Od tego czasu Microsoft zarządza największym repozytorium Git na świecie ! I od października 2018, Microsoft przejął GitHub .
Możesz zobaczyć, jak Johannes mówi w tym filmie dla Git Merge 2018 w kwietniu 2018 roku.
Jakiś czas później jakiś inny programista (patrzę na ciebie, Andreas! ;-)) zdecydował, że dobrym pomysłem --preserve-merges
byłoby połączenie go z --interactive
(z zastrzeżeniami!) I opiekunem Git (cóż, tymczasowym opiekunem Git to znaczy podczas nieobecności Junio) zgodziło się, i wtedy urok tego --preserve-merges
projektu zaczął się rozpadać dość szybko i niezbyt haniebnie.
Tutaj Jonathan mówi o Andreasie Schwabie z Suse.
Niektóre z ich dyskusji można zobaczyć w 2012 roku .
Powód? W --preserve-merges
trybie rodzice zatwierdzenia scalania (lub, w tym przypadku, dowolnego zatwierdzenia) nie zostali wyraźnie wymienieni, ale
wynikali z nazwy zatwierdzenia przekazanej do pick
polecenia .
Uniemożliwiło to na przykład zmianę kolejności zatwierdzeń .
Nie wspominając już o przenoszeniu zatwierdzeń między gałęziami lub, zabraniając bóstwa, dzieleniu gałęzi tematycznych na dwie.
Niestety, te niedociągnięcia uniemożliwiły również temu trybowi (którego pierwotnym celem było zaspokojenie potrzeb Gita dla Windows, z dodatkową nadzieją, że może być również przydatny dla innych), zaspokojenie potrzeb Gita dla Windows.
Pięć lat później, kiedy stało się naprawdę niemożliwe, aby mieć jedną nieporęczną, dużą serię łatek hodge-podge częściowo powiązanych, częściowo niezwiązanych łatek w Git dla Windows, które od czasu do czasu były bazowane na podstawowych tagach Git (zdobywając niezasłużony gniew dewelopera niefortunnej
git-remote-hg
serii, która po raz pierwszy zdezaktualizowała konkurencyjne podejście Git for Windows, ale później została porzucona bez opiekuna) była naprawdę niemożliwa do wykonania, polecenie „ Git nożyce ogrodowe ”, urodzili : skrypcie świnka poparcie w górnej części interaktywnej rebase, , które najpierw określą topologię rozgałęzień łat, które mają zostać ponownie oparte, utwórz pseudo listę rzeczy do zrobienia do dalszej edycji, przekształć wynik w prawdziwą listę rzeczy do zrobienia (intensywnie wykorzystującexec
polecenie „zaimplementuj” brakujące polecenia z listy rzeczy do zrobienia) i na koniec odtwórz serię poprawek na szczycie nowego podstawowego zatwierdzenia.
(Skrypt nożyc ogrodowych Git jest wymieniony w tej łatce w zatwierdzeniu 9055e40 )
To było w 2013
roku. Zajęło to około trzech tygodni, aby wymyślić projekt i zaimplementować go jako skrypt z drzewa. Nie trzeba dodawać, że wdrożenie wymagało kilku lat na ustabilizowanie się, a sam projekt okazał się solidny.
Dzięki tej łatce dobroć nożyc ogrodowych Git przychodzi do git
rebase -i
siebie .
Pominięcie --rebase-merges
opcji spowoduje wygenerowanie listy czynności do wykonania, którą można łatwo zrozumieć i gdzie oczywiste jest, jak zmienić kolejność zatwierdzeń .
Nowe gałęzie można wprowadzić, wstawiając label
polecenia i wywołując merge <label>
.
A gdy ten tryb stanie się stabilny i powszechnie akceptowany, możemy przestać być błędem projektowym--preserve-merges
.
Git 2.19 (III kwartał 2018 r.) Ulepsza nową --rebase-merges
opcję, umożliwiając jej działanie --exec
.
„ --exec
” Opcja „ git rebase --rebase-merges
” umieściła polecenia exec w niewłaściwych miejscach, co zostało poprawione.
Zobacz zatwierdzenie 1ace63b (09 sierpnia 2018) i zatwierdzenie f0880f7 (06 sierpnia 2018) przez Johannesa Schindelina ( dscho
) .
(Połączone przez Junio C Hamano - gitster
- w commit 750eb11 , 20 sierpnia 2018)
rebase --exec
: spraw, by to działało --rebase-merges
Chodzi o --exec
to, aby dołączyć exec
połączenie po każdym pick
.
Od czasu wprowadzenia commits fixup!
/ s quash!
pomysł ten został rozszerzony na „pick, ewentualnie po łańcuchu fixup / squash”, tzn. Exec nie byłby wstawiany między a pick
i żadną z odpowiadających mu
linii fixup
lub squash
wierszy.
Obecna implementacja używa brudny trick aby osiągnąć: zakłada, że istnieją tylko odebrać / fixup / squash polecenia, a następnie
wstawia te exec
linie przed jakimkolwiek pick
ale pierwszy, i dołącza się ostateczne.
Dzięki wygenerowanym listom zadań do wykonania git rebase --rebase-merges
, ta prosta implementacja pokazuje swoje problemy: produkuje dokładnie coś złego, gdy są label
, reset
i merge
polecenia.
Zmieńmy implementację tak, aby działała dokładnie tak, jak chcemy: poszukaj
pick
linii, pomiń wszelkie łańcuchy napraw / squash, a następnie wstaw exec
linię . Spłucz, spłucz, powtórz.
Uwaga: staramy się wstawiać przed wierszami komentarza, gdy tylko jest to możliwe, ponieważ puste zatwierdzenia są reprezentowane przez komentowane wiersze wyboru (i chcemy wstawić wiersz wykonania poprzedzającego wyboru przed taką linią, a nie później).
Będąc w tym miejscu, dodawaj również exec
wiersze po merge
poleceniach, ponieważ są podobne w duchu do pick
poleceń: dodają nowe zatwierdzenia.
Git 2.22 (drugi kwartał 2019 r.) Naprawia użycie refs / przepisanych / hierarchii do przechowywania stanów pośrednich bazy danych, co z natury sprawia, że hierarchia jest zależna od drzewa roboczego.
Zobacz zatwierdzenie b9317d5 , zatwierdzenie 90d31ff , zatwierdzenie 09e6564 (07 marca 2019) autor: Nguyễn Thái Ngọc Duy ( pclouds
) .
(Połączone przez Junio C Hamano - gitster
- w commit 917f2cd , 09 kwietnia 2019)
Upewnij się, że referencje / przepisane / są zgodne z drzewem roboczym
a9be29c (sekwencer: tworzenie odnośników wygenerowanych przez label
polecenie worktree-local, 2018-04-25, Git 2.19) dodaje refs/rewritten/
jako przestrzeń odniesienia dla drzewa roboczego.
Niestety (moje złe) jest kilka miejsc, które wymagają aktualizacji, aby upewnić się, że to naprawdę działa.
- add_per_worktree_entries_to_dir()
jest aktualizowany, aby upewnić się, że lista referencyjna wygląda na drzewie roboczym refs/rewritten/
zamiast na jednym repozytorium.
common_list[]
jest aktualizowany, dzięki czemu git_path()
zwraca poprawną lokalizację. Obejmuje to „ rev-parse --git-path
”.
Ten bałagan jest tworzony przeze mnie.
Zacząłem próbować to naprawić, wprowadzając, refs/worktree,
gdzie wszystkie referencje będą dla danego stołu roboczego bez specjalnych zabiegów.
Niefortunne ref / przepisane pojawiły się przed refs / worktree, więc to wszystko, co możemy zrobić.
Dzięki Git 2.24 (czwarty kwartał 2019 r.) git rebase --rebase-merges
Nauczył się prowadzić różne strategie łączenia i przekazywać im opcje specyficzne dla strategii.
Zobacz commit 476998d (04 września 2019) autor: Elijah Newren ( newren
) .
Zobacz popełnić e1fac53 , popełnić a63f990 , popełnić 5dcdd74 , popełnić e145d99 , popełnić 4e6023b , popełnić f67336d , popełnić a9c7107 , popełnić b8c6f24 , popełnić d51b771 , popełnić c248d32 , popełnić 8c1e240 , popełnić 5efed0e , popełnić 68b54f6 , popełnić 2e7bbac , popełnić 6180b20 , popełnić d5b581f (31 Lip 2019) przezJohannes Schindelin ( dscho
) .
(Połączone przez Junio C Hamano - gitster
- w commit 917a319 , 18 września 2019)
W Git 2.25 (Q1 2020) logika używana do rozróżnienia lokalnych referencji lokalnych i repozytorium od siebie jest stała, aby ułatwić scalenie zachowaj.
Zobacz zatwierdzenie f45f88b , zatwierdzenie c72fc40 , zatwierdzenie 8a64881 , zatwierdzenie 7cb8c92 , zatwierdzenie e536b1f (21 października 2019 r.) Autor: SZEDER Gábor ( szeder
) .
(Połączone przez Junio C Hamano - gitster
- w commit db806d7 , 10 listopada 2019)
path.c
: nie wywoływaj match
funkcji bez wartości wtrie_find()
Podpisano: SZEDER Gábor
'logs / refs' nie jest działającą ścieżką specyficzną dla drzewa, ale od czasu zatwierdzenia b9317d55a3 (Upewnij się, że refs / przepisane / jest na drzewko robocze, 2019-03-07, v2.22.0-rc0) ' git rev-parse --git-path
' zwraca fałszywą ścieżkę jeśli występuje końcowe „ /
”:
$ git -C WT/ rev-parse --git-path logs/refs --git-path logs/refs/
/home/szeder/src/git/.git/logs/refs
/home/szeder/src/git/.git/worktrees/WT/logs/refs/
Używamy trie
struktury danych, aby efektywnie decydować, czy ścieżka należy do wspólnego katalogu, czy działa specyficznie dla drzewa.
Tak się składa, że b9317d55a3 uruchomił błąd, który jest tak stary jak trie
sama implementacja, dodany w 4e09cf2acf („ path
: optymalizuj wspólne sprawdzanie katalogu”, 31.08.2015, Git v2.7.0-rc0 - scalenie wymienione w partii nr 2 ).
Zgodnie z komentarzem opisującym trie_find()
, powinien wywoływać tylko podaną funkcję dopasowania „fn” dla „/ -lub- \ 0-zakończonego przedrostka klucza, dla którego trie zawiera wartość”.
To nieprawda: istnieją trzy miejsca, w których trie_find () wywołuje funkcję dopasowania, ale w jednym z nich brakuje sprawdzenia istnienia wartości.
b9317d55a3 dodał dwa nowe klucze do trie
:
- ”
logs/refs/rewritten
i
- „
logs/refs/worktree
obok istniejącego logs/refs/bisect
”.
W rezultacie powstał trie
węzeł ze ścieżką „ logs/refs/
”, który wcześniej nie istniał i do którego nie dołączono żadnej wartości.
Zapytanie „ logs/refs/
” znajduje ten węzeł, a następnie trafia w jedno miejsce wywoływania match
funkcji, które nie sprawdza istnienia wartości, a zatem wywołuje match
funkcję z NULL
wartością as.
Gdy match
funkcja check_common()
jest wywoływana z NULL
wartością, zwraca 0, co oznacza, że żądana ścieżka nie należy do wspólnego katalogu, co ostatecznie skutkuje fałszywą ścieżką pokazaną powyżej.
Dodaj brakujący warunek, aby trie_find()
nigdy nie wywoływał funkcji dopasowania z nieistniejącą wartością.
check_common()
nie będzie już musiał sprawdzać, czy ma wartość inną niż NULL, więc usuń ten warunek.
Uważam, że nie ma innych ścieżek, które mogłyby spowodować podobny fałszywy wynik.
AFAICT jedynym innym kluczem powodującym wywołanie funkcji dopasowania z NULL
wartością jest „ co
” (z powodu klawiszy „ common
” i „ config
”).
Ponieważ jednak nie znajdują się one w katalogu należącym do wspólnego katalogu, oczekiwana jest wynikowa ścieżka specyficzna dla drzewa.
git --rebase-merges
ostatecznie zastąpi starygit --preserve-merges
. Zobacz moją odpowiedź poniżej