簡體   English   中英

遙控器的“ git fetch”遙控器

[英]“git fetch” remote refs of remotes

我希望能夠將所有正在進行的分支從存儲庫移到存儲庫,並能夠刪除舊的分支而不丟失任何提交。 有沒有辦法可以從遠程存儲庫中獲取遠程分支?

# A: Create a repo with two branches
> mkdir a ; cd a ; git init
> echo initial > file_master ; git add file_master ; git commit -am "initial"
> git checkout -b mybranch
> echo test > file_mybranch ; git add file_mybranch ; git commit -am "test"
> git checkout master

# B: Clone
> git clone . ../b ; cd ../b
> git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/mybranch
# if I wanted, I could delete a and checkout remotes/origin/mybranch

# C: Clone of clone, but it's missing mybranch
> git clone . ../c ; cd ../c
> git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
# no remotes/origin/mybranch - it's a remote of origin
# if I delete a and b I lose mybranch for good

>git ls-remote
7505fa4ec342ff85095737d27df0a5062c53d4d5        HEAD
7505fa4ec342ff85095737d27df0a5062c53d4d5        refs/heads/master
7505fa4ec342ff85095737d27df0a5062c53d4d5        refs/remotes/origin/HEAD
7505fa4ec342ff85095737d27df0a5062c53d4d5        refs/remotes/origin/master
dfd057c18baa4227905999b32bffdecf639185f7        refs/remotes/origin/mybranch
# there it is, but I don't have it locally

重申一下,在存儲庫B中,我可以安全地rm -rf ../a ,然后git checkout remotes/origin/mybranch ,我將擁有file_mybranch 我想要的是在存儲庫C中進行此提交。 我的問題是: 如何從B將分支的remotes/origin/mybranch指向的提交放入C 可以說我已經刪除了A。

顯然有嚴重的Git命名問題在這里,因為這個問題旅行的人所有的時間 根本問題是“分支”一詞令人困惑。 這並不意味着您認為它有用! 另請參見“分支”到底是什么意思?

克隆是故意不完美的副本

當您使用git clone <url>git clone <path>或類似方法克隆存儲庫時,您不會獲得上游存儲庫的確切副本。 相反,您會得到一份經過一些故意更改的副本:

  • 新副本具有一個遠程文件 (通常命名為origin ,設置為保存原始URL。
  • 新的副本取走了原始副本的所有分支 ,但沒有一個遠程跟蹤分支 盡管名稱為“遠程跟蹤分支”,但這些不是分支! Git可以稱它們為“大象”,這可能會減少混亂。 :-)在這里我們稱它們為RTB ,只是為了使它們中沒有單詞“ branch”。
  • 實際上,新副本開始時根本沒有分支 ,但是立即執行了git checkout somebranch的等效git checkout somebranch git clone這個git checkout命令的名字取決於一些棘手的事情。
  • 新的克隆確實從大量RTB開始。 請記住,這些不是分支機構。 他們是這些有趣的實時出價工具。 RTB是以與遙控器相同的字符串開頭,然后帶有斜杠的名稱。

您獲得的特定RTB 取決於您要克隆的存儲庫中的哪些分支 假設您要克隆的存儲庫具有三個實際分支,分別稱為masterdevelopmybranch 這意味着,在克隆不完善的副本中,您將獲得其中三個RTB事物(不是分支),它們分別是origin/masterorigin/developorigin/mybranch

git checkout命令將自動創建分支

假設您有一個完全沒有分支的存儲庫,例如git clone創建的分支之一,並且從一頂帽子中挑選了一個分支名稱,其中包括可能的名稱: masterdevelopmybranch 為了真實起見,讓我們使用Git通常選擇的master 您說服git clone命令將此名稱傳遞給git checkout

git checkout master

現在,問題是, 沒有master分支,因為根本沒有分支。 因此,Git無法將其檢出。 但是,這是第一個棘手的部分,您的Git 可以掃描您所有的實時出價,尋找名稱類似於 master 實時出價。 就是這樣: origin/master聞起來像master一樣,Git會在副本中創建一個新的分支,稱為master ,使用origin/master作為該新分支的哈希ID。

那是git clone的最后一步:它簽出一些分支,並在此過程中最終創建該分支。 您可以使用-b選擇哪個分支,但只有一個名稱:您可以讓Git運行git checkout master ,也可以讓Git運行git checkout mybranch ,但不能同時運行它們。 你只有一個!

如果不提供-b參數,則您的Git會從在另一個Git上看到的完整分支名稱中選擇一個。 它通常采master ,但也有通過其他的Git給你的Git暗示這名挑規則。 最重要的規則是,你的Git會詢問哪些分支已經簽出了其他的Git(或者更准確地說,檢查其HEAD設置)。

有很多方法可以制作出更完美的克隆,但是您不能使用

如果使用git clone --mirror ,則將獲得完美的副本。 問題在於,這個完美的副本沒有工作樹:這就是Git所說的“裸”克隆。

這樣做的原因是,這樣的克隆被設置成為一個盲目的復制所有的時間 :每次運行時git fetch鏡中的克隆,你更新它完全匹配無論是在其他存儲庫。 這意味着您將放棄在任何分支上完成的所有工作,並再次奴隸地匹配另一個存儲庫的分支。 為了確保您不會丟失這種工作,Git會阻止您使用精確副本進行工作。

解決的辦法是忍受缺陷

克隆時,您會得到不完美的副本,Git會簽出一個分支,並通過重命名所有分支來從Git制作的RTB復制該分支。

現在,您可以在其余所有RTB上運行git checkout ,也就是說,除了git clone已對其運行git checkout RTB之外的所有RTB。 最簡單的方法是僅對所有名稱運行它:畢竟再次運行git checkout master並沒有什么壞處。

要提取所有名稱,您可以使用git for-each-ref (腳本的意思是)或git branch -r (不是很多)。 您將需要按摩一下名稱以去除origin/零件,然后運行git checkout

(或者,您可以簡單地在需要它們之前就不花心去檢查它們。不要重新克隆不完美的副本:重新克隆原件-假設您仍然有並且可以拿到它。)

如果您仍然有副本,但沒有原始副本,並且想要第二個副本與第一個副本完全相同 (直到擁有相同的分支和相同的實時出價),則需要使用一個或多個技巧,因為未設置Git要做到這一點。 一個訣竅是無論如何都要進行鏡像克隆:

$ git clone --mirror url-of-copy mirror-clone-dir

現在,您具有該副本的完全相同的副本,只是副本本身是一個空克隆。 現在,您可以將其從裸克隆轉換為非裸克隆(例如,請參見如何將裸git存儲庫轉換為普通的(就地)存儲庫? ),但是還應該更新其remote.origin.fetch設置:

$ cd mirror-clone-dir
$ git config --get remote.origin.fetch
+refs/*:refs/*
$ git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

(然后是其余的轉換)。 或者,您可以從普通克隆開始,然后再運行一個命令:

$ git clone <url-of-copy> new-clone-dir
[the usual messages]
$ cd new-clone-dir
$ git fetch origin '+refs/remotes/origin/*:refs/remotes/origin/*'

請注意,最后一步將副本的遠程跟蹤分支替換所有現有的遠程跟蹤分支(“ RTB”)。 換句話說,您失去了副本分支的記憶,將Git的“我在url副本中看到的內容”替換為“我從url副本中獲得的內容, 它們已被列為它們的內存”。記住他們在原始作品中看到的內容 。”

從字面上看,您不能同時獲得兩者,至少不能使用這些實時出價工具:要么擁有分支並記住他們的分支,要么擁有分支並記住他們對別人分支的記憶。 但是,您確實還有一些其他選擇:

  • 如果真正的原件仍然存在,請將其添加為第二個遙控器,然后從中獲取:

     $ git remote add real-source <url> $ git fetch real-source 

    現在您不僅擁有origin/master而且擁有real-source/master

  • 如果不是這樣,則將副本添加為第二個遠程對象(在相同的存儲庫中使用兩個名稱沒有什么害處),然后使用相同的git fetch技巧從副本中填充其他RTB集:

     $ git remote add r2 <url-of-copy> $ git fetch r2 '+refs/remotes/origin/*:refs/remotes/r2/*' 

    現在,您有兩個遠程origin/masterorigin/master記住“在來源上看到的master ,重命名為origin/master ”,而r2/master記住“在r2上看到的origin / master(與URL相同的URL),重命名為r2/master ”。

暫無
暫無

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

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