Bagaimana Anda mencapai skema versi numerik dengan Git?


131

Organisasi saya sedang mempertimbangkan untuk pindah dari SVN ke Git. Salah satu argumen yang menentang perpindahan adalah sebagai berikut:

Bagaimana cara kita membuat versi?

Kami memiliki distribusi SDK berdasarkan Platform NetBeans. Karena revisi SVN adalah angka sederhana, kita dapat menggunakannya untuk memperpanjang nomor versi plugin dan build SDK kami. Bagaimana kita menangani ini ketika kita pindah ke Git?

Solusi yang memungkinkan:

  • Menggunakan nomor build dari Hudson (Masalah: Anda harus memeriksa Hudson untuk menghubungkannya dengan versi Git yang sebenarnya)
  • Meningkatkan versi secara manual untuk malam dan stabil (Masalah: Kurva pembelajaran, kesalahan manusia)

Jika ada orang lain yang mengalami masalah serupa dan menyelesaikannya, kami senang mendengarnya.


3
Bisakah Anda mendapatkan server hudson (bukan jenkins ?) Anda untuk secara otomatis menambahkan gittag setelah setiap build berhasil? Ini akan memiliki keuntungan tambahan yang membuatnya benar-benar jelas gitkomit mana yang telah membangun masalah atau kegagalan pengujian, karena mereka akan tetap tidak ditandai.
Mark Booth


Sebagai catatan tambahan, Anda dapat menambahkan jumlah build ke tag dengan melacak waktu build .
Shahbaz

Tidak yakin apakah solusi yang layak, tetapi bagaimana dengan mengekspor dari git ke repo svn tepat sebelum setiap build? Kemudian hanya membangun dari repo svn - jika terpusat adalah apa yang kita inginkan, gunakan saja itu.
Jonny

Jawaban:


152

Gunakan tag untuk menandai komit dengan nomor versi:

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

Tag push upstream — ini tidak dilakukan secara default:

git push --tags

Kemudian gunakan perintah uraikan :

git describe --tags --long

Ini memberi Anda serangkaian format:

v2.5-0-gdeadbee
^    ^ ^^
|    | ||
|    | |'-- SHA of HEAD (first seven chars)
|    | '-- "g" is for git
|    '---- number of commits since last tag
|
'--------- last tag

Setuju - semestinya mudah untuk mengotomatisasi penomoran tag malam hari jika Anda membutuhkannya, dan promosi ke stabil tetap dilakukan secara manual.
berguna

20
Perbaikan kecil: git describe --long --tags --dirty --always. 'Kotor' akan memberi tahu Anda jika ada perubahan lokal saat 'uraikan' dilakukan (artinya itu tidak dapat sepenuhnya menggambarkan keadaan repo). 'Selalu' berarti Anda tidak akan mendapatkan kesalahan saat tidak ada tag. Ini akan mundur ke hanya hash komit. Jadi bisa Anda dapatkan 76001f2-dirtysebagai contoh. Jelas, melihat 'kotor' berarti seseorang mengacau.
Mike Weller

1
Bagaimana ini bisa berfungsi ketika tag dibuat terakhir . Biasanya Anda ingin membangun untuk memiliki versi berikutnya dari produk Anda. Tetapi mereka akan selalu dipaksa untuk menggunakan versi terakhir dalam kasus ini. Hanya bangunan final yang dikirimkan yang akan memiliki nomor yang sesuai.
void.pointer

@ void.pointer: Tentu, nomor versi ini menjawab pertanyaan “berdasarkan rilis mana komit ini dibuat?” bukan “rilis mana yang akan digunakan untuk komit ini?” Namun, Anda bebas menginterpretasikan tag secara berbeda. Misalnya, jika Anda memberi tag HEADsebagai v2.5, Anda bisa mengartikannya sebagai awal dari siklus rilis 2.5, lalu memberi tag v2.5-releaseatau apa pun yang Anda suka.
Jon Purdy

8
Perbaikan kecil lainnya. Jika Anda ingin memiliki tag lain juga, tetapi menggunakan tag yang bermotif khusus untuk pembuatan revisi, Anda dapat menggunakan --matchopsi seperti ini:git describe --long --tags --dirty --always --match 'v[0-9]\.[0-9]'
Alexander Amelkin

42

Ini muncul pada beberapa proyek untuk saya. Solusi terbaik yang saya miliki sejauh ini adalah menghasilkan nomor versi seperti ini:

xy <jumlah komit> .r <git-hash>

Biasanya, ini dibuat oleh sistem build kami menggunakan kombinasi beberapa file atau tag statis untuk mendapatkan angka revisi utama, git rev-list HEAD | wc -l(yang lebih cepat daripada menggunakan git log), dan git rev-parse HEAD. Alasannya adalah sebagai berikut:

  1. Kami membutuhkan kemampuan untuk membuat versi tingkat tinggi terjadi secara eksplisit (iexy)
  2. Ketika pengembangan paralel terjadi, kami harus TIDAK PERNAH menghasilkan nomor versi yang sama.
  3. Kami ingin melacak dengan mudah dari mana versi berasal.
  4. Ketika garis paralel digabungkan, kami ingin versi baru untuk menyelesaikan lebih tinggi dari salah satu cabang.

Nomor 2 tidak terlihat oleh kebanyakan orang, tetapi sangat penting, dan sangat sulit dengan kontrol sumber yang didistribusikan. SVN membantu dengan ini dengan memberi Anda satu nomor revisi. Ternyata jumlah komit sedekat yang Anda bisa dapatkan, sementara secara ajaib menyelesaikan # 4 juga. Di hadapan cabang, ini masih tidak unik, dalam hal ini kita menambahkan hash, yang juga memecahkan # 3 dengan rapi.

Sebagian besar dari ini adalah untuk mengakomodasi penyebaran melalui pip Python. Ini menjamin bahwa pip installmungkin akan sedikit aneh selama pengembangan paralel (yaitu paket dari orang-orang di cabang yang berbeda akan berbaur, tetapi dengan cara deterministik), tetapi setelah bergabung, semuanya beres. Kecuali adanya rebase atau amandemen yang terbuka, ini bekerja cukup baik untuk persyaratan di atas.

Jika Anda bertanya-tanya, kami memilih untuk meletakkan r di depan hash karena beberapa keanehan dengan bagaimana kemasan Python menangani huruf dalam nomor versi (yaitu ae kurang dari 0, yang akan menghasilkan "1.3.10.a1234" < "1.3.10" <"1.3.10.1234").


1
btw, bagaimana Anda menangani masalah ayam-telur dalam menentukan git-hash sebelum Anda memeriksanya? Apakah Anda menggunakan beberapa bentuk .gitignore atau trik lain?
kfmfe04

3
Saya tidak melakukannya. Saya tidak menggunakan hash sampai waktu pembuatan paket, yang lama setelah check-in. Bahasa yang berbeda memiliki cara berbeda untuk menyuntikkan ini. Untuk Python, saya menggunakan './setup.py egg_info -b ". $ {BUILD_VERSION}" sdist'. Untuk C dan C ++, saya mendefinisikan makro pada waktu kompilasi dengan 'CFLAGS = -D "$ {BUILD_VERSION}"'. Untuk Go, saya mendefinisikan simbol pada waktu tautan dengan 'go install -ldflags appmodule.BuildVersion "-X. $ {BUILD_VERSION}"'.
Jayson

1
Ini harus menjadi jawaban terbaik.
alvinabad

jawaban yang sangat bagus
haelix

9

Ini mungkin agak berlebihan, tetapi saya akan memberi tahu Anda bagaimana kami melakukannya.

Kami menggunakan struktur percabangan yang sangat mirip dengan ini .

Hudson membangun dari cabang "mengembangkan" kami dan meningkatkan angka mulai dari 0. Angka build unik untuk setiap proyek dan ditandai dalam kontrol versi. Alasannya adalah agar Anda dapat mengetahui dengan tepat dari mana pembangunan cabang 42 berasal, misalnya (setiap proyek dapat memiliki beberapa cabang yang dikembangkan secara paralel, karena setiap proyek dapat memiliki beberapa tim yang mengerjakan aspek berbeda dari proyek).

Ketika kami memutuskan bahwa build tertentu cukup bagus untuk dirilis, komit yang memicu build tersebut akan ditandai dengan nomor versi rilis, yang diputuskan oleh pemasaran. Ini berarti bahwa tim pengembang tidak peduli tentang nomor versi terakhir dan pemasaran bebas untuk mengacak-acak nomor versi yang dianggap sesuai. Nomor versi final dan nomor build keduanya ada dalam produk yang dirilis.

Contoh: 2.1.0 build 1337

Ini berarti, untuk rilis produk tertentu, Anda dapat mengetahui mana tim terakhir yang telah mengerjakannya dan Anda dapat meminta git untuk semua komitmen yang akan dirilis untuk mendiagnosis masalah jika perlu.


8

Versi diidentifikasi hashing hash SHA1 dari semua file di pohon direktori tersimpan pada saat checkin. Hash ini disimpan di samping hash checkin induk agar riwayat lengkap dapat dibaca.

Lihatlah proses menggunakan 'git-uraikan' dengan cara GIT-VERSION-GEN dan bagaimana Anda dapat menambahkan ini melalui proses build Anda ketika Anda menandai rilis Anda.

Berikut adalah blog yang bagus yang memberikan contoh cara mendapatkan apa yang Anda inginkan:

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


0

Jon Purdy memiliki ide yang tepat. git flowmembuat pengelolaan cabang-cabang ini menjadi mudah, juga, dan manajemen cabang merupakan argumen untuk pindah ke git.

Mari kita mulai dengan ikhtisar dasar git, karena Anda datang dari perspektif- svnke- git. Pertimbangkan githal-hal berikut:

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

Di atas, Anda bercabang masterke develop(dilambangkan dengan \), dan bercabang developke featurecabang. Kami menggabungkan cabang-cabang itu cadangan (dilambangkan dengan /), dengan komit ( -) di sepanjang cabang. (Jika tidak ada komit tetapi gabungannya adalah jalan ke kanan, ada .indikator untuk menunjukkan bahwa -komit berikutnya adalah komit berikutnya).

Cukup mudah. Bagaimana jika kami memiliki perbaikan terbaru di rilis utama kami?

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

Di atas, developbercabang dari master. Bug yang ditemukan di masterdiperbaiki dengan bercabang dari master, memperbaikinya, dan menggabungkan kembali ke master. Kami kemudian bergabung masterke dalam develop, dan kemudian developkefeature2 , yang menggulung kode baru dari hotfixcabang-cabang ini.

Saat Anda bergabung feature2kembali ke develop, riwayatnya termasuk developdengan hotfix. Demikian juga, developdigabung feature2dengan kode baru dari master, jadi penggabungan developkembali masterakan terjadi tanpa hambatan, karena didasarkan pada komit pada mastersaat itu — seolah-olah Anda telah bercabang masterpada saat itu.

Jadi, inilah cara lain untuk melakukan itu.

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

Anda 1.0 rilis mendapatkan tagged- 1.0.1, 1.0.2, 1.0.3, dan sebagainya.

Sekarang inilah triknya: Anda menemukan bug di 1.0 dan itu mempengaruhi 1.1, 1.2, dan 1.3. Apa yang kamu kerjakan?

Anda bercabang rilis rilis terbaru atau paling awal dipertahankan dan memperbaikinya. Kemudian Anda menggabungkan baru Anda hotfixcabang ke 1.3-dan dalam 1.2, 1.1dan 1.0. Jangan bercabang dari masing-masing cabang versi pemeliharaan; tidak menggabungkan 1.0ke dalam masteratau menggabungkan masterkembali ke 1.0. Ambil satu hotfixcabang dan gabungkan ke semua cabang versi Anda. Jika ada konflik, itu akan memberi tahu Anda; tinjau kode Anda untuk memastikan perubahannya benar ( git diffadalah teman Anda).

Sekarang perubahan spesifik diterapkan di mana-mana. Silsilahnya bercabang, tetapi tidak apa-apa. Itu tidak sembarangan. 1.3Beri tag pada head sebagai 1.3.17, gabungkan ke setiap fitur dalam proses yang bercabang 1.3, dan lanjutkan.

The git flowekstensi membantu mengelola pemeliharaan, fitur, dan cabang perbaikan terbaru ini untuk Anda. Setelah Anda menyelesaikan alur kerja, ini sepele dan mengeluarkan banyak masalah dari manajemen kode sumber.

Saya telah melihat ini dilakukan pada tim pemrograman, tetapi saya sendiri belum bekerja sedalam itu sebagai seorang programmer, jadi saya masih memikirkan alur kerja sehari-hari saya sendiri.


-6

Pro Git di bagian 7.2 "Atribut Git" di bagian "Kata Kunci" Ekspansi berisi contoh yang bagus tentang penggunaan filter noda & bersih untuk menghasilkan kata kunci gaya RCS. Anda dapat menggunakan teknik yang sama untuk menanamkan string versi-beberapa ke dalam kode, diformat dan dihitung sesuai dengan aturan Anda . Anda masih dapat menggunakan git describesebagai titik menatap, tetapi Anda memiliki kemungkinan untuk berubah ke bentuk yang lebih tepat dan dapatkan dari v2.5-14-feebdaed, misalnya, bersihkan 2.5.14


9
-1 untuk merusak jawaban yang baik dengan sepenuhnya tidak pantas untuk serangan hominem iklan.
Jörg W Mittag

9
Siapa bilang itu git-boys memilihmu. Bisa dengan mudah orang yang suka sedikit kesopanan .
Mark Booth

FYI, saya baru saja mengedit jawabannya.
Keith Thompson

git describemenampilkan nama tag kecuali jika --longdilewatkan atau ada komitmen sejak tag terakhir, jadi sudah benar-benar bersih. Jika Anda tidak mengubah default, itu akan memberi Anda apa yang Anda inginkan.
strcat
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.