Czy Git-svn dcommit po połączeniu w git jest niebezpieczny?

Moją motywacją do wypróbowania git-svn jest bezproblemowe łączenie i rozgałęzianie. Wtedy zauważyłem, że man Git-svn (1) mówi:

Uruchamianie git-merge lub git-pull nie jest zalecane na planowanej gałęzi do dcommit z. Subversion nie reprezentuje łączeń w żadnym rozsądną lub użyteczną modę; tak więc użytkownicy korzystający z Subversion nie widzą żadnych / align = "left" / Ponadto, jeśli połączysz lub ściągniesz z Gita branch, który jest mirrorem gałęzi SVN, dcommit może zobowiązać się do źle branch.

Czy to oznacza, że nie mogę utworzyć lokalnej gałęzi z svn / trunk( lub gałęzi), zhakować, połączyć z powrotem do svn / trunk, a następnie dcommit? Rozumiem, że użytkownicy svn zobaczą ten sam bałagan, który łączy się w svn pre 1.5.x zawsze były, ale czy są jakieś inne wady? To ostatnie zdanie też mnie martwi. Czy ludzie rutynowo robią takie rzeczy?

Author: code_dredd, 2008-10-10

6 answers

Właściwie, znalazłem jeszcze lepszy sposób z opcją --no-ff na Git merge. Cała ta technika squasha, której używałem wcześniej, nie jest już wymagana.

Mój nowy obieg pracy wygląda teraz następująco:

  • Mam gałąź "master", która jest jedyną gałąź z której dcommit i która sklonuje repozytorium SVN (-s zakładam, że masz standardowy układ SVN w repozytorium trunk/, branches/, oraz tags/):

    git svn clone [-s] <svn-url>
    
  • Pracuję na lokalnym oddziale "work" (-b tworzy oddział "praca")

    git checkout -b work
    
  • Zatwierdź lokalnie do gałęzi " work "(-s, aby podpisać wiadomość o zatwierdzeniu). W sequelu zakładam, że wykonałeś 3 lokalne commity.]}

    ...
    (work)$> git commit -s -m "msg 1"
    ...
    (work)$> git commit -s -m "msg 2"
    ...
    (work)$> git commit -s -m "msg 3"
    

Teraz chcesz dokonać commitu na serwerze SVN

  • [W końcu] Schowaj modyfikacje, których nie chcesz widzieć na serwerze SVN (często komentujesz jakiś kod w głównym pliku tylko dlatego, że chcesz przyspieszyć kompilację i skupić się na danym funkcja)

    (work)$> git stash
    
  • W przeciwieństwie do innych systemów, w których nie ma dostępu do serwera SVN, nie ma dostępu do serwera SVN.]}
    (work)$> git checkout master
    (master)$> git svn rebase
    
  • Wróć do gałęzi pracy i rebase z master

    (master)$> git checkout work
    (work)$> git rebase master
    
  • Upewnij się, że wszystko jest w porządku, na przykład:

    (work)$> git log --graph --oneline --decorate
    
  • Teraz nadszedł czas, aby połączyć wszystkie trzy commity z gałęzi "work" W "master" używając tej wspaniałej opcji --no-ff

    (work)$> git checkout master
    (master)$> git merge --no-ff work
    
  • Możesz zauważyć status dzienniki:

    (master)$> git log --graph --oneline --decorate
    * 56a779b (work, master) Merge branch 'work'
    |\  
    | * af6f7ae msg 3
    | * 8750643 msg 2
    | * 08464ae msg 1
    |/  
    * 21e20fa (git-svn) last svn commit
    
  • Teraz prawdopodobnie chcesz edytować (amend) ostatni commit dla swoich kolesi z SVN (w przeciwnym razie zobaczą tylko jeden commit z Komunikatem "Merge branch 'work'""]}

    (master)$> git commit --amend
    
  • Wreszcie commit na serwerze SVN

    (master)$> git svn dcommit
    
  • Wróć do pracy i ostatecznie Odzyskaj ukryte pliki:

    (master)$> git checkout work
    (work)$> git stash pop
    
 171
Author: Sebastien Varrette,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-31 12:35:37

Tworzenie lokalnych gałęzi jest zdecydowanie możliwe dzięki git-svn. Tak długo, jak używasz tylko lokalnych gałęzi dla siebie i nie próbujesz używać Gita do łączenia się między odgałęzieniami svn, powinieneś być w porządku.

Mam gałąź "master", której używam do śledzenia serwera svn. To jedyna gałąź, z której się wywodzę. Jeśli wykonuję jakąś pracę, tworzę gałąź tematyczną i pracuję nad nią. Kiedy chcę go popełnić, wykonuję następujące czynności:

  1. Zatwierdź wszystko do tematu branch
  2. Git svn rebase (rozwiąż wszelkie konflikty pomiędzy Twoją pracą a svn)
  3. Git checkout master
  4. Git svn rebase (to sprawia, że następny krok to szybkie scalanie, Zobacz komentarze Aarona poniżej)
  5. git merge topic_branch
  6. rozwiązywanie wszelkich konfliktów merge (nie powinno być żadnych w tym momencie)
  7. git svn dcommit

Mam też inną sytuację, w której muszę zachować pewne lokalne zmiany (do debugowania), które nigdy nie powinien być popychany do svn. W tym celu mam powyższą gałąź master, ale także gałąź o nazwie "work", w której normalnie pracuję. Gałęzie tematyczne są rozgałęzione poza pracą. Kiedy chcę tam zatwierdzić pracę, checkout master i używam cherry-pick, aby wybrać commity z gałęzi pracy, które chcę zatwierdzić W svn. Dzieje się tak dlatego, że chcę uniknąć popełnienia trzech zmian lokalnych. Następnie wykonuję polecenie z gałęzi master i zmieniam wszystko.

Warto biegać git svn dcommit -n najpierw aby upewnić się, że masz zamiar popełnić dokładnie to, co zamierzasz popełnić. W przeciwieństwie do Gita, przepisywanie historii w svn jest trudne!

Uważam, że musi być lepszy sposób scalania zmian w gałęzi tematycznej, pomijając te lokalne zmiany, niż używanie cherry-pick, więc jeśli ktoś ma jakieś pomysły, byłby mile widziany.

 49
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-22 21:32:20

Proste rozwiązanie: Usuń gałąź 'work' po połączeniu

Krótka odpowiedź: możesz używać Gita jak chcesz (zobacz poniżej prosty obieg pracy), włączając w to merge. Po prostu upewnij się, że podążasz za każdym ' git merge work' z ' Git branch-d work ', aby usunąć gałąź pracy tymczasowej.

Wyjaśnienie tła: Problem z merge / dcommit polega na tym, że ilekroć' git svn dcommit ' gałęzi, historia scalania tej gałęzi jest 'spłaszczony': git zapomina o wszystkich operacjach scalania, które przeszły do tej gałęzi: tylko zawartość pliku jest zachowana, ale fakt, że ta zawartość (częściowo) pochodzi z innej gałęzi zostaje utracony. Zobacz: dlaczego git svn dcommit traci historię zmian merge dla lokalnych gałęzi?

(uwaga: git-svn nie może wiele z tym zrobić: svn po prostu nie rozumie znacznie potężniejszych połączeń Gita. Tak więc, wewnątrz repozytorium svn ta informacja scalająca nie może być reprezentowane w jakikolwiek sposób.)

Ale to jest cały problem. Jeśli usuniesz gałąź 'work' po połączeniu z 'master branch', Twoje repozytorium git będzie w 100% czyste i będzie wyglądać dokładnie tak jak twoje repozytorium svn.

Mój workflow: 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ę w "katalogu lokalnym". Ilekroć potrzebuję aktualizacji z serwera (jak 'svn update') robię:

$> git checkout master
$> git svn rebase
Wszystkie moje prace rozwojowe wykonuję w oddzielnej gałęzi 'work', która jest tworzona w ten sposób:
$> git checkout -b work

Oczywiście, możesz utworzyć dowolną liczbę gałęzi do swojej pracy, jak chcesz i scalić i rebase między nimi, jak chcesz (po prostu usuń je, gdy skończysz z nimi - - - jak omówiono poniżej). W mojej normalnej pracy Bardzo często się angażuję:

$> git commit -am '-- finished a little piece of work'

Następny krok (Git rebase-i) jest opcjonalny - - - to tylko czyszczenie historii przed archiwizacją na svn: gdy osiągnąłem stabilny kamień milowy, którym chcę się podzielić z innymi, przepisuję historię tej' pracy ' gałęzi i czyszczę komunikaty commit (inni deweloperzy 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 commita, który jest aktywny w repozytorium svn (jak wskazuje git-svn-id). Wtedy wołam

$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb

Wystarczy wkleić sha-1 hash naszego ostatni commit svn zamiast mojego. Możesz przeczytać dokumentację z 'git help rebase' po szczegóły. Krótko mówiąc: to polecenie najpierw otwiera edytor prezentujący Twoje commity - - - - po prostu zmień 'pick' na 'squash' dla wszystkich tych commitów, które chcesz zgnieść z poprzednimi commitami. Oczywiście pierwsza linia powinna pozostać jako "pick". W ten sposób możesz skondensować swoje wiele małych commitów w jedną lub więcej znaczących jednostek. Zapisz i zamknij Edytor. Dostaniesz innego redaktora, który poprosi Cię o przepisz komunikaty dziennika zmian.

W skrócie: po zakończeniu 'code hacking' masuję swoją gałąź 'work', aż będzie wyglądała tak, jak chcę ją zaprezentować innym programistom(lub jak chcę zobaczyć pracę za kilka tygodni, kiedy przeglądam historię).

Aby wypchnąć 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 dział "praca").

Jeśli są zmiany, które mogą kolidować z nowymi zmianami "pracy", musisz je rozwiązać lokalnie, zanim będziesz mógł przesunąć nową pracę(patrz szczegóły poniżej). Następnie możemy przesunąć 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 usunięcie gałęzi, których już nie potrzebujesz (ponieważ są one już scalone z bieżącą gałęzią). Jeśli wykonasz to polecenie przez pomyłkę przed połączeniem swojego praca z gałąź 'master', otrzymasz komunikat o błędzie.

Uwaga 2: Upewnij się, że usuniesz swoją gałąź za pomocą 'Git branch-d work' pomiędzy merging i dcommit: jeśli spróbujesz usunąć gałąź po dcommit, otrzymasz komunikat o błędzie: gdy wykonasz 'Git svn dcommit', git zapomni, że Twoja gałąź została połączona z 'master'. Musisz go usunąć za pomocą 'Git branch-d work', który nie sprawdza bezpieczeństwa.

Teraz od razu tworzę nową gałąź 'pracy', aby uniknąć przypadkowe włamanie do gałęzi "master":

$> git checkout -b work
$> git branch            # show my branches:
  master
* work

Integracja twojej "pracy" ze zmianami w svn: Oto, co robię, gdy 'Git svn rebase' ujawnia, że inni zmienili repozytorium svn podczas pracy 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ą potężniejsze rozwiązania: Przedstawiony przepływ pracy jest uproszczony: używa uprawnień git tylko w każdej rundzie 'update / hack/dcommit' - - - ale pozostawia długoterminową historię projektu tak samo liniową jak svn repozytorium. Jest to ok, jeśli chcesz zacząć używać Git merges w małych pierwszych krokach w starszej wersji projektu svn.

Kiedy będziesz bardziej zaznajomiony z git merging, możesz sprawdzić inne przepływy pracy: jeśli wiesz, co robisz, możesz mieszać Git merges z svn merges (używając git-svn (lub podobnego) tylko po to, aby pomóc w svn merges?)

 33
Author: Yaakov Belch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:32:11

Odpowiedź Greg Hewgill na górze nie jest Bezpieczna! Jeśli jakieś nowe commity pojawią się w bagażniku pomiędzy dwoma "git svn rebase", scalenie nie będzie szybkie.

Można to zapewnić używając flagi "--FF-only "do git-merge, ale zazwyczaj nie uruchamiam" Git svn rebase "w gałęzi, tylko" Git rebase master " na niej (zakładając, że jest to tylko lokalna gałąź). Następnie" git merge thebranch " jest gwarantowany do przodu.

 8
Author: Marius K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-16 11:49:33

Bezpiecznym sposobem łączenia gałęzi svn w git jest użycie git merge --squash. Spowoduje to utworzenie pojedynczego commita i zatrzymanie, aby dodać wiadomość.

Załóżmy, że masz gałąź tematyczną svn, zwaną svn-branch.

git svn fetch
git checkout remotes/trunk -b big-merge
git merge --squash svn-branch

W tym momencie masz wszystkie zmiany z gałęzi svn zgniecione w jeden commit czekający w indeksie

git commit
 6
Author: luntain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-06 16:30:11

Przełącz lokalną gałąź git na master gałąź Git, a następnie dcommit i w ten sposób wygląda to tak, jakbyś zrobił wszystkie commity w sekwencji, aby ludzie z svn mogli zobaczyć to liniowo, do czego są przyzwyczajeni. Więc zakładając, że masz lokalny oddział o nazwie topic, możesz zrobić

git rebase master topic

Który następnie odtworzy Twoje commity na gałęzi master gotowej do dcommit

 5
Author: JoeyJ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-11 09:12:22