[英]GIT how to pull changes from a branch in one repository into a branch of another repository
我知道這對某些人來說可能聽起來很愚蠢,但我在一個分支中進行了代碼更改並將這些更改提交給該分支。 此代碼更改位於 a.Net 解決方案的特定存儲庫中,並且此解決方案與許多其他 .Net 解決方案共享。
我試圖用 git 子模塊做的是將代碼更改從這個存儲庫下拉到我正在處理另一個代碼更改的另一個存儲庫的另一個分支。
有沒有辦法可以專門拉下那個分支?
找到我的筆記,由於標記,無法在評論中很好地發布這個,基本行是這些:
git remote add local-origin /c/git/OTHER_REPOSITORY
git pull --rebase local-origin main --allow-unrelated-histories
您可能需要git cherry-pick
。 使用它並不是特別困難; 這里的設置很棘手。 你可能不想要git merge
,有或沒有--allow-unrelated-histories
。
重要的是要認識到 Git 與分支無關,在某種意義上甚至與文件無關。 相反,Git 是關於提交的——這反過來意味着您需要了解很多關於提交的信息:提交是什么,為您做什么,以及提交與其他提交的關系。
任何 Git 存儲庫中的每個提交都被編號,帶有一個丑陋的隨機外觀hash ID (正式地, object ID或 OID),如c48035d29b4e524aed3a32f0403676f0d9128863
。 實際上,此 ID 是提交的真實名稱(另請參閱TV Tropes ):具有此特定提交的任何Git 存儲庫都將其存儲在此UUID下。 1個
每個提交都會存儲一些元數據,包括作者的姓名和 email 地址以及一些日期和時間戳。 元數據還包括先前(或父)提交 hash ID 的列表——只是原始數字,但由於這些是這些提交的真實名稱,因此 Git 可以找到這些提交。 並且 - 間接地 - 每個提交都會存儲每個源文件的完整快照,就像提交作者進行該提交時的形式一樣。
這樣的結果是,只要給定 hash ID,Git 就可以得到:
通過比較兩個快照,Git 找出“發生了什么變化”。 提交存儲快照,而不是一組更改。 需要兩次提交才能“看到”任何更改。
1任何 Git object 的 OID 目前只是對象數據的 SHA-1。 一旦 Git 更廣泛地支持 SHA-256,提交將有兩個“真名”,這將很尷尬。 目前還不清楚最終將如何處理。
我正在嘗試做的......是將代碼更改從這個存儲庫下拉到另一個存儲庫的另一個分支
兩個存儲庫實際上可以共享提交:如果存儲庫A有提交c48035d29b4e524aed3a32f0403676f0d9128863
我們簡稱為“提交C1
”——並且獨立的存儲庫B也有提交C1
,那么根據真名法則,這是同一個提交。 並且 - 至少通常情況下,在沒有淺克隆的情況下 - 如果你有一些提交,你有提交的父級,以及父級的父級,等等,一直回到時間第一次提交。
所以如果你想復制一些提交C2
的更改,並且你有提交C2
,你可以讓 Git 將提交C2
變成“提交C2
中的更改”。 git show
命令執行此操作並顯示更改的內容,並以有關來自C2
元數據的提交的一般信息為前綴。 git diff
命令可用於獲取快照中的差異:您可以將C2
與其(第一個並且可能是唯一的)父級進行比較。 其他 Git 命令也可以做同樣的事情。
一旦你有了C2
和它的父級之間的差異,你就可以將這個相同的差異應用於第三次提交C3
。 您可以手動執行此操作,這往往非常乏味。 或者你可以讓 Git 為你做,用git cherry-pick
。
cherry-pick 命令的工作非常簡單:您檢查要用作起點的提交,通常使用git switch
或git checkout
:
git switch somebranch
然后,您給git cherry-pick
原始 hash 您想要復制其效果的提交的 ID。 或者,如果您有一個分支或標記名稱,當解析為原始 hash ID 時,獲取正確提交的原始 hash ID,您可以使用該名稱,但我們在這里只使用原始 hash ID:
git cherry-pick c48035d29b4e524aed3a32f0403676f0d9128863
Git 現在找到您在此處指定的提交(我選擇了C1
)。 它必須存在於您當前的存儲庫中。 Git 使用該提交的元數據來查找該提交的父項:必須只有一個父項,因此這是一個普通的提交。 2 Git 將提交的快照(在本例中為C1
)與其父快照進行比較,找出更改的內容,然后找出如何將這些更改組合到當前提交中。
這種組合在技術上是一種合並操作——“作為動詞合並”,我喜歡這樣稱呼它——這意味着你可能會遇到合並沖突。 如果您確實遇到合並沖突,您可以按照通常的方式解決它們。 完成后,您可以使用git cherry-pick --continue
或git commit
來完成。 如果沒有合並沖突, cherry-pick
會繼續並運行git commit
來為您完成工作。 最終結果是普通提交,而不是合並,默認情況下 Git 會重新使用您現在復制的提交中的提交消息。
新的提交是不同的——它有自己的新 UUID,它包含了你的名字和你的 email 地址以及當前日期和時間,以幫助確保它的唯一性——但它“做同樣的事情”(有相同的差異,更多或更少)作為您剛剛復制的提交。
2您可以挑選一個根提交——一個沒有父提交的提交——Git 將調用每個文件“新添加”。 如果您出於某種原因選擇合並提交,這是一個具有多個父級的提交,您可以告訴git cherry-pick
假裝哪個父級是唯一的父級,以便它可以獲得適當的差異。 但總的來說,無論如何你只會挑選一個“普通”(單親)提交。
從這個存儲庫到...另一個存儲庫
如果這兩個存儲庫不是彼此的克隆,或者不是過去的,那么很可能不僅您的新提交不在兩個存儲庫中(您只將它添加到一個),而且它的父提交也不在兩個存儲庫中存儲庫(一開始就沒有)。
對於git cherry-pick
,這是一個show-stopper (意思是 3)。 為了使用git cherry-pick
,您必須將要復制的提交及其父提交都放入您自己的存儲庫中。
幸運的是,這很簡單:只需使用git remote add
將包含您關心的兩個提交的存儲庫添加到您現有的克隆中。 然后使用該遙控器運行git fetch
。 例如,假設您剛剛進行的提交位於$HOME/work/project23/
中,並且您想要挑選到$HOME/work/project45/
HOME/work/project45/ 中的存儲庫中。 所以您現在位於第二個存儲庫 ( project45
) 中:
git remote add project23 $HOME/work/project23
git fetch project23
您現在在project23
存儲庫中project45
來自 project23 的所有提交。 這確實會使存儲庫有些膨脹,但只要您有足夠的磁盤空間,就無需再挑剔了。 您現在可以運行git cherry-pick
命令。
當你完成並想要清理時,運行:
git remote remove project23
這將刪除名稱project23
和對其他 Git 存儲庫的引用。 Git 將保留所有復制的提交一段時間,但最終會清除它們並且您的存儲庫將縮小,並且git push
不會將所有這些提交復制到其他地方:它們只是占據那個特定克隆中的空間,直到 Git 繞過清理。
(如果你想強制 Git 提前清理,你可以運行git gc --prune=now
,但除非你的磁盤空間嚴重不足,否則我不建議這樣做。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.