Jak wyeksportować historię zmian z Mercurial lub Git do CVS?

100

Mam zamiar pracować z innymi ludźmi nad kodem z projektu, który używa cvs. Chcemy używać rozproszonego vcs do naszej pracy, a kiedy skończymy, a może raz na jakiś czas, chcemy przekazać nasz kod i całą naszą historię wersji do cvs. Nie mamy dostępu do zapisu w repozytorium cvs projektu, więc nie możemy zatwierdzać zbyt często. Jakiego narzędzia możemy użyć do wyeksportowania naszej historii zmian do CVS? Obecnie myśleliśmy o użyciu git lub mercurial, ale moglibyśmy użyć innego rozproszonego vcs, jeśli mogłoby to ułatwić eksport.

tatsuhirosatou
źródło
Kiedy mówisz „rozproszony CVS”, myślę, że masz na myśli „zniekształcony VCS” lub „DVCS”, co oznacza „rozproszony system kontroli wersji”.
Patrick McElhaney,
Mam na myśli rozproszony system kontroli wersji.
tatsuhirosatou

Odpowiedzi:

237

Na szczęście dla tych z nas, którzy wciąż są zmuszeni używać CVS, git dostarcza całkiem dobrych narzędzi do robienia dokładnie tego, co chcesz. Moje sugestie (i co robimy tutaj w $ work):

Tworzenie początkowego klonu

Służy git cvsimportdo klonowania historii wersji CVS do repozytorium git. Używam następującego wywołania:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout

Ta -Aopcja jest opcjonalna, ale pomaga sprawić, by historia wersji zaimportowana z CVS wyglądała bardziej jak git (zobacz man git-cvsimportwięcej informacji o tym, jak to jest skonfigurowane).

W zależności od rozmiaru i historii repozytorium CVS, ten pierwszy import zajmie BARDZO dużo czasu. Możesz dodać -v do powyższego polecenia, jeśli chcesz mieć pewność, że coś się dzieje.

Po zakończeniu tego procesu będziesz mieć mastergałąź, która powinna odzwierciedlać HEAD CVS (z wyjątkiem, że git cvsimportdomyślnie ignoruje ostatnie 10 minut zatwierdzeń, aby uniknąć przechwycenia zatwierdzenia, który jest w połowie ukończony). Następnie możesz użyć git logi znajomych do zbadania całej historii repozytorium, tak jakby używało git od początku.

Poprawki konfiguracji

Istnieje kilka poprawek konfiguracyjnych, które ułatwią w przyszłości przyrostowy import z CVS (a także eksport). Nie są one udokumentowane na git cvsimportstronie podręcznika, więc przypuszczam, że mogą ulec zmianie bez powiadomienia, ale FWIW:

% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT

Wszystkie te opcje można określić w wierszu poleceń, dzięki czemu można bezpiecznie pominąć ten krok.

Import przyrostowy

Kolejne git cvsimportpowinno być znacznie szybsze niż pierwsze wywołanie. Robi to jednak cvs rlogw każdym katalogu (nawet w tych, w których są tylko pliki Attic), więc może to potrwać kilka minut. Jeśli powyżej określiłeś sugerowane konfiguracje, wszystko, co musisz zrobić, to wykonać:

% git cvsimport

Jeśli nie skonfigurowałeś swoich konfiguracji, aby określić wartości domyślne, musisz określić je w wierszu poleceń:

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

Tak czy inaczej, dwie rzeczy, o których należy pamiętać:

  1. Upewnij się, że jesteś w katalogu głównym repozytorium git. Jeśli jesteś gdziekolwiek indziej, spróbuje zrobić coś nowego cvsimport, co znowu zajmie wieczność.
  2. Upewnij się, że jesteś w swoim masteroddziale, aby zmiany mogły zostać scalone (lub przeniesione) do gałęzi lokalnych / tematycznych.

Dokonywanie lokalnych zmian

W praktyce radzę zawsze wprowadzać zmiany w gałęziach i scalać je tylko masterwtedy, gdy jesteś gotowy do wyeksportowania tych zmian z powrotem do repozytorium CVS. Możesz użyć dowolnego przepływu pracy na swoich gałęziach (scalanie, ponowne bazowanie, zgniatanie itp.), Ale oczywiście obowiązują standardowe zasady ponownego bazowania: nie zmieniaj bazy, jeśli ktoś inny opierał swoje zmiany na twojej gałęzi.

Eksportowanie zmian do CVS

git cvsexportcommitKomenda pozwala na eksport pojedynczy zobowiązać się do serwera CVS. Możesz określić pojedynczy identyfikator zatwierdzenia (lub cokolwiek, co opisuje określone zatwierdzenie zgodnie z definicją w man git-rev-parse). Następnie generowany jest plik różnicowy, stosowany do pobrania CVS, a następnie (opcjonalnie) zatwierdzany do CVS przy użyciu rzeczywistego cvsklienta. Mógłbyś wyeksportować każde mikro zatwierdzenie do gałęzi tematycznych, ale generalnie lubię tworzyć zatwierdzenie scalające na aktualnym masteri eksportować to pojedyncze zatwierdzenie scalające do CVS. Kiedy eksportujesz zatwierdzenie przez scalanie, musisz powiedzieć gitowi, którego rodzica zatwierdzenia ma użyć do wygenerowania różnicy. Nie zadziała to również, jeśli scalanie było szybkim przewijaniem do przodu (zobacz sekcję „JAK DZIAŁA ŁĄCZENIE”, man git-mergeaby zapoznać się z opisem szybkiego łączenia do przodu), więc musisz użyć--no-ffpodczas łączenia. Oto przykład:

# on master
% git merge --no-ff --log -m "Optional commit message here" topic/branch/name
% git cvsexportcommit -w /path/to/cvs/checkout -u -p -c ORIG_HEAD HEAD

Możesz zobaczyć, co oznacza każda z tych opcji na stronie podręcznika man dla git-cvsexportcommit . Masz możliwość ustawienia -wopcji w konfiguracji git:

% git config cvsexportcommit.cvsdir /path/to/cvs/checkout

Jeśli łatka zawiedzie z jakiegokolwiek powodu, z mojego doświadczenia wynika, że ​​prawdopodobnie (niestety) lepiej będzie skopiować zmienione pliki ręcznie i zatwierdzić za pomocą klienta cvs. Nie powinno to jednak mieć miejsca, jeśli upewnisz się, że jesteś masterna bieżąco z CVS przed scaleniem gałęzi tematu.

Jeśli zatwierdzenie nie powiedzie się z jakiegokolwiek powodu (problemy z siecią / uprawnieniami itp.), Możesz przenieść polecenie wydrukowane na twój terminal na końcu wyjścia błędu i wykonać je w katalogu roboczym CVS. Zwykle wygląda to mniej więcej tak:

% cvs commit -F .msg file1 file2 file3 etc

Następnym razem, gdy wykonasz git cvsimport(czekając co najmniej 10 minut), powinieneś zobaczyć łatkę wyeksportowanego zatwierdzenia ponownie zaimportowaną do lokalnego repozytorium. Będą miały różne identyfikatory zatwierdzeń, ponieważ zatwierdzenie CVS będzie miało inny znacznik czasu i prawdopodobnie inną nazwę osoby zatwierdzającej (w zależności od tego, czy ustawiłeś plik autorów w swoim inicjału cvsimportpowyżej).

Klonowanie klonu CVS

Jeśli masz więcej niż jedną osobę, która musi to zrobić cvsimport, bardziej wydajne byłoby posiadanie jednego repozytorium git, które wykonuje cvsimport, a wszystkie inne repozytoria zostały utworzone jako klon. Działa to doskonale, a sklonowane repozytorium może wykonywać polecenia cvsexportcommits, tak jak opisano powyżej. Jest jednak jedno zastrzeżenie. Ze względu na sposób, w jaki zatwierdzenia CVS powracają z różnymi identyfikatorami zatwierdzeń (jak opisano powyżej), nie chcesz, aby Twoja sklonowana gałąź śledziła centralne repozytorium git. Domyślnie w ten sposób git clonekonfiguruje się repozytorium, ale można to łatwo naprawić:

% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge

Po usunięciu tych konfiguracji będziesz musiał wyraźnie powiedzieć, skąd i co należy wyciągnąć, jeśli chcesz pobrać nowe zatwierdzenia z centralnego repozytorium:

% git pull origin master

Ogólnie rzecz biorąc, stwierdziłem, że ten przepływ pracy jest całkiem łatwy w zarządzaniu, a „następna najlepsza rzecz” podczas całkowitej migracji do git nie jest praktyczna.

Brian Phillips
źródło
3
Dziękuję Ci. Pomogło mi to niezmiernie, szczególnie wskazówka dotycząca używania nie-fastforward merge w celu zebrania zmian dla CVS w jednym zatwierdzeniu.
skiphoppy
8
Dla przypomnienia, opcja -A, którą sugerujesz użyć dla git-cvsimport, jest wspomniana na stronie podręcznika jako „niezalecana ... jeśli zamierzasz później wyeksportować zmiany z powrotem do CVS za pomocą git-cvsexportcommit (1)”. W moim przypadku podoba mi się sposób, w jaki autorzy wychodzą tak, jak jest.
skiphoppy
2
Dzięki za wskazówki. Jedną z poręcznych rzeczy, które zrobiłem, jest dodanie "cvs =! Git cvsimport -k -a" pod [alias] w moim .gitconfig. To sprawia, że ​​"git cvs" będzie DTRT (ze szczytu drzewa).
bstpierre
1
Jeśli brakuje Ci git cvsimportna Debianie, spróbujapt-get install git-cvs
Tino
5
Mavricks w systemie Mac OSX całkowicie nie ma cvs i wygląda na to, że git cvsimport zależy od cvs Initialized empty Git repository in /Users/gus/projects/foo/foobar/.git/ Can't exec "cvsps": No such file or directory at /Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git-cvsimport line 777. Could not start cvsps: No such file or directory git cvsimport: fatal: cvsps reported errorWięc niestety nie pozwala to obejść braku CVS :(
Gus
22

Nie powinieneś ślepo ufać cvsimport i sprawdzać, czy zaimportowane drzewo pasuje do tego, co jest w repozytorium CVS. Zrobiłem to, udostępniając nowy projekt za pomocą wtyczki eclipse CVS i stwierdziłem, że wystąpiły niespójności.

Dwa zatwierdzenia, które zostały wykonane w czasie krótszym niż minuta z tym samym komunikatem o zatwierdzeniu (w celu przywrócenia błędnie usuniętego pliku) zostały zgrupowane w jedno duże zatwierdzenie, co spowodowało brak pliku z drzewa.

Udało mi się rozwiązać ten problem, modyfikując parametr „fuzz” na mniej niż minutę.

przykład:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout -z 15

Podsumowanie: sprawdź swoje drzewo po zaimportowaniu

shil88
źródło
3

Oprócz odpowiedzi Briana Phillipsa: istnieje również git-cvsserver, który działa jak serwer CVS, ale w rzeczywistości ma dostęp do repozytorium git ... ale ma pewne ograniczenia.

Jakub Narębski
źródło