Tổ chức kho Git với các mô đun con lồng nhau phổ biến


50

Tôi là một fan hâm mộ lớn của các mô-đun Git . Tôi muốn có thể theo dõi một phụ thuộc cùng với phiên bản của nó, để bạn có thể quay lại phiên bản trước của dự án và có phiên bản phụ thuộc tương ứng để xây dựng an toàn và sạch sẽ. Hơn nữa, việc phát hành các thư viện của chúng tôi dưới dạng các dự án nguồn mở dễ dàng hơn vì lịch sử của các thư viện tách biệt với các ứng dụng phụ thuộc vào chúng (và chúng sẽ không được mở nguồn).

Tôi đang thiết lập quy trình làm việc cho nhiều dự án tại nơi làm việc và tôi đã tự hỏi sẽ thế nào nếu chúng ta thực hiện phương pháp này một chút cực đoan thay vì có một dự án nguyên khối. Tôi nhanh chóng nhận ra đó là một lon tiềm năng của sâu trong thực sự sử dụng sub-module.

Giả sử một cặp ứng dụng: studioplayer, và các thư viện phụ thuộc core, graphnetwork, nơi phụ thuộc như sau:

  • core là độc lập
  • graphphụ thuộc vào core(mô-đun phụ tại ./libs/core)
  • networkcorephụ thuộc vào (mô-đun phụ tại ./libs/core)
  • studiophụ thuộc vào graphnetwork(các mô-đun phụ tại ./libs/graph./libs/network)
  • playerphụ thuộc vào graphnetwork(các mô-đun phụ tại ./libs/graph./libs/network)

Giả sử rằng chúng tôi đang sử dụng CMake và mỗi dự án này đều có các bài kiểm tra đơn vị và tất cả các công việc. Mỗi dự án (bao gồm studioplayer) phải có thể được biên dịch độc lập để thực hiện các số liệu mã, kiểm tra đơn vị, v.v.

Điều này là, một đệ quy git submodule fetch, sau đó bạn có được cấu trúc thư mục sau:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/graph/
studio/libs/graph/libs/         (sub-module depth: 2)
studio/libs/graph/libs/core/
studio/libs/network/
studio/libs/network/libs/       (sub-module depth: 2)
studio/libs/network/libs/core/

Lưu ý rằng coređược nhân bản hai lần trong studiodự án. Ngoài việc lãng phí dung lượng ổ đĩa này, tôi gặp vấn đề về hệ thống xây dựng vì tôi đang xây dựng corehai lần và tôi có khả năng nhận được hai phiên bản khác nhau core.

Câu hỏi

Làm cách nào để tổ chức các mô-đun phụ để tôi có được sự phụ thuộc theo phiên bản và xây dựng độc lập mà không nhận được nhiều bản sao của các mô-đun phụ lồng nhau phổ biến?

Giải pháp có thể

Nếu phần phụ thuộc thư viện có phần gợi ý (nghĩa là trong "thời gian được biết là hoạt động với phiên bản X" hoặc "chỉ phiên bản X được hỗ trợ chính thức") và các ứng dụng hoặc thư viện phụ thuộc tiềm năng chịu trách nhiệm xây dựng với bất kỳ phiên bản nào họ thích, sau đó Tôi có thể tưởng tượng kịch bản sau đây:

  • Có hệ thống xây dựng graphnetworkcho họ biết nơi cần tìm core(ví dụ: thông qua trình biên dịch bao gồm đường dẫn). Xác định hai mục tiêu xây dựng, "độc lập" và "phụ thuộc", trong đó "độc lập" dựa trên "phụ thuộc" và thêm đường dẫn bao gồm để trỏ đến coremô đun con cục bộ .
  • Giới thiệu một phụ thuộc thêm: studiovào core. Sau đó, studioxây dựng core, đặt đường dẫn bao gồm bản sao của coremô-đun phụ, sau đó xây dựng graphnetworkở chế độ "phụ thuộc".

Cấu trúc thư mục kết quả trông như sau:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/core/
studio/libs/graph/
studio/libs/graph/libs/         (empty folder, sub-modules not fetched)
studio/libs/network/
studio/libs/network/libs/       (empty folder, sub-modules not fetched)

Tuy nhiên, điều này đòi hỏi một số phép thuật hệ thống xây dựng (tôi khá tự tin điều này có thể được thực hiện với CMake) và một chút công việc thủ công trên một phần của các bản cập nhật phiên bản (cập nhật graphcũng có thể yêu cầu cập nhật corenetworkđể có phiên bản tương thích coretrong tất cả các dự án) .

Bất kỳ suy nghĩ về điều này?


Lưu ý rằng vấn đề này không cụ thể đối với cmake: nó tồn tại cho bất kỳ hệ thống xây dựng nào, kể cả không có hệ thống! (tức là khi dự định siêu dự án chỉ cần thêm các nguồn thư viện; bao gồm các thư viện chỉ có tiêu đề)
MM

Câu trả lời:


5

Tôi đến bữa tiệc này rất muộn, nhưng câu hỏi của bạn vẫn chưa có câu trả lời hoàn chỉnh, và đó là một điểm nhấn khá nổi bật từ google.

Tôi có cùng một vấn đề với C ++ / CMake / Git / Submodules và tôi có một vấn đề tương tự với MATLAB / Git / Submodules, điều này có thêm một số điều kỳ lạ vì MATLAB không được biên dịch. Tôi đã xem qua video này gần đây, dường như đề xuất một "giải pháp". Tôi không thích giải pháp này, vì về cơ bản nó có nghĩa là vứt bỏ các mô hình con, nhưng nó loại bỏ vấn đề. Nó chỉ là như @errordeveloper khuyến nghị. Mỗi dự án không có mô hình con. Để xây dựng một dự án, tạo một siêu dự án để xây dựng nó, và bao gồm nó như một người anh em với sự phụ thuộc của nó.

Vì vậy, dự án phát triển của bạn graphcó thể trông giống như:

buildgraph/graph
buildgraph/core

và sau đó dự án của bạn cho studio có thể là:

buildstudio/studio
buildstudio/graph
buildstudio/network
buildstudio/core

Các siêu dự án chỉ là một chính CMakeLists.txtvà một loạt các mô hình con. Nhưng không có dự án nào có bất kỳ mô hình con nào.

Chi phí duy nhất tôi thấy cho phương pháp này là sự phát triển của các "siêu dự án" tầm thường chỉ dành riêng cho việc xây dựng các dự án thực sự của bạn. Và nếu ai đó nắm giữ một trong những dự án của bạn, không có cách nào dễ dàng để nói mà không tìm thấy siêu dự án, thì sự phụ thuộc của nó là gì. Điều đó có thể làm cho nó ngồi thực sự xấu xí trên Github, ví dụ.


1

Tôi cho rằng khi bạn tích hợp cả hai graphvà các networkmô hình con vào studio, bạn luôn phải có cùng một phiên bản coretại một thời điểm nhất định trong lịch sử studio. Tôi sẽ simlink studio/libs/coremô hình con vào studio/libs/{graph,network}/libs.

Cập nhật:

Tôi đã bẻ khóa nhiều kho lưu trữ với các phụ thuộc mà bạn đã nêu:

./core      <--- (v2)
./graph
./graph/libs
./graph/libs/core  <--- (v2)
./graph/.gitmodules
./network
./network/libs
./network/libs/core  <--- (v1)
./network/.gitmodules
./studio
./studio/libs
./studio/libs/graph
./studio/libs/graph/libs
./studio/libs/graph/libs/core <--- (v1)
./studio/libs/graph/.gitmodules
./studio/libs/network
./studio/libs/network/libs
./studio/libs/network/libs/core  <--- (v1)
./studio/libs/network/.gitmodules
./studio/studio
./studio/.gitmodules

v1v2là hai phiên bản khác nhau của core. graphxử lý phiên bản 2, trong khi networkcần một số công việc và bị kẹt ở phiên bản 1. Trong studio, các phiên bản nhúng cục bộ của corecả hai điểm v1để có một chương trình làm việc. Bây giờ, ngoài quan điểm xây dựng, mọi thứ đều hoạt động tốt với các mô hình con.

Bây giờ tôi có thể xóa thư mục sau:

./studio/libs/network/libs/core

Và thay thế nó bằng một liên kết tượng trưng:

./studio/libs/network/libs/core@ -> ../../graph/libs/core/

Tôi cam kết thay đổi cục bộ này và mất khả năng có hai phiên bản corebên trong riêng biệt studio, nhưng tôi chỉ xây dựng coremột lần. Khi tôi sẵn sàng nâng cấp lên v2, tôi có thể làm:

 git submodule update # (--rebase ?)

... bên trong studio / libs / mạng.


Ý tưởng liên kết tượng trưng đã vượt qua tâm trí tôi, nhưng đó không phải là giải pháp. Nếu bạn liên kết từ graph/libs/corebên ngoài, bạn không sử dụng mô hình con. Nếu bạn liên kết từ studio/libs/coremột trong các thư viện riêng của mô-đun phụ, thì bạn chọn cái nào, graphhoặc network? Hơn nữa, điều gì xảy ra khi nó sâu hơn ba lớp? Cuối cùng, những gì nếu corecó thể là một loạt các phiên bản. Không rõ ràng rằng bạn muốn liên kết với một trong hai phiên bản coređó graphnetworkđang sử dụng.
André Caron

"Bạn chọn cái nào ?" : coresẽ là một mô hình con được lấy từ corethư viện gốc , được cập nhật lên phiên bản tương thích với cả hai graphnetwork(bạn phải quyết định cái nào là tốt). Các liên kết tượng trưng sẽ được thêm vào cục bộ graphnetworkmô đun con (không tải).
coredump

1
Các liên kết tượng trưng mà bạn đề xuất để thêm vào graphnetworksẽ chỉ ra bên ngoài kho lưu trữ của riêng họ (ví dụ: một nơi khác trong studiodự án). Làm thế nào để họ biết khi nào nên sử dụng mô-đun phụ của riêng họ so với khi nào nên sử dụng liên kết tượng trưng? Có lẽ bạn nên thêm một ví dụ để thể hiện dòng suy nghĩ của bạn.
André Caron

0

Tôi sẽ làm phẳng nó xuống để có độ sâu mô-đun phụ chỉ là một và có một kho lưu trữ chứa tất cả các mô-đun dưới dạng mô-đun phụ và không có gì khác ngoài README và các tập lệnh xây dựng. Sẽ có một tập lệnh xây dựng riêng cho từng gói liên kết các phụ thuộc của nó. Nếu không, bạn có thể có một repo riêng cho một gói.


1
Tôi không chắc điều này có rõ ràng trong bài viết của mình không, nhưng tôi có nhiều ứng dụng phụ thuộc vào cùng một thư viện và tôi không muốn sao chép tập lệnh xây dựng cho các thư viện trên các ứng dụng.
André Caron

3
Bạn nên giải thích về câu trả lời của bạn để chứng minh cách nó giải quyết các vấn đề khác nhau. Tôi không rõ chính xác cách bạn liên kết các phụ thuộc được đưa ra, tùy thuộc vào ngữ cảnh, các thư viện phụ thuộc không ở cùng một vị trí.
André Caron

0

Tôi sẽ không sử dụng mô hình con.

Nó hấp dẫn, giống như đã từng là trường hợp với svn-externals. Tuy nhiên, bạn có thể chắc chắn tất cả các dự án mà bạn liên kết vẫn ở cùng một nơi trong một năm không? Còn năm thì sao?

Do đó, tôi chỉ đơn giản là sao chép tất cả các phụ thuộc cần thiết vào dự án của tôi. Điều này có nghĩa là miễn là repo của tôi hợp lệ, tôi có thể kiểm tra trạng thái chính xác.

Về cơ bản, tôi có một cấu trúc thư mục như sau:

myproject/... [sources etc]
ext/ [third-party dependencies]


e.g. ext/boost, ext/cppunit

Mặc dù điều này không tốt lắm từ góc độ không gian đĩa, tôi đánh giá cao sự đảm bảo rằng tôi có thể kiểm tra mọi trạng thái được ghi lại miễn là repo có sẵn cao hơn nhiều.

Ngoài ra, có một loạt các vấn đề với mô đun con như được mô tả ở đây


Tôi chắc chắn rằng họ đang ở đúng vị trí vì tôi đang duy trì tất cả trong số họ :-) Ngoài ra, hãy cẩn thận về việc sao chép dự án vì điều kiện phân phối lại.
André Caron

OK, điều đó làm giảm vấn đề. Và cấp phép: Có, bạn phải cẩn thận, nhưng đó là một vấn đề hoàn toàn khác.
Wilbert

0

Đối mặt chính xác cùng một vấn đề ở đây. Một trong những giải pháp có thể có một số repo libsrằng sẽ tổ chức core, network, graphnhư submodules và chỉ CMakeLists mà sẽ nói với mỗi người trong số các libs nơi để tìm sự phụ thuộc của nó. Mỗi ứng dụng bây giờ sẽ có libsmô hình con và chỉ sử dụng các lib cần thiết.

Kiểm tra từng lib có thể được thiết lập theo 2 cách:

  • Có core_testing, graph_testing, network_testing như các ứng dụng riêng biệt
  • Triển khai các lib đã kiểm tra đến các máy chủ thử nghiệm và tìm thấy chúng trong khi chạy thử nghiệm bằng cmake

Điều này không làm cho tất cả các lib có sẵn cho tất cả các lib khác?
André Caron

Theo mặc định, có. Nhưng điều đó có thể được quyết định trong các cmakelists cấp libs. Nếu graphkhông cần phải biết về network- không vượt qua networkthứ -related để graphsubdir
Max
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.