Jak uzyskać numeryczny schemat kontroli wersji za pomocą Git?

131

Moja organizacja rozważa przejście z SVN do Git. Jeden argument przeciwko przeprowadzce jest następujący:

Jak wykonujemy wersjonowanie?

Posiadamy dystrybucję SDK opartą na platformie NetBeans. Ponieważ wersje SVN są prostymi liczbami, możemy je wykorzystać do rozszerzenia numerów wersji naszych wtyczek i kompilacji SDK. Jak sobie z tym poradzić po przejściu do Git?

Możliwe rozwiązania:

  • Używanie numeru kompilacji z Hudsona (Problem: musisz sprawdzić Hudsona, aby skorelować go z rzeczywistą wersją Gita)
  • Ręczne podniesienie wersji w nocy i stabilne (Problem: Krzywa uczenia się, błąd ludzki)

Jeśli ktoś inny napotkał podobny problem i go rozwiązał, chcielibyśmy usłyszeć, jak to zrobić.

Erlend
źródło
3
Czy możesz poprosić serwer Hudson (nie Jenkins ?) O automatyczne dodawanie gittagu po każdej udanej kompilacji? Miałoby to tę dodatkową zaletę, że wyjaśnia, które gitzatwierdzenia mają problemy z kompilacją lub testami, ponieważ pozostałyby one nieoznaczone.
Mark Booth
Na marginesie możesz dodać liczbę kompilacji do tagu, śledząc czasy kompilacji .
Shahbaz
Nie jestem pewien, czy jest to realne rozwiązanie, ale co powiesz na eksport z gita do repozytorium svn tuż przed każdą kompilacją? Następnie zbuduj z repozytorium svn - jeśli chcemy tego scentralizowanego, po prostu użyj tego.
Jonny

Odpowiedzi:

152

Użyj znaczników, aby oznaczyć zatwierdzenia numerami wersji:

git tag -a v2.5 -m 'Version 2.5'

Wciśnij tagi w górę - nie dzieje się to domyślnie:

git push --tags

Następnie użyj polecenia opisz :

git describe --tags --long

To daje ci ciąg formatu:

v2.5-0-gdeadbee
^    ^ ^^
|    | ||
|    | |'-- SHA of HEAD (first seven chars)
|    | '-- "g" is for git
|    '---- number of commits since last tag
|
'--------- last tag
Jon Purdy
źródło
Zgadzam się - jeśli zajdzie taka potrzeba, automatyzacja nocnej numeracji tagów powinna być łatwa, a awans do wersji stabilnej jest ręczny.
Bezużyteczne
20
Mała poprawa: git describe --long --tags --dirty --always. „Brudny” powie ci, czy były jakieś lokalne zmiany, kiedy „opis” zostało zrobione (co oznacza, że ​​nie może w pełni opisać stanu repo). „Zawsze” oznacza, że ​​nie pojawi się błąd, gdy nie będzie żadnych tagów. Wróci do zwykłego skrótu zatwierdzenia. Możesz więc podać 76001f2-dirtyjako przykład. Oczywiście widok „brudny” oznacza, że ​​ktoś się pomylił.
Mike Weller
1
Jak to może działać, gdy tag jest generowany jako ostatni . Zwykle chcesz, aby kompilacje miały następną wersję Twojego produktu. Ale w tym przypadku zawsze będą zmuszeni do użycia ostatniej wersji. Tylko ostateczna, dostarczona wersja będzie miała odpowiednią liczbę.
void.pointer
@ void.pointer: Jasne, ten numer wersji odpowiada na pytanie „w której wersji oparto ten zatwierdzenie?”, a nie „w jakiej wersji będzie ten zatwierdzenie?”. Jednak możesz dowolnie interpretować tagi. Na przykład, jeśli oznaczysz HEADjako v2.5, możesz równie dobrze zinterpretować to jako początek cyklu wydania 2.5, a następnie oznacz v2.5-releaselub cokolwiek zechcesz.
Jon Purdy,
8
Kolejna niewielka poprawa. Jeśli chcesz mieć także inne tagi, ale do generowania poprawek używasz specjalnie wzorzystego tagu, możesz skorzystać z takiej --matchopcji:git describe --long --tags --dirty --always --match 'v[0-9]\.[0-9]'
Alexander Amelkin
41

To dotyczy kilku projektów. Najlepszym rozwiązaniem, jakie dotychczas miałem, jest wygenerowanie numeru wersji takiego:

xy <liczba zatwierdzeń> .r <git-hash>

Zazwyczaj jest generowany przez nasz system kompilacji przy użyciu kombinacji jakiegoś statycznego pliku lub znacznika, aby uzyskać główne numery wersji git rev-list HEAD | wc -l(co było szybsze niż użycie git log), i git rev-parse HEAD. Rozumowanie było następujące:

  1. Potrzebowaliśmy możliwości jawnego tworzenia wersji na wysokim poziomie (iexy)
  2. Gdy miało miejsce równoległe opracowywanie, NIGDY nie musieliśmy generować tego samego numeru wersji.
  3. Chcieliśmy łatwo wyśledzić, skąd pochodzi wersja.
  4. Kiedy linie równoległe zostały scalone, chcieliśmy, aby nowa wersja była rozpoznawana wyżej niż jedna z gałęzi.

Numer 2 jest niewidoczny dla większości ludzi, ale jest naprawdę ważny i bardzo trudny przy rozproszonej kontroli źródła. SVN pomaga w tym, dając ci jeden numer wersji. Okazuje się, że liczba zatwierdzeń jest tak bliska, jak to tylko możliwe, jednocześnie magicznie rozwiązując # 4. W obecności rozgałęzień nadal nie jest to wyjątkowe, w którym to przypadku dodajemy skrót, który również starannie rozwiązuje # 3.

Większość z nich miała na celu wdrożenie wdrażania za pomocą pipa Pythona. To gwarantowało, pip installże być może będzie to nieco dziwne podczas równoległego programowania (tj. Pakiety od ludzi z różnych gałęzi przenikną się, ale w deterministyczny sposób), ale po połączeniu wszystko się załatwi. Pomijając obecność ujawnionego rebase lub zmiany, działało to całkiem nieźle jak na powyższe wymagania.

Jeśli się zastanawiasz, zdecydowaliśmy się umieścić r przed haszem z powodu jakiejś dziwności, w jaki sposób pakiet Python obsługuje litery w numerach wersji (tj. Ae jest mniejsze niż 0, co oznaczałoby, że „1.3.10.a1234” < „1.3.10” <„1.3.10.1234”).

Jayson
źródło
1
btw, jak poradziłeś sobie z problemem jaj kurzych polegającym na określeniu haszu git przed sprawdzeniem? Czy użyłeś jakiejś formy .gitignore lub innej sztuczki?
kfmfe04
2
Ja nie. Nie używam skrótu do czasu kompilacji pakietu, który jest długi po odprawie. Różne języki mają różne sposoby na wstrzyknięcie tego. W przypadku Pythona używam „./setup.py egg_info -b”. $ {BUILD_VERSION} „sdist”. Dla C i C ++ definiuję makro w czasie kompilacji za pomocą „CFLAGS = -D” $ {BUILD_VERSION} ””. Dla Go definiuję symbol w czasie połączenia za pomocą „go install -ldflags appmodule.BuildVersion” -X. $ {BUILD_VERSION} ””.
Jayson
1
To powinna być najlepsza odpowiedź.
alvinabad
bardzo dobra odpowiedź
haelix
8

Wersje są identyfikowane zaszyfrowane skrótami SHA1 wszystkich plików w drzewie katalogów przechowywanych podczas meldowania. Ten skrót jest przechowywany obok skrótów nadrzędnych kontroli, aby można było odczytać całą historię.

Spójrz na proces korzystania z „git-description” za pomocą GIT-VERSION-GEN i jak możesz to dodać poprzez proces kompilacji, kiedy otagujesz swoją wersję.

Oto fajny blog, który podaje przykład, jak zdobyć to, czego chcesz:

http://cd34.com/blog/programming/using-git-to-generate-an-automatic-version-number/

SoftwareCarpenter
źródło
8

To może być trochę przesada, ale dam ci znać, jak to robimy.

Używamy rozgałęzionej struktury bardzo podobnej do tej .

Hudson opiera się na naszych „rozwijających się” gałęziach i zwiększa liczby kompilacji, zaczynając od 0. Numer kompilacji jest unikalny dla każdego projektu i jest oznaczany w kontroli wersji. Powodem jest to, że można dokładnie powiedzieć, na przykład, z której wersji kompilacji deweloperskiej pochodzi 42 (każdy projekt może mieć kilka równoległych gałęzi programistycznych, ponieważ każdy projekt może mieć kilka zespołów pracujących nad różnymi aspektami projektu).

Kiedy zdecydujemy, że konkretna kompilacja jest wystarczająca do wydania, zatwierdzenie, które ją uruchomiło, jest oznaczane numerem wersji, o czym decyduje marketing. Oznacza to, że zespoły deweloperów nie dbają o ostateczny numer wersji, a marketing może swobodnie przeszukiwać numery wersji według własnego uznania. Ostateczny numer wersji i numer kompilacji są obecne w wydanym produkcie.

Przykład: wersja 2.1.0 1337

Oznacza to, że w przypadku konkretnego wydania produktu możesz określić, który zespół pracował nad tym ostatnim, i możesz zapytać git o wszystkie zatwierdzenia poprzedzające wydanie, aby w razie potrzeby zdiagnozować problem.

Carl
źródło
0

Jon Purdy ma dobry pomysł. git flowułatwia również faktyczne zarządzanie tymi oddziałami, a zarządzanie oddziałami jest argumentem przemawiającym za przejściem do git.

Zacznijmy od podstawowego podsumowania git, ponieważ przychodzisz z perspektywy svn-to- gitperspektywy. Rozważ gitnastępujące kwestie:

master--...............-.....-..............-
        \             /     /              /
         ---develop---------............../
                            \            /
                             --feature---

Powyżej rozgałęziasz mastersię develop(oznaczony przez \) i rozgałęziasz developsię na featureoddział. Scalamy te gałęzie z powrotem (oznaczone przez /), z commits ( -) wzdłuż gałęzi. (Jeśli nie ma zatwierdzenia, ale scalenie jest po prawej stronie, istnieją .wskaźniki wskazujące, że następne -jest następne zatwierdzenie).

Wystarczająco łatwe. Co jeśli mamy poprawkę w naszym głównym wydaniu?

master--...............-.....-................-...........-.........-
        \             /     /                / \         /|        /
         \           /     /                /   -hotfix-- V       /
          ---develop---------............../..............-...----
                             \            / \             V   /
                              --feature---   --feature2...----

Powyżej developrozgałęziony z master. Wykryty błąd masterzostał naprawiony przez odgałęzienie master, naprawienie go i ponowne połączenie master. Następnie połączyliśmy się masterw develop, a następnie developwfeature2 , który wprowadził nowy kod z hotfixtych gałęzi.

Po feature2ponownym połączeniu się develop, jego historia obejmuje developtakże hotfix. Podobnie developjest połączyły się feature2z nowym kodem z master, więc łączenie developz powrotem masterstanie się gładko, jak to jest w oparciu o które zobowiązują się masterw tym czasie-jak gdybyś rozgałęzionego od masterw tym momencie.

Oto inny sposób na zrobienie tego.

master--..........-........-
        \        /\       /
         ---1.0--  --1.1-- 

Twoje 1.0 uwalnia się tagged- 1.0.1, 1.0.2, 1.0.3, i tak dalej.

Oto sztuczka: znalazłeś błąd w wersji 1.0 i dotyczy on wersji 1.1, 1.2 i 1.3. Co robisz?

Odgałęziasz swoją najnowszą lub najwcześniej utrzymaną wersję i naprawiasz ją. Następnie należy połączyć swój nowy hotfixoddział w 1.3-I w 1.2, 1.1i 1.0. Nie rozgałęziaj się w każdym z oddziałów wersji konserwacji; nie łączą 1.0się masterani nie łączą z masterpowrotem 1.0. Weź jedną hotfixgałąź i połącz ją ze wszystkimi gałęziami wersji. Jeśli wystąpią konflikty, powie ci; sprawdź swój kod, aby upewnić się, że zmiany są poprawne ( git diffjest twoim przyjacielem).

Teraz ta konkretna zmiana jest stosowana wszędzie. Ród jest rozgałęziony, ale jest w porządku. To nie jest przypadkowe. Oznacz 1.3głowę jako 1.3.17, połącz ją ze wszystkimi rozwijanymi funkcjami 1.3i przejdź dalej.

git flowPrzedłużenie pomaga zarządzać tymi konserwacji, funkcji i oddziały poprawki dla Ciebie. Po wyłączeniu przepływu pracy jest to trywialne i sprawia ogromne problemy z zarządzaniem kodem źródłowym.

Widziałem to w zespołach programistycznych, ale sam nie pracowałem tak głęboko jako programista, więc sam wciąż skupiam się na codziennej pracy.

John Moser
źródło
-6

Pro Git w sekcji 7.2 „Atrybuty Git” w części „Słowo kluczowe” Dodatek zawiera ładny przykład użycia filtrów rozmazywania i czyszczenia do generowania słów kluczowych w stylu RCS. Możesz użyć tej samej techniki do osadzania niektórych ciągów znaków w kodzie, sformatowanych i obliczonych zgodnie z twoimi regułami . Nadal możesz używać git describejako punktu początkowego, ale masz możliwość przekształcenia się w bardziej odpowiednią formę i uzyskania wersji 2.5-14 feebdaed, na przykład, czyste 2.5.14

Leniwy Borsuk
źródło
9
-1 za zrujnowanie dobrej odpowiedzi z całkowicie nieuzasadnionymi atakami ad hominem.
Jörg W Mittag
9
Kto powiedział, że to głupi chłopcy cię głosowali. Mogą to być ludzie, którzy wolą odrobinę uprzejmości .
Mark Booth
Do Twojej wiadomości właśnie zredagowałem odpowiedź.
Keith Thompson
git describewypisuje nazwę znacznika, chyba że --longzostanie przekazana lub od ostatniego znacznika są zatwierdzenia, więc jest już idealnie czysta. Jeśli nie zmieniasz wartości domyślnych, dałoby to dokładnie to, czego chciałeś.
strcat