Bagaimana Anda mengatur repositori kontrol versi Anda?

108

Pertama, saya tahu tentang ini: Bagaimana Anda mengatur repositori Subversion untuk proyek perangkat lunak internal? Selanjutnya, pertanyaan sebenarnya: Tim saya sedang merestrukturisasi repositori kami dan saya mencari petunjuk tentang cara mengaturnya. (SVN dalam kasus ini). Inilah yang kami dapatkan. Kami memiliki satu repositori, beberapa proyek, dan beberapa referensi silang svn: externals

\commonTools /*tools used in all projects. Referenced in each project with svn:externals*/
   \NUnit.v2.4.8
   \NCover.v.1.5.8
   \<other similar tools>
\commonFiles /*settings strong name keys etc.*/
   \ReSharper.settings
   \VisualStudio.settings
\trash /*each member of the team has trash for samples, experiments etc*/
   \user1
   \user2
\projects
   \Solution1 /*Single actual project (Visual Studio Solution)*/
      \trunk
         \src
             \Project1 /*Each sub-project resulting in single .dll or .exe*/
             \Project2
         \lib
         \tools
         \tests
         \Solution1.sln
      \tags
      \branches
   \Solution2
      \trunk
         \src
             \Project3 /*Each sub-project resulting in single .dll or .exe*/
             \Project1 /*Project1 from Solution1 references with svn:externals*/
         \lib
         \tools
         \tests
         \Solution2.sln
      \tags
      \branches

Untuk menghapus kosakata: Solusi berarti produk tunggal, Proyek adalah Proyek Visual Studio (yang menghasilkan satu .dll atau tunggal .exe)

Begitulah cara kami mengatur tata letak repositori. Masalah utamanya adalah, kami memiliki banyak Solusi, tetapi kami ingin membagikan Proyek di antara Solusi. Kami berpikir bahwa tidak ada gunanya benar-benar memindahkan Proyek yang dibagikan tersebut ke Solusi mereka sendiri, dan sebaliknya kami memutuskan untuk menggunakan svn: eksternal untuk berbagi Proyek di antara Solusi. Kami juga ingin menyimpan seperangkat alat umum dan pustaka pihak ketiga di satu tempat di repositori, dan mereka mereferensikannya di setiap Solusi dengan svn: eksternal.

Apa pendapat Anda tentang tata letak ini? Terutama tentang penggunaan svn: externals. Ini bukan solusi yang ideal, tetapi mempertimbangkan semua pro dan kontra, itu yang terbaik yang dapat kami pikirkan. Bagaimana ANDA melakukannya?

Krzysztof Kozmic
sumber
Apakah Anda yakin yang Anda maksud "thrash"? Atau lebih tepatnya "sampah"?
ssc

Jawaban:

92

Jika Anda mengikuti rekomendasi saya di bawah ini (saya telah bertahun-tahun), Anda akan dapat:

- letakkan setiap proyek di mana saja dalam kendali sumber, selama Anda mempertahankan struktur dari direktori akar proyek ke bawah

- bangun setiap proyek di mana saja di mesin apa pun, dengan risiko minimum dan persiapan minimum

- membangun setiap proyek sepenuhnya berdiri sendiri, selama Anda memiliki akses ke dependensi binernya (direktori "library" dan "output" lokal)

- membangun dan bekerja dengan kombinasi proyek apa pun, karena mereka independen

- membangun dan bekerja dengan banyak salinan / versi dari satu proyek, karena mereka independen

- hindari mengacaukan repositori kendali sumber Anda dengan file atau pustaka yang dihasilkan

Saya merekomendasikan (ini dagingnya):

  1. Tentukan setiap proyek untuk menghasilkan satu kiriman utama, seperti .DLL, .EXE, atau .JAR (default dengan Visual Studio).

  2. Susun setiap proyek sebagai pohon direktori dengan satu root.

  3. Buat skrip build otomatis untuk setiap project di direktori root yang akan dibuat dari awal, tanpa ketergantungan pada IDE (tetapi jangan mencegahnya untuk dibuat di IDE, jika memungkinkan).

  4. Pertimbangkan nAnt untuk proyek .NET di Windows, atau yang serupa berdasarkan OS Anda, platform target, dll.

  5. Jadikan setiap referensi skrip build project sebagai dependensi eksternalnya (pihak ketiga) dari satu direktori "library" bersama lokal, dengan setiap biner SEPENUHNYA diidentifikasi menurut versi: %DirLibraryRoot%\ComponentA-1.2.3.4.dll, %DirLibraryRoot%\ComponentB-5.6.7.8.dll.

  6. Buat setiap skrip build project memublikasikan kiriman utama ke satu direktori "output" bersama lokal: %DirOutputRoot%\ProjectA-9.10.11.12.dll, %DirOutputRoot%\ProjectB-13.14.15.16.exe.

  7. Jadikan setiap skrip build project mereferensikan dependensinya melalui jalur absolut yang dapat dikonfigurasi dan berversi lengkap (lihat di atas) di direktori "library" dan "output", DAN TANPA DI MANA LAIN.

  8. JANGAN PERNAH membiarkan proyek merujuk langsung proyek lain atau kontennya - hanya izinkan referensi ke kiriman utama di direktori "keluaran" (lihat di atas).

  9. Jadikan setiap referensi skrip build proyek sebagai alat build yang diperlukan melalui jalur absolut yang dapat dikonfigurasi dan berversi lengkap: %DirToolRoot%\ToolA\1.2.3.4, %DirToolRoot%\ToolB\5.6.7.8.

  10. Membuat setiap proyek membangun script konten sumber referensi oleh path relatif absolut ke direktori root proyek: ${project.base.dir}/src, ${project.base.dir}/tst(sintaks bervariasi oleh alat membangun).

  11. SELALU memerlukan skrip build proyek untuk mereferensikan SETIAP file atau direktori melalui jalur absolut yang dapat dikonfigurasi (di-root pada direktori yang ditentukan oleh variabel yang dapat dikonfigurasi): ${project.base.dir}/some/dirsatau ${env.Variable}/other/dir.

  12. JANGAN PERNAH mengizinkan skrip build project untuk mereferensikan APA SAJA dengan jalur relatif seperti .\some\dirs\hereatau ..\some\more\dirs, SELALU gunakan jalur absolut.

  13. JANGAN PERNAH mengizinkan skrip build project untuk mereferensikan APA SAJA menggunakan jalur absolut yang tidak memiliki direktori root yang dapat dikonfigurasi, seperti C:\some\dirs\hereatau \\server\share\more\stuff\there.

  14. Untuk setiap direktori root yang dapat dikonfigurasi yang direferensikan oleh skrip build proyek, tentukan variabel lingkungan yang akan digunakan untuk referensi tersebut.

  15. Berusaha meminimalkan jumlah variabel lingkungan yang harus Anda buat untuk mengonfigurasi setiap mesin.

  16. Di setiap mesin, buat skrip shell yang menentukan variabel lingkungan yang diperlukan, yang khusus untuk mesin ITU (dan mungkin khusus untuk pengguna itu, jika relevan).

  17. JANGAN meletakkan skrip shell konfigurasi khusus mesin ke dalam kontrol sumber; sebagai gantinya, untuk setiap proyek, lakukan salinan skrip di direktori root proyek sebagai template.

  18. WAJIB setiap skrip build project untuk memeriksa setiap variabel lingkungannya, dan batalkan dengan pesan yang bermakna jika tidak ditentukan.

  19. MEMERLUKAN setiap skrip build project untuk memeriksa setiap file executable alat build dependennya, file library eksternal, dan file pengiriman project dependen, dan batalkan dengan pesan yang berarti jika file tersebut tidak ada.

  20. TOLAK godaan untuk memasukkan file yang dihasilkan ke dalam kontrol sumber - tidak ada hasil proyek, tidak ada sumber yang dihasilkan, tidak ada dokumen yang dibuat, dll.

  21. Jika Anda menggunakan IDE, buat file kontrol proyek apa pun yang Anda bisa, dan jangan memasukkannya ke kontrol sumber (ini termasuk file proyek Visual Studio).

  22. Buat server dengan salinan resmi dari semua pustaka dan alat eksternal, untuk disalin / diinstal di workstation pengembang dan mesin build. Cadangkan, bersama dengan repositori kendali sumber Anda.

  23. Buat server integrasi berkelanjutan (buat mesin) tanpa alat pengembangan apa pun.

  24. Pertimbangkan alat untuk mengelola pustaka dan kiriman eksternal Anda, seperti Ivy (digunakan dengan Ant).

  25. JANGAN gunakan Maven - ini awalnya akan membuat Anda bahagia, dan akhirnya membuat Anda menangis.

Perhatikan bahwa tidak ada yang khusus untuk Subversion, dan sebagian besar bersifat umum untuk proyek yang ditargetkan ke OS, perangkat keras, platform, bahasa, dll. Saya memang menggunakan sedikit sintaks khusus OS dan alat, tetapi hanya untuk ilustrasi- -Saya percaya bahwa Anda akan menerjemahkan ke OS atau alat pilihan Anda.

Catatan tambahan mengenai solusi Visual Studio: jangan letakkan di kontrol sumber! Dengan pendekatan ini, Anda tidak memerlukannya sama sekali atau Anda dapat membuatnya (seperti file proyek Visual Studio). Namun, saya merasa yang terbaik adalah menyerahkan file solusi kepada pengembang individu untuk dibuat / digunakan sesuai keinginan mereka (tetapi tidak diperiksa ke kontrol sumber). Saya menyimpan Rob.slnfile di workstation saya yang menjadi referensi proyek saya saat ini. Karena proyek saya semuanya berdiri sendiri, saya dapat menambah / menghapus proyek sesuka hati (itu berarti tidak ada referensi ketergantungan berbasis proyek).

Harap jangan gunakan Subversion eksternal (atau yang serupa di alat lain), mereka anti-pola dan, oleh karena itu, tidak perlu.

Saat Anda menerapkan integrasi berkelanjutan, atau bahkan saat Anda hanya ingin mengotomatiskan proses rilis, buat skrip untuk itu. Buat satu skrip shell yang: mengambil parameter nama proyek (seperti yang tercantum dalam repositori) dan nama tag, membuat direktori sementara dalam direktori root yang dapat dikonfigurasi, memeriksa sumber untuk nama proyek dan nama tag yang diberikan (dengan membuat URL yang sesuai dalam kasus Subversion) ke direktori sementara itu, melakukan build bersih yang menjalankan pengujian dan memaket kiriman. Skrip shell ini harus bekerja pada proyek apa pun dan harus diperiksa ke dalam kontrol sumber sebagai bagian dari proyek "alat pembangunan" Anda. Server integrasi berkelanjutan Anda dapat menggunakan skrip ini sebagai fondasinya untuk membangun proyek, atau bahkan mungkin menyediakannya (tetapi Anda mungkin masih menginginkannya sendiri).

@VonC: Anda TIDAK ingin bekerja sepanjang waktu dengan "ant.jar" daripada "ant-abcdjar" setelah Anda dibakar saat skrip build rusak karena Anda tanpa sadar menjalankannya dengan versi Ant yang tidak kompatibel. Hal ini biasa terjadi antara Ant 1.6.5 dan 1.7.0. Generalisasi, Anda SELALU ingin tahu versi spesifik dari SETIAP komponen yang digunakan, termasuk platform Anda (Java ABCD) dan alat build Anda (Ant EFGH). Jika tidak, Anda pada akhirnya akan menemukan bug dan masalah BESAR pertama Anda akan melacak versi apa dari berbagai komponen Anda yang terlibat. Lebih baik menyelesaikan masalah itu di depan.

Rob Williams
sumber
6
Begitu banyak poin untuk dikritik ... cukup untuk mengatakan ini bukan resep universal! Poin 5 dan 6 khususnya adalah oh jadi salah ketika proyeknya besar dan jumlah pihak ketiga penting: Anda ingin bekerja setiap saat dengan 'ant.jar', bukan 'ant1.5.4.jar', atau produk myProduct .exe, bukan 1.3.exe
VonC
5
Namun, +1 untuk banyak poin lain yang Anda buat yang valid dan sangat memuji pengalaman Anda yang luas tentang topik tersebut.
VonC
3
Saya ingin mendengar dan berinteraksi dengan kritik Anda - setiap poin didasarkan pada penyelesaian pengalaman buruk dengan proyek besar. Misalnya, menangani masalah versi mana yang diwakili oleh Xxx.jar dan Yyy.exe, terutama ketika ada selusin salinan yang direferensikan.
Rob Williams
2
@Rob - Dapatkah Anda menguraikan tema 'antipattern eksternal' Anda? Saya telah mengangkatnya sebagai pertanyaan di sini: stackoverflow.com/questions/338824/…
Ken
3
@Makis: Anda benar, JIKA # 12 tidak seimbang dengan # 13. Setiap referensi ke file atau direktori dalam setiap proyek harus dibuat melalui jalur absolut yang dimulai dengan variabel direktori root yang dapat dikonfigurasi, misalnya $ {basedir} /sub/dir/file.txt di Ant.
Rob Williams
3

Kami telah mengatur agar hampir sama persis dengan apa yang Anda posting. Kami menggunakan bentuk umum:

\Project1
   \Development (for active dev - what you've called "Trunk", containing everything about a project)
   \Branches (For older, still-evolving supported branches of the code)
       \Version1
       \Version1.1
       \Version2
   \Documentation (For any accompanying documents that aren't version-specific

Meskipun saya kira tidak selengkap contoh Anda, ini bekerja dengan baik bagi kami dan memungkinkan kami memisahkan hal-hal. Saya suka ide setiap pengguna memiliki folder "Thrash" juga - saat ini, jenis proyek tersebut tidak berakhir di kontrol Sumber, dan saya selalu merasa bahwa mereka harus melakukannya.

SqlRyan
sumber
3
Saya terkejut Anda memiliki direktori terpisah untuk dokumen yang tidak berubah antar versi ... Saya tidak pernah merasa senang mengerjakan produk seperti itu! :)
ARKBAN
1

Mengapa semuanya ada dalam satu repositori? Mengapa tidak hanya memiliki repositori terpisah untuk setiap proyek (maksud saya "Solusi")?

Yah, setidaknya saya sudah terbiasa dengan pendekatan satu-proyek-per-repositori. Bagi saya, struktur repositori Anda tampak terlalu rumit.

Dan berapa banyak proyek yang Anda rencanakan untuk dimasukkan ke dalam satu repositori besar ini? 2? 3? 10? 100?

Dan apa yang Anda lakukan ketika Anda membatalkan pengembangan satu proyek? Hapus saja dari pohon repositori sehingga akan sulit ditemukan di masa mendatang. Atau membiarkannya tergeletak selamanya? Atau ketika Anda ingin memindahkan satu proyek ke server lain sekaligus?

Dan bagaimana dengan kekacauan dari semua nomor versi itu? Nomor versi dari satu proyek menjadi 2, 10, 11, sedangkan yang lainnya adalah 1, 3, 4, 5, 6, 7, 8, 9, 12 ...

Mungkin saya bodoh, tapi saya suka satu proyek per repositori.

Rene Saarsoo
sumber
1. Satu repositori adalah kebijakan perusahaan, tidak bisa mengubahnya. 2. Kami akan memiliki sekitar lusinan Solusi. 3. dengan nomor versi yang Anda maksud revisi? Itu bukan masalah bagi kami.
Krzysztof Kozmic
Sebuah struktur proyek yang baik harus mengabaikan struktur repositori lainnya, terutama yang berkaitan dengan satu atau banyak repositori. Silakan lihat jawaban rinci saya.
Rob Williams
1
Harap dicatat bahwa memiliki banyak repositori di banyak (kebanyakan?) Alat kontrol sumber bisa SANGAT mahal, seperti ketika Anda menerapkan keamanan.
Rob Williams
0

Saya pikir kelemahan utama dari struktur yang diusulkan adalah bahwa proyek bersama hanya akan diversi dengan solusi pertama yang mereka tambahkan (kecuali svn: eksternal lebih bagus daripada yang saya bayangkan). Misalnya, saat Anda membuat cabang untuk rilis pertama Solution2, Project1 tidak akan bercabang karena berada di Solution1. Jika Anda perlu membangun dari cabang itu di lain waktu (rilis QFE), itu akan menggunakan versi terbaru Project1 daripada versi Project1 pada saat cabang.

Untuk alasan ini, mungkin menguntungkan untuk menempatkan proyek bersama dalam satu atau beberapa solusi bersama (dan dengan demikian direktori tingkat atas dalam struktur Anda) dan kemudian mencabangnya dengan setiap rilis solusi apa pun .

C.Naga 76
sumber
Anda benar sampai batas tertentu. Tapi kita bisa mengupdate referensi jika kita mau. Dan memasukkan Proyek bersama ke dalam Solusi mereka sendiri juga tidak masuk akal. Meskipun saya ingin menemukan solusi yang lebih baik daripada svn: eksternal di semua tempat.
Krzysztof Kozmic
Apa yang Anda maksud dengan "perbarui referensi jika kami ingin"? Saya tidak melihat bagaimana Anda dapat mencabangkan Project1 (yang tampaknya diinginkan setiap kali Anda mencabangkan Solution2) tanpa mencabangkan Solution1.
C. Dragon 76
Silakan lihat jawaban rinci saya, terutama untuk TIDAK menempatkan solusi Visual Studio ke dalam kendali sumber.
Rob Williams
0

Untuk menambah masalah jalur relatif:

Saya tidak yakin ini masalahnya:
Cukup periksa Solution1 / trunk di bawah direktori bernama "Solution1", ditto untuk Solution2: tujuan 'direktori' yang sebenarnya mewakili cabang tidak terlihat setelah diimpor ke ruang kerja. Karenanya jalur relatif dimungkinkan antara 'Solution1' (sebenarnya 'Solution1 / trunk') dan 'Solution2' (Solution2 / trunk).

VonC
sumber
Ini akan sangat mudah rusak, silakan lihat jawaban rinci saya.
Rob Williams
0

RE: jalur relatif dan masalah file bersama -

Sepertinya ini spesifik svn, tapi itu bukan masalah. Satu orang lain telah menyebutkan repositori terpisah dan itu mungkin solusi terbaik yang dapat saya pikirkan dalam kasus di mana Anda memiliki proyek berbeda yang mengacu pada proyek lain yang sewenang-wenang. Dalam kasus di mana Anda tidak memiliki file bersama maka solusi OP (Serta banyak lainnya) akan berfungsi dengan baik.

Kami masih mengerjakan ini dan saya memiliki 3 upaya berbeda (klien berbeda) yang harus saya selesaikan sekarang karena saya mengambil alih pengaturan kontrol versi yang tidak ada atau buruk.

Tim
sumber
Memiliki proyek yang mereferensikan proyek lain menciptakan mimpi buruk pemeliharaan karena ketergantungan tumbuh secara eksponensial dan referensinya SANGAT rapuh. Silakan lihat jawaban rinci saya.
Rob Williams
0

Saya memiliki tata letak yang serupa, tetapi batang, cabang, tag saya sepenuhnya di bagian atas. Jadi: / trunk / main, / trunk / utils, / Branches / release /, dll.

Ini akhirnya menjadi sangat berguna ketika kami ingin mencoba sistem kontrol versi lain karena banyak alat terjemahan bekerja paling baik dengan tata letak SVN buku teks dasar.

Peter Mortensen
sumber