簡體   English   中英

如何將更改從我自己的存儲庫的子模塊推送到其他人的存儲庫(我是合作者)?

[英]How do I push changes to someone else's repository (I'm a collaborator on), from a submodule of my own repository?

所以我有自己的存儲庫,我們稱之為“我的”,它包含一個子模塊存儲庫“他們的”。 我可以訪問他們的遠程存儲庫,因此我可以直接將更改推送到它。

我正在嘗試將我對“他們的”所做的更改推送回他們的遠程 GitHub 存儲庫,但我似乎無法讓它工作。 我可以將更改推送到我在 GitHub 上的遠程存儲庫“我的”,並且可以看到對“他們的”的新提交。 但是當我訪問他們的 GitHub 時,它沒有添加最新的提交。

子模塊不應該只是常規存儲庫,在另一個內部帶有一些額外的元數據嗎? 如果是這樣,為什么“他們的”目錄中的“git push”不起作用? 我試過從“他們的”內部提交和推送,然后從“cd ..”和“我的”內部提交/推送,但它也不起作用。

我已嘗試此處列出的步驟: Git submodule push無濟於事。 我只能假設,因為我正在嘗試推送到我不擁有的存儲庫,所以還需要做其他事情嗎?

~/Mine$ git remote -v                                                                                                                                                                                                        
origin  https://github.com/myUser/Mine.git (fetch)                                                                                                                                                                                
origin  https://github.com/myUser/Mine.git (push) 

~/Mine/Their$ git remote -v                                                                                                                                                                                                    
origin  https://github.com/theirUser/Theirs.git (fetch)                                                                                                                                                                                        
origin  https://github.com/theirUser/Theirs.git (push) 

提交完成后,將其推送到分叉倉庫(即“我的”)。 從你的分支在正確的分支中打開一個拉取請求。 拉取請求獲得批准並合並后,您可以將更改從上游拉取到本地存儲庫。

然后更改將被添加到“他們的”存儲庫中。

你是對的:子模塊本身就是一個存儲庫。 這意味着您可以cdchdir進入子模塊並以與使用任何其他 Git 存儲庫相同的方式開始使用它,包括運行git fetchgit checkoutgit commit等。

使子模塊成為子模塊的原因是,位於子模塊上方某處的其他 Git 正在控制子模塊,通常通過在其中運行git checkout hash-id控制子模塊。 這會將子模塊置於 Git 所謂的分離 HEAD模式。 (控制 Git 是超級項目。)

這種“分離頭”模式有點棘手。 可以在這種模式下進行新的提交,但是當您這樣做時,大多數普通方法都無法找到它們。 它們暫時很容易通過特殊名稱HEAD ,但是這個特殊名稱HEAD將被超級項目強行調整,它將chdir進入子模塊並再次運行git checkout hash-id ,丟失1你所做的提交.

要將您在子模塊 Git 存儲庫中所做的提交發送到某個其他 Git 存儲庫,您必須其他Git 存儲庫中為這些提交指定一個名稱 通常,這意味着給他們一個分支名稱。 您的存儲庫中使用分支名稱沒有硬性要求,因為您可以運行:

git push <remote-or-URL> HEAD:<name>

通過名稱HEAD將子模塊存儲庫中標識的提交發送到另一個 Git,並禮貌地要求它創建或更新其名稱name以指向該提交。 但是大多數人不喜歡使用/使用分離的 HEAD 模式。

一般來說,這意味着要在充當某些超級項目的子模塊的 Git 存儲庫中工作,您應該使用以下順序: 2

  1. 進入子模塊。 從這里到第 3 步,您只需將它用作常規 Git 存儲庫即可。

  2. 通過選擇分支名稱git checkout或創建指向當前提交的分支名稱退出分離的 HEAD 模式 需要注意的是,如果你選擇一些現有的分行名稱,這可能是一個不同於當前提交提交。 或者它可能與當前提交相同

    請記住,超級項目存儲庫早些時候告訴這個 Git:使用這個原始提交,通過它的哈希 ID進入分離的 HEAD 模式。 我們現在正在退出分離 HEAD 模式,這需要選擇或創建分支名稱。 如果你選擇一些現有的分支名稱,你就會被分支名稱選擇的任何提交所困擾。 但是,如果您正在子模塊存儲庫中開發新的提交,您可能需要一個分支名稱來記住它們。

  3. 現在,以通常的方式進行新的提交。 以通常的方式使用git push 提交將或不會以提交執行或不執行的通常方式進入接收存儲庫。 如果他們確實進入了接收存儲庫,則會以通常的方式創建或更新該存儲庫的分支名稱

  4. 一切完成后,退出子模塊存儲庫,返回超級項目存儲庫。 現在是時候在superproject 中進行新的提交了。

我已經多次提到超級項目 Git 一直控制着子模塊 Git。 它在子模塊 Git 中執行chdir並運行git checkout hash-id 這里的關鍵來自兩部分:

  • 超級項目 Git 什么時候對子模塊做這個?
  • 超級項目 Git哪里獲取原始哈希 ID?

第一個問題的答案很復雜: git submodule update做到了,但並非總是如此; 3 git checkout --recursive這樣做(總是); 根據選項和設置,各種其他操作有時也可以做到。 也就是說,它不會發生,除非和直到你問這樣的事發生,但它並不總是很明顯,問這樣的事發生。 我們要做的是確保在第二點再次發生之前解決第二點。

第二個問題的答案——超級項目 Git 從哪里獲得原始哈希ID——是它從超級項目中的提交中獲取它。 但是你已經在子模塊中進行了新的提交,並將其提交到上游到其他一些 Git 存儲庫,所以現在是時候在superproject 中進行新的提交,以記錄正確的哈希 ID,即新的哈希 ID提交您在子模塊中所做的。

與往常一樣,任何提交都不能更改; 和往常一樣,Git 從索引中的任何內容(又名staging area )進行新的提交。 當您提取一些現有提交時,Git 會將該提交中的文件讀取到索引/暫存區中。 如果存儲庫充當某個子模塊的超級項目,則此步驟還會從提交中讀取所需的哈希 ID (在該子模塊中)到索引中。 由於這不再是所需的哈希 ID,您現在的工作是將新的哈希 ID放入索引中。

在超級項目中執行此操作的命令是git add 與往常一樣, git add將內容寫入索引。 對於普通文件,它將該文件的副本寫入索引。 4但是,對於子模塊,它:

  • 進入子模塊片刻;
  • Git:什么是原始哈希ID為提交你確定HEAD ( git rev-parse HEAD );
  • 將生成的哈希 ID(無論它是什么)填充到超級項目 Git 的索引中,在該子模塊的插槽中。

無論子模塊是否處於分離的HEAD狀態,這都有效,因為git rev-parse HEAD始終返回當前提交的原始哈希 ID。

因此,在git add path/to/submodule選擇的(實際上是制作和推送的)提交的哈希 ID 現在記錄在超級項目的索引中。 您的下一次提交將記錄原始哈希 ID。

假設其他一切都准備好了,您現在可以運行git commit在超級項目中進行新的提交(這大概是,並且一直處於附加 HEAD 狀態,在某個分支名稱上)。 一旦你提交了這個新的超級項目,你就可以像往常一樣git push了。

請注意此處步驟的仔細排序:

  1. 進入子模塊。
  2. 為簡單起見,在子模塊中的分支上進行提交,但是無論您如何進行提交都可以。
  3. 發送這些提交到哪里它是人們從克隆子模塊,使Git有他們。 此步驟需要在其他 Git 中設置分支或標簽名稱。
  4. 現在其他人可以訪問子模塊的origin存儲庫中的提交,在 suprerproject 中創建和推送一個提交,該提交引用子模塊提交的原始哈希 ID。

由於 Git 的分布式特性,可以在您的子模塊中進行提交但將其推送到任何地方,然后在您的超級項目中進行提交推送它。 任何獲得這個新提交的人都會得到一個提交,該提交通過原始哈希 ID 指向一個提交,他們不僅沒有,而且甚至無法獲得. 因此,第 3 步(“使提交對所有人可用”)必須在第 4 步中的push之前發生。(第 4 步中的“進行提交”可以更早發生——注意不要推送它,並使用任何更新的內容重做提交哈希,如果子模塊提交出於任何原因必須重做。)


1失去這里的意思是“很難找到”。 提交本身不會立即消失:它們與其他丟失的提交具有相同的寬限期,您可以使用子模塊 Git 的HEAD reflog 來查找它們,就像您在任何存儲庫中查找丟失的提交一樣——因為子模塊畢竟只是另一個存儲庫。

2因為 Git 是一組工具,而不是預先打包的解決方案,所以還有很多其他方法可以實現您的目標。 這只是一種非常靈活的方式。

3特別是git submodule update有很多更新方式 使用一些參數,您可以直接git submodule update來檢查git submodule update名稱,從而首先生成一個附加的 HEAD(而不是分離的 HEAD)! 這是腳注 2 所指內容的一部分。 git submodule update的詳細工作非常復雜,所以我試圖在這個答案中避免這些變體。

4從技術上講,它用正確的文件內容寫出一個blob 對象——或者如果可能的話,不改變地重用一些現有的 blob 對象——然后將 blob 對象的哈希 ID 寫入索引,而不是實際的文件內容。 但是效果就像 Git 將文件復制到索引中一樣,只要你不深入到git ls-files --stagegit update-index的級別。

暫無
暫無

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

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