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):
$> git svn clone <svn-repository-url> <local-directory>
Cała praca odbywa się wtedy w „katalogu lokalnym”. Za każdym razem, gdy potrzebuję aktualizacji z serwera (np. „Aktualizacja svn”), robię:
$> git checkout master
$> git svn rebase
Wszystkie prace programistyczne wykonuję w osobnej gałęzi „praca”, która jest tworzona w następujący sposób:
$> git checkout -b work
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:
$> git commit -am '-- finished a little piece of work'
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ę
$> git log
i skopiuj hash sha-1 ostatniego zatwierdzenia, który znajduje się w repozytorium svn (zgodnie z identyfikatorem git-svn-id). Wtedy dzwonię
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
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ę:
$> git checkout master
$> git svn rebase
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:
$> git checkout master
$> git merge work # (1) merge your 'work' into 'master'
$> git branch -d work # (2) remove the work branch immediately after merging
$> git svn dcommit # (3) push your changes to the svn repository
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”:
$> git checkout -b work
$> git branch # show my branches:
master
* work
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':
$> git checkout master
$> git svn rebase # 'svn pull' changes
$> git checkout work # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed
$> git checkout master # try again to push my changes
$> git svn rebase # hopefully no further changes to merge
$> git merge integration # (1) merge your work with theirs
$> git branch -d work # (2) remove branches that are merged
$> git branch -d integration # (2) remove branches that are merged
$> git svn dcommit # (3) push your changes to the svn repository
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? )