Moją motywacją do wypróbowania git-svn jest łatwe łączenie i rozgałęzianie. Wtedy zauważyłem, że człowiek git-svn (1) mówi:
Uruchamianie git-merge lub git-pull NIE jest zalecane na gałęzi, z której planujesz dcommitować. Subversion nie reprezentuje fuzji w żaden rozsądny lub użyteczny sposób; więc użytkownicy korzystający z Subversion nie widzą żadnych wykonanych przez ciebie połączeń. Ponadto, jeśli scalisz lub ściągniesz z gałęzi git, która jest lustrzanym odbiciem gałęzi SVN, dcommit może zatwierdzić niewłaściwą gałąź.
Czy to oznacza, że nie mogę utworzyć lokalnego oddziału z svn / trunk (lub oddziału), zhakować, połączyć się z powrotem w svn / trunk, a następnie wykonać dcommit? Rozumiem, że użytkownicy svn zobaczą ten sam bałagan, jaki zawsze występował w svn pre 1.5.x, ale czy są jakieś inne wady? To ostatnie zdanie też mnie martwi. Czy ludzie rutynowo robią takie rzeczy?
--mergeinfo=<mergeinfo>
opcja, która może być w stanie przekazać informacje o scalaniu do SVN. Nie jestem pewien, jak należy go używać.Odpowiedzi:
Właściwie znalazłem jeszcze lepszy sposób dzięki
--no-ff
opcji na git merge. Cała ta technika squasha, której używałem wcześniej, nie jest już potrzebna.Mój nowy przepływ pracy wygląda teraz następująco:
Mam „master” oddział, który jest jedyną gałąź że dcommit zi że klon repozytorium SVN (
-s
Zakładam, że masz standardowy układ SVN w repozytoriumtrunk/
,branches/
itags/
):Pracuję w lokalnym oddziale „praca” (
-b
tworzy oddział „praca”)zatwierdzić lokalnie do gałęzi "work" (
-s
aby podpisać komunikat o zatwierdzeniu). Zakładam, że w sequelu wykonałeś 3 lokalne zatwierdzeniaTeraz chcesz zatwierdzić na serwerze SVN
[Ostatecznie] przechowuj modyfikacje, których nie chcesz widzieć na serwerze SVN (często komentowałeś jakiś kod w pliku głównym tylko dlatego, że chcesz przyspieszyć kompilację i skupić się na danej funkcji)
przebuduj gałąź główną za pomocą repozytorium SVN (aby zaktualizować z serwera SVN)
Wróć do gałęzi pracy i przeprowadź rebase z mistrzem
Upewnij się, że wszystko jest w porządku, na przykład:
Teraz nadszedł czas, aby połączyć wszystkie trzy zatwierdzenia z gałęzi „work” w „master”, używając tej wspaniałej
--no-ff
opcjiMożesz zauważyć stan dzienników:
Teraz prawdopodobnie chcesz edytować (
amend
) ostatnie zatwierdzenie dla twoich kolesi z SVN (w przeciwnym razie zobaczą tylko pojedyncze zatwierdzenie z komunikatem "Merge branch 'work'"Na koniec zatwierdź na serwerze SVN
Wróć do pracy i ostatecznie odzyskaj przechowywane pliki:
źródło
--no-ff
opcją, jawnie tworzysz zatwierdzenie scalające (zatwierdzenie z dwoma rodzicami) zamiast szybkiego przewijania do przodu. Aby upewnić się, że wszystkie zatwierdzenia w gałęzi śledzenia svn są zatwierdzeniami pojedynczego rodzica, wszystkie połączenia muszą być albo szybkie do przodu (--ff-only
może w tym pomóc), albo, jeśli trunk zmienił się za twoimi plecami, a--squash
, prawda?git svn dcommit
przepisuje zatwierdzenie git, które jej dajesz. Oznacza to, że tracisz drugiego rodzica, a teraz twoje repozytorium git nie ma informacji, że kiedykolwiek scaliłeś tę gałąźmaster
. Może to również spowodować niespójność katalogu roboczego.git merge --no-ff work -m "commit message"
zamiast dodatkowegogit commit --amend
krokuTworzenie lokalnych oddziałów jest zdecydowanie możliwe dzięki git-svn. Tak długo, jak używasz lokalnych oddziałów dla siebie i nie próbujesz używać git do łączenia się między gałęziami svn wyższego rzędu, powinno być dobrze.
Mam gałąź "master", której używam do śledzenia serwera svn. To jedyna gałąź, z której się zaangażowałem. Jeśli wykonuję jakąś pracę, tworzę gałąź tematyczną i pracuję nad nią. Kiedy chcę to zrobić, wykonuję następujące czynności:
Mam również inną sytuację, w której muszę zachować pewne lokalne zmiany (do debugowania), które nigdy nie powinny być przenoszone do svn. W tym celu mam powyższą gałąź główną, ale także gałąź zwaną „pracą”, w której normalnie pracuję. Gałęzie tematyczne są rozgałęzione od pracy. Kiedy chcę tam zatwierdzić pracę, wyewidencjonowuję mastera i używam cherry-pick, aby wybrać commity z gałęzi work, które chcę przekazać do svn. Dzieje się tak, ponieważ chcę uniknąć wykonywania trzech lokalnych zatwierdzeń zmian. Następnie dcommend z gałęzi głównej i przebudowuję wszystko.
Warto
git svn dcommit -n
najpierw uruchomić, aby upewnić się, że masz zamiar popełnić dokładnie to, co zamierzasz. W przeciwieństwie do gita, przepisywanie historii w svn jest trudne!Uważam, że musi istnieć lepszy sposób na scalenie zmiany w gałęzi tematycznej, pomijając te lokalne zmiany, niż przy użyciu selektora, więc jeśli ktoś ma jakieś pomysły, byłby mile widziany.
źródło
Proste rozwiązanie: Usuń gałąź 'work' po scaleniu
Krótka odpowiedź: Możesz używać git, jak chcesz (zobacz poniżej prosty przepływ pracy), w tym scalanie. Po prostu upewnij się, że podążaj za każdym poleceniem „ git merge work ” z „ git branch -d work ”, aby usunąć tymczasową gałąź pracy.
Wyjaśnienie w tle: Problem merge / dcommit polega na tym, że za każdym razem, gdy 'git svn dcommit' gałąź, historia scalania tej gałęzi jest `` spłaszczona '': git zapomina o wszystkich operacjach scalania, które przeszły do tej gałęzi: tylko zawartość pliku jest zachowywana, ale fakt, że ta treść (częściowo) pochodzi z innej konkretnej branży, jest stracony. Zobacz: Dlaczego git svn dcommit traci historię zatwierdzeń połączeń dla lokalnych oddziałów?
(Uwaga: git-svn nie może wiele na to poradzić: svn po prostu nie rozumie o wiele potężniejszych połączeń git. Tak więc w repozytorium svn te informacje o scalaniu nie mogą być w żaden sposób reprezentowane.)
Ale to jest cały problem. Jeśli usuniesz gałąź 'work' po jej scaleniu z 'gałęzią główną', twoje repozytorium git jest w 100% czyste i wygląda dokładnie tak, jak repozytorium svn.
Mój przepływ pracy: Oczywiście najpierw sklonowałem zdalne repozytorium svn do lokalnego repozytorium git (może to zająć trochę czasu):
Cała praca odbywa się wtedy w „katalogu lokalnym”. Za każdym razem, gdy potrzebuję aktualizacji z serwera (np. „Aktualizacja svn”), robię:
Wszystkie prace programistyczne wykonuję w osobnej gałęzi „praca”, która jest tworzona w następujący sposób:
Oczywiście możesz utworzyć dowolną liczbę gałęzi dla swojej pracy, a także scalać i ponownie bazować między nimi, jak chcesz (po prostu usuń je, gdy skończysz - jak omówiono poniżej). W mojej normalnej pracy bardzo często popełniam:
Kolejny krok (git rebase -i) jest opcjonalny - po prostu wyczyści historię przed zarchiwizowaniem jej na svn: Kiedy osiągnąłem stabilny kamień milowy, którym chcę się podzielić z innymi, przepisuję historię tej „pracy” rozgałęziaj i wyczyść komunikaty zmian (inni programiści nie muszą widzieć wszystkich małych kroków i błędów, które popełniłem po drodze - tylko wynik). W tym celu robię
i skopiuj hash sha-1 ostatniego zatwierdzenia, który znajduje się w repozytorium svn (zgodnie z identyfikatorem git-svn-id). Wtedy dzwonię
Po prostu wklej hash sha-1 naszego ostatniego zatwierdzenia svn zamiast mojego. Aby uzyskać szczegółowe informacje, możesz przeczytać dokumentację za pomocą polecenia „git help rebase”. W skrócie: to polecenie najpierw otwiera edytor prezentujący twoje zatwierdzenia - po prostu zmień 'pick' na 'squash' dla wszystkich tych zatwierdzeń, które chcesz zgnieść z poprzednimi zatwierdzeniami. Oczywiście pierwsza linia powinna pozostać jako „wybór”. W ten sposób możesz skondensować swoje liczne małe zmiany w jedną lub więcej znaczących jednostek. Zapisz i wyjdź z edytora. Otrzymasz inny edytor z prośbą o przepisanie komunikatów dziennika zmian.
W skrócie: po zakończeniu „hakowania kodu” masuję gałąź „praca”, aż wygląda, jak chcę ją zaprezentować innym programistom (lub jak chcę zobaczyć pracę za kilka tygodni, kiedy przeglądam historię) .
Aby wprowadzić zmiany do repozytorium svn, wykonuję:
Teraz wracamy do starej gałęzi „master”, zaktualizowanej o wszystkie zmiany, które zaszły w międzyczasie w repozytorium svn (Twoje nowe zmiany są ukryte w gałęzi „praca”).
Jeśli istnieją zmiany, które mogą kolidować z nowymi zmianami „pracy”, musisz je rozwiązać lokalnie, zanim będziesz mógł przesłać nową pracę (zobacz szczegóły poniżej). Następnie możemy przesłać nasze zmiany do svn:
Uwaga 1: Polecenie „git branch -d work” jest całkiem bezpieczne: pozwala tylko na usuwanie gałęzi, których już nie potrzebujesz (ponieważ są już włączone do twojej bieżącej gałęzi). Jeśli wykonasz to polecenie przez pomyłkę przed połączeniem pracy z gałęzią „master”, pojawi się komunikat o błędzie.
Uwaga 2: Upewnij się, że usunąłeś swoją gałąź za pomocą 'git branch -d work' między scalaniem a dcommit: Jeśli spróbujesz usunąć gałąź po dcommit, pojawi się komunikat o błędzie: Kiedy wykonujesz 'git svn dcommit', git zapomina o tym twoja gałąź została połączona z 'master'. Musisz go usunąć za pomocą 'git branch -D work', które nie wykonuje testu bezpieczeństwa.
Teraz natychmiast tworzę nową gałąź „work”, aby uniknąć przypadkowego włamania się do gałęzi „master”:
Integrowanie twojej 'pracy' ze zmianami na svn: Oto co robię, gdy 'git svn rebase' ujawnia, że inni zmienili repozytorium svn, gdy pracowałem nad moją gałęzią 'work':
Istnieją mocniejsze rozwiązania: przedstawiony przepływ pracy jest uproszczony: wykorzystuje uprawnienia git tylko w każdej rundzie „update / hack / dcommit” - ale pozostawia długoterminową historię projektu tak samo liniową, jak repozytorium svn. Jest to w porządku, jeśli chcesz po prostu zacząć używać scalania git w małych pierwszych krokach w starszym projekcie svn.
Kiedy stajesz się bardziej zaznajomieni z git scalania, nie krępuj się badać inne przepływy pracy: Jeśli wiesz, co robisz, ty może mieszać git łączy się z scala svn ( Używanie git-svn (lub podobne), żeby pomóc z svn seryjnej? )
źródło
git merge --squash work
, dlaczego tego nie robią? Widzę, jak robisz squash w gałęzi przed scaleniem, jeśli tworzysz więcej niż jeden „wybór” (powiedzmy, że masz 8 zatwierdzeń i zamieniasz każde z 4 zatwierdzeń w 1 i łączenie 2 zatwierdzeń w master). Także aktualizując gałąź 'work', robię torebase
, jest to prostsze niż tworzenie innej gałęzi dla mojego oddziału i robienieOdpowiedź Grega Hewgilla na górze nie jest bezpieczna! Jeśli jakieś nowe zatwierdzenia pojawiły się na linii głównej między dwoma "git svn rebase", scalanie nie będzie szybkie do przodu.
Można to zapewnić używając flagi "--ff-only" do git-merge, ale zwykle nie uruchamiam "git svn rebase" w gałęzi, tylko "git rebase master" (zakładając, że jest to tylko lokalna gałąź). Następnie gwarantuje się szybkie przejście do przodu „git merge thebranch”.
źródło
Bezpiecznym sposobem łączenia gałęzi svn w git jest użycie git merge --squash. Spowoduje to utworzenie pojedynczego zatwierdzenia i zatrzymanie dodawania wiadomości.
Powiedzmy, że masz gałąź tematyczną svn o nazwie svn-branch.
w tym momencie wszystkie zmiany z gałęzi svn są zgniecione w jednym zatwierdzeniu oczekującym w indeksie
źródło
Przebuduj lokalną gałąź git do głównej gałęzi git, a następnie dcommit i wygląda na to, że wykonałeś wszystkie zatwierdzenia po kolei, aby ludzie svn mogli zobaczyć to liniowo, tak jak są przyzwyczajeni. Zakładając, że masz lokalny oddział o nazwie Temat, który możesz zrobić
który następnie odegra Twoje zatwierdzenia na gałęzi głównej, gotowy do wykonania polecenia
źródło