2009-09-14 127 views
43

比方說,我有一個名爲核心四個項目,一個超級。依賴樹是這樣的:Git的嵌套子模塊和依賴

Super ---> Core 
     |-> A -> Core 
     |-> B -> Core 

我希望每個項目是獨立的,那就是,我希望能夠退房和編譯自身每個項目(每個有它的依賴,當然)。

我想到了每一個項目映射到存儲庫,然後用子模塊指的依賴關係,但我看到了以下問題與方法:

  1. 當檢查出超級其所有的依賴,我想最終得到三份Core
  2. 因爲子模塊是完全獨立的,所以這三個副本中的每一個都可能指向核心的不同版本,那將是一團糟。

所以...我錯過了什麼?我誤解了git submodules還是誤用了它們?有沒有其他解決方案來解決這個問題(除了求助於二進制依賴)?

回答

12

你剛剛發現使用Git子模塊缺乏覆蓋的依賴關係:

如果超級取決於核心,其核心的依賴應該「覆蓋」的那些A和B具有與核心。

效仿,這將是創建您的超級項目,你做的方式,唯一的辦法
去除A和B.
的子模塊核心(意爲超級現在取決於A」和B',A'是A沒有核心,B'是B沒有核心)

7

git存儲庫應該是相當原子化的,每個存儲庫都是獨立的實體用於特定目的。除了合併項目A和B以外,超級項目的目的是什麼?如果沒有獨特的東西(即不在A,B或Core中的文件),那麼它是相當多的。

編輯:因爲git子模塊在我工作的某個地方特別痛苦,我們建立了自己的依賴系統,通過文本文件跟蹤依賴的回購站。我們設置它,因此它總是跟蹤分支的頭部,而不是特定的提交。

我們能夠建立我們的所有項目,雖然他們都是這樣的超級項目的一部分:

Super 
|-A 
|-B 
|-Core 

該項目將使用相對路徑例如相互引用../A/include.h。檢查出回購A將無法正常工作,你必須創建另一個「超級」回購對公正的工作:

AWorking 
|-A 
|-Core 

編輯另一個原因行爲git的是,它不能跟蹤的東西,都在根目錄repo目錄之上(即在包含.git文件夾的文件夾之上),如果你希望你的超級項目和子項目引用相同的存儲庫,這肯定是必需的。

+0

中超,本身就是一個項目。不要因爲我稱之爲「超級」而認爲它沒有內容。 – 2009-09-14 03:21:39

+1

但我希望每個項目都是獨立的。我喜歡git submodules被固定到一個特定的提交,而不是跟隨像svn外部,所以Core的變化不會立即破壞A,B和Super。 – 2009-09-14 04:19:33

+1

您是否跟蹤分支或落實SHA完全取決於您。但是,針對您的問題的最佳答案是,既不可能同時擁有獨立項目和超級項目選項。在實踐中,我發現爲每個子項目制定一個超級項目並不是什麼大不了的事情。 – 2009-09-14 04:38:47

0

我不會嘗試使用子模塊映射依賴關係樹 - 出於您已經發現的原因。

子模塊跟蹤給定分支的給定修訂版,因此它們有助於給出一組一致的模塊的快照。

因此,如果您的項目需要將一組版本的不同模塊作爲一個單元進行跟蹤,則可以將它們組合爲子模塊。然後,您可以在不同版本中標記不同的模塊組,以給出項目的歷史記錄,其中每個標籤顯示某個時間點哪些模塊兼容的版本。

tags/ 
    release1/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 
    release2/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 

至少我是如何理解他們的,雖然像Git的大多數事情一樣,但它可能比這更多。就管理依賴關係而言,我所能說的就是另闢蹊徑,根據我的理解,這不是Git有或沒有子模塊的原因。

+0

好的...但我認爲這解決了一個不同的問題...不是我問的那個問題。 – 2009-09-14 03:28:53

6

我認爲這裏的問題是Git的設計和你正在尋求解決的問題之間的不匹配。

Git有助於跟蹤樹木。項目之間的依賴關係可以(也可能)形成一個Graph。樹是圖,但圖不一定是樹。由於您的問題是如何有效地表示圖形,樹不是該工作的最佳工具。

這裏有一個方法可能工作:

一個Git項目有它記錄了「提示」,指出哪些項目提交可能取決於,在那裏他們可以找到一個.gitmodules目錄,走什麼路內的項目他們預計將被插入。 (http://osdir.com/ml/git/2009-04/msg00746.html

您可以添加一個腳本,它從一組項目中讀取此信息,將每個項目的.gitmodules文件中找到的提示映射到實際放置項目的文件系統上的位置,然後添加符號從git希望檢查子模塊的路徑鏈接到相應項目的實際文件系統位置。

此方法使用符號鏈接來突破樹模並構建圖。如果我們直接在git repos中記錄這些鏈接,我們會在各個項目中記錄特定於本地設置的相對路徑,並且這些項目不會像您想要的那樣「完全獨立」。因此,該腳本動態構建符號鏈接。

我在想,這種方法可能會以不希望的方式干擾git,因爲我們已經採取了希望找到一件事情的路徑,並將其他東西放在那裏。也許我們可以.gitignore符號鏈接路徑。但現在我們正在寫這些路徑兩次,並且違反了DRY。在這一點上,我們已經遠離假裝使用子模塊。我們可以在每個項目的其他地方記錄依賴關係,並保留git所期望的.gitmodules文件。因此,我們將構建自己的文件,比如.dependencies,並且每個項目都可以在其中聲明它的依賴關係。我們的腳本會在那裏查看,然後去建立它的符號鏈接。

嗯,我想我可能只是描述一個特設的包管理系統,有自己的輕量級封裝格式:)

megamic的建議似乎是一個不錯的使用git子模塊的給我。我們只處理跟蹤一個Set而不是一個Graph,並且一個Set很容易適合樹。一層深的樹本質上是一個父節點和一組子節點。

正如您所指出的那樣,這並不能完全解決您的問題中提到的問題。我們可以分爲兩種截然不同的類型:「我們可能感興趣的信息」: 1.來自項目版本的聲明(可能由項目作者提出)說「我需要項目Y的版本X」 2.您自己的構建設置使用的聲明「我已經成功地使用這套項目版本測試了我們的整個系統」

megamic的答案已解決(2)但對於(1)我們仍然希望項目告訴我們他們的依賴是什麼。然後我們可以使用(1)中的信息來計算我們最終將記錄爲(2)的那些版本集。這是一個足夠複雜的問題,以保證它自己的工具,這使我們回到包管理系統:)

據我所知,大多數優秀的包管理工具是爲特定語言或操作系統的用戶。查看Bundler在ruby世界中的'gem'包以及適用於Debian世界中的'.deb'包。

如果有人知道非常適合於'polyglot'(http://blog.heroku.com/archives/2011/8/3/polyglot_platform/)編程項目的語言中立,操作系統中立的解決方案,我會非常感興趣!我應該把它作爲一個問題。

+1

+1由於您的問題是如何有效地表示圖形,因此樹不是該工作的最佳工具。 – 2013-10-03 16:06:40

2

我認爲你可以像這樣管理一致性:在你的所有「Core」庫中定義一個「引用」分支或具有相同名稱的一系列標記(注意:你的只有一個「Core」庫例)。然後指示子項目(A,B,...)的開發者儘快升級到參考版「Core」。

在運行構建之前,通過在乾淨的,遞歸的「超級」頂級結帳中運行這三個命令,輕鬆檢查「核心」在A,B,C, :

# 1. Switch to the reference version (= "Force" consistency where need be) 
git submodule foreach --recursive 'git checkout [origin/]reference || true' 

# 2a. Show which inconsistencies you just forced; terse output 
git status -s; git submodule foreach --recursive git status -s 2>/dev/null 

# 2b. Same but verbose output 
git submodule; git submodule foreach --recursive git submodule 

# 3. Switch back to versions individually defined by sub-projects 
git submodule update --recursive 

上面的「Terse輸出」命令2a突出顯示哪個子項目沒有使用Core的「參考」版本。

您可以輕鬆擴展該方法以顯示差異,強制升級或執行任何其他您喜歡的操作。