簡體   English   中英

Git 子樹合並策略或子樹命令?

[英]Git subtree merge strategy or subtree command?

我正在開始一個新的 Zend Framework 項目,我將在其中與設計師合作。 我將使用 git 維護這個項目代碼,通常設計師不會說 git(或任何編程語言)所以我想讓他的事情變得容易,否則我擔心他根本不會使用 ZBA9F11ECC3497D6993B933FDCBD2 我的計划是給他一些 Git gui,然后他應該只使用基本的 git 功能,例如提交、差異、獲取、合並、推送和拉取。

我正在使用 gitolite 來維護我們的 git 存儲庫的共享副本,並且由於它具有細粒度的權限系統,因此我將僅授予設計人員對專用分支(設計)的 RW 訪問權限和對其他分支的讀取權限。

為了簡單起見,我只想與他分享主項目中的一些文件夾(遵循ZF 推薦的結構),他確實需要訪問這些文件夾才能完成工作。 同時我希望我們倆仍然可以相互融合。

他的分支的簡化結構應該是這樣的:

<project name>/
    application/
        layouts/
            scripts/
        views/
            scripts/
    public/
        css/
        images/
        js/

我知道我可以使用子模塊來完成這項任務,但是維護起來會很痛苦,因為我應該將我的項目拆分為(至少)4 個子存儲庫,他應該只能訪問子存儲庫,並且他有 3 個存儲庫可以使用. 出於這個原因,如果這是唯一的解決方案,我將放棄這個想法。

我已經閱讀過的一些鏈接讓我認為我所要求的是可能的:

這是我的問題:

  1. 如何創建簡化的分支designgit checkout -b designgit mv/rm ?)
  2. 如何配置 git 以跟蹤跨分支的編輯(所以我可以git merge design ,反之亦然)

更新:

我發現了解決這兩個 SO 問題的另一種可能方法

我嘗試在設計分支中實現git rm all-unneeded-stuff之后的第一個,我在 master 分支中進行了提交,其中涉及白名單路徑中的一個文件和黑名單路徑中的另一個文件,但是git merge失敗並出現以下問題信息

CONFLICT (delete/modify): application/Bootstrap.php deleted in HEAD and modified in master. Version master of application/Bootstrap.php left in tree.

然后我在主分支中添加了一個新目錄,並在從設計合並時添加了新目錄。 我在驅動程序中放了一些調試回顯,我發現在這兩種情況下都沒有調用它,可能是因為它不是真正的合並。

我還沒有嘗試過第二種方法(.gitignore 一種),但如果我理解這種方法不符合我的需要,因為它只會忽略設計分支中的黑名單文件,但它們會在設計分支,打破了我的要求。

我在GitHub上進行了實驗

更新 2:

我認為目前沒有解決方案。 使用當前的 git 實現,這根本無法實現。

我想被反駁,但我又怕它不會發生。

聽起來您希望能夠在每個目錄的基礎上限制讀取訪問。 這是可能的,但我知道的唯一解決方案遠非簡單。 它涉及服務器上同一個存儲庫的多個版本,每個版本都使用一些復雜的鈎子魔法來過濾掉子目錄,從而保持同步。

我在業余時間致力於實現這些鈎子,最終目標是將它們作為開源軟件發布(也許作為 gitolite 的一個功能),但不幸的是,我的業余時間有限。

存儲庫

通用解決方案涉及同一存儲庫的至少三個變體: 一個協調兩個或多個委托存儲庫的權限存儲庫。 用戶從不克隆權限庫; 只有委托存儲庫被克隆。

代表負責將傳入的提交轉發到權限存儲庫。 權限存儲庫負責為每個其他委托存儲庫適當地過濾傳入的提交。 然后將結果下推給其他代表。

權限存儲庫不是嚴格要求的——代表可以自己執行過濾,然后將結果直接推送給其他代表——但是使用另一個存儲庫作為集中協調器可以大大簡化實施。

委托存儲庫

每個委托存儲庫都包含整個項目數據的子集(例如,過濾掉的零個或多個子目錄)。 所有委托存儲庫都彼此相同,只是每個委托都有一組不同的文件被過濾掉。 它們都具有相同的提交歷史圖,但提交將具有不同的文件內容,因此具有不同的 SHA1 標識符。 它們具有相同的分支和標簽集(換句話說,如果項目有一個master分支,那么每個委托存儲庫也有一個master分支),但是因為等效提交的 SHA1 標識符不同,所以引用將指向不同的 SHA1 標識符。

例如,以下是兩個委托存儲庫的內容圖表。 everything.git存儲庫沒有過濾掉任何內容,但是no-foo.git存儲庫過濾掉了子目錄foo中的所有內容。

$ cd ~git/repositories/everything.git
$ git log --graph --oneline --decorate --date-order --all
* 2faaad9 (HEAD, master) barbaz
| * c3eb6a9 (release) foobar
* |   8b56913 Merge branch 'release'
|\ \  
| |/  
| * b8f899c qux
* | aad30f1 baz
|/  
* f4acd9f put a new file in subdirectory bar
* 2a15586 put a new file in subdirectory foo

$ cd ~git/repositories/no-foo.git
$ git log --graph --oneline --decorate --date-order --all
* 81c2189 (HEAD, master) barbaz
| * 6bbd85f (release) foobar
* |   c579c4b Merge branch 'release'
|\ \  
| |/  
| * 42c45c7 qux
* | 90ecdc7 baz
|/  
* 4d1cd8d put a new file in subdirectory bar
* 9cc719d put a new file in subdirectory foo

請注意,這兩個圖看起來相同,具有相同的提交消息、相同的分支名稱等。唯一的區別是 SHA1 ID,因為文件內容不同。

(旁注:提交也可以被過濾掉,以防止另一個委托的用戶甚至知道在過濾掉的目錄中進行了提交。但是,只有在提交只涉及過濾后的文件時才能過濾掉 - out 目錄。否則會出現無法通過 hooks 自動解決的合並沖突。)

權威資料庫

權限存儲庫是所有委托權限的超集。 每個委托倉庫中的所有提交對象都會通過每個委托倉庫中的掛鈎自動推送到授權倉庫中。 因此,如果有兩個委托存儲庫,則權限存儲庫中將有兩個同構 DAG(每個委托一個)(假設委托不共享公共根提交)。

權限存儲庫還將具有來自每個委托的每個項目分支的版本,以委托名稱為前綴。 繼續上面的示例, everything.git委托存儲庫有一個master分支指向提交2faaad9 ,而委托no-foo.git有一個master分支指向過濾但其他等效的提交81c2189 在這種情況下, authority.git將有兩個 master 分支: everything/master指向2faaad9no-foo/master指向81c2189 下圖說明了這一點。

$ cd ~git/repositories/authority.git
$ git log --graph --oneline --decorate --date-order --all
* 2faaad9 (everything/master) barbaz
| * 81c2189 (no-foo/master) barbaz
| | * c3eb6a9 (everything/release) foobar
| | | * 6bbd85f (no-foo/release) foobar
* | | |   8b56913 Merge branch 'release'
|\ \ \ \  
| | |/ /  
| |/| |   
| | * |   c579c4b Merge branch 'release'
| | |\ \  
| | | |/  
| * | | b8f899c qux
| | | * 42c45c7 qux
* | | | aad30f1 baz
|/ / /  
| * | 90ecdc7 baz
| |/  
* | f4acd9f put a new file in subdirectory bar
| * 4d1cd8d put a new file in subdirectory bar
* | 2a15586 put a new file in subdirectory foo
 /  
* 9cc719d put a new file in subdirectory foo

請注意,每個提交有兩個版本,每個代表一個版本。 還要注意分支名稱。

掛鈎

委托存儲庫

每個委托都將提交提交給權限存儲庫。

當用戶更新委托存儲庫中的引用(通過git push )時,該存儲庫的update掛鈎會自動將git push送到權限存儲庫中。 但是,它不使用標准推送 refspec,而是使用 refspec 導致授權存儲庫中的引用以委托存儲庫的名稱為前綴(例如,如果委托存儲庫名為foo.git ,那么它將使用推送 refspec,如+refs/heads/master:refs/heads/foo/master+refs/tags/v1.0:refs/tags/foo/v1.0 )。

權威資料庫

權限存儲庫過濾傳入的提交並將它們推送到其他委托存儲庫。

當委托倉庫推送到權限倉庫時,權限的update鈎子:

  1. 檢查用戶是否嘗試在過濾出的目錄之一中創建文件。 如果是這樣,它會以錯誤退出(否則可能會出現無法自動解決的合並沖突)。
  2. 移植回最初過濾掉的子目錄,形成一棵沒有過濾掉的樹。
  3. 對於每個其他委托,過濾未過濾的樹以進行等效提交,並刪除適當的內容。
  4. 將等效提交推送到委托存儲庫。

必須注意避免委托存儲庫之間的競爭條件並正確處理錯誤。

你的案例

在您的示例中,您將有兩個這樣的委托存儲庫:

  • everything.git (給你)
  • zend-project.git (供您的設計師使用)

authority.git中的分支將以everything為前綴,而zend-project對應於兩個委托存儲庫。

當你 push to master in everything.git時,會發生以下情況:

  1. everything.git中的update掛鈎會將傳入的提交推送到authority.git中的everything/master分支。
  2. 對於每個傳入的提交, authority.git中的update掛鈎將:
    1. 創建一個與提交樹 100% 相同的新樹 object,但刪除applicationpublic子目錄之外的所有內容。
    2. 使用新樹和等效父級創建新提交 object,但重用原始提交消息、作者和時間戳。
    3. 更新zend-project/master以指向新的提交。
  3. zend-project/master中的authority.git推送到zend-project.git中的master中。

當您的設計人員推動master zend-project.git時,會發生以下情況:

  1. zend-project.git中的update掛鈎會將傳入的提交推送到authority.git中的zend-project/master分支。
  2. 對於每個傳入的提交, authority.git中的update掛鈎將:
    1. 檢查是否在applicationpublic子目錄之外創建了任何新文件。 如果是,則返回錯誤消息。
    2. 創建一個新的樹 object,它與提交的樹 100% 相同,除了來自everything/master節點的其他子目錄。
    3. 使用新樹和等效父級創建新提交 object,但重用原始提交消息、作者和時間戳。
    4. 更新everything/master以指向新的提交。
  3. 推送everything/master in authority.git to master in everything.git

筆記

上面描述了一種實現按目錄讀取訪問控制的方法。 如果您真的不希望某些用戶能夠訪問存儲庫的某些部分,它應該是合適的。 在您的情況下,為您的設計師提供便利可能比限制訪問更重要。 如果是這樣,可能有一種更簡單的方法來完成你想要的。

我希望我能夠足夠清楚地解釋這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM