簡體   English   中英

如何將遠程倉庫分支添加到本地倉庫

[英]How to get remote repo branch added to local repo

新創建 - 通過創建一個文件夾並運行命令git init簡而言之,從頂部創建一個本地 git 存儲庫。

我這里有一個帶有2 個分支的本地 git 存儲庫(新創建的)。 現在這些分支只是我創建的虛擬分支,對它沒有什么重要的。

$ git branch
* repo2-branch1
  repo2-branch2

我這里還有一個來自 Github 的遠程存儲庫(私有),帶有一個分支“TLA1” ,現在還記得我上面提到的帶有這兩個分支的新創建的本地存儲庫嗎? 正如我所提到的,我想要做的是在我新創建的本地存儲庫中添加這個“TLA1”分支作為帶有repo2-branch1repo2-branch2的分支之一。

在此處輸入圖像描述

假設已添加“TLA1”分支。 因此,當我輸入git branch時,我希望它是這樣的。

$ git branch
* repo2-branch1
  repo2-branch2
  TLA1

當然,當我輸入git log時,當我切換到“TLA1”時,我也會有遠程存儲庫中的提交,如圖所示,因為對我來說,這些提交非常重要。

我嘗試過的解決方案:

我做了很多研究並發現了這一點,我認為這已經是它了,因為它與我的目標相似。 但是當我嘗試它時,我得到了一個錯誤。

$ git checkout -b TLA1 origin/TLA1
fatal: 'origin/TLA1' is not a commit and a branch 'TLA1' cannot be created from it

我也沒有嘗試過,因為這可能會對我的遠程git reset --hard <remote>/<branch_name>做一些事情,這似乎不是我找到的解決方案。

有什么解決辦法嗎? 我真的很想在我新創建的存儲庫上有這個分支。

TL;博士

您需要先運行git fetch origin ,然后才能運行git checkout TLA1

你走在正確的軌道上,但有很多東西要知道——還有很多人們發現的錯誤的東西,你應該小心。

忘掉的東西

在您熟練使用Git之前,您需要了解一些東西。 這些虛假聲明 go 如下:

  • “分支很重要”:這沒有錯,但這也不對。 第一個問題是分支這個詞,它在 Git 中基本上是模棱兩可的。 如果我們堅持使用兩個詞的短語branch name ,我們會得到更有用的東西。 分支名稱很重要,但僅限於人類 Git 使用它們來幫助我們找到提交; 真正重要的是提交。

  • “遠程分支”:這個兩個詞的短語,如果有的話,比“分支”這個詞本身更糟糕 人們用它來表示至少三種不同的東西。 讓我們也避免使用這個短語。 Git 文檔使用術語remote-tracking branchremote-tracking branch name ,這是git branch -r列出的名稱。 這句話沒有那么糟糕,但其中的分支一詞毫無意義。 讓我們稱之為遠程跟蹤名稱

需要學習的東西

Git 中重要的是提交 了解這些關於提交的事情:

  • 每個都有一個唯一的 hash ID。 某個提交的 hash ID 表示提交。 沒有其他提交——在任何地方,在任何Git 存儲庫中——將具有hash ID。 提交(在任何Git 存儲庫中的任何位置)將具有hash ID。

  • 提交是在不同的 Git 克隆之間共享的內容。 分支名稱不共享 您的 Git 克隆具有您的分支名稱,而其他一些克隆具有分支名稱。 您可能使用相同的名稱,以使事情保持直截了當,但這取決於您(盡管 Git 會在這里提供幫助,因為這是很常見的事情)。

  • 每個提交由兩部分組成:

    • 提交的主要數據是所有文件的快照。 這些文件一直被凍結:它們以壓縮、只讀、僅 Git 和去重的形式存儲。 重復數據刪除處理的事實是,大多數時候,大多數新提交大多包含與前一次提交相同的文件。 當然,存儲在提交中的文件被凍結,甚至不能被非 Git 的程序讀取(更不用說寫入)這一事實是一個問題。

    • 提交的另一部分是它的元數據 這包括提交人的姓名、他們的 email 地址以及提交的日期和時間戳。 所有這些東西也是只讀的。 對於 Git 本身而言,至關重要的是,Git 將 hash ID 添加到此元數據中,之前的某個或多個提交的 ID。 我們稱這些為提交的父母

提交表單鏈; 分支名稱幫助我們(和 Git)找到提交

鑒於我們有一些簡單的提交序列:

... <-F <-G <-H

這里的每個字母代表一個實際的 Git hash ID,我們最終得到一個以提交H結尾的線性提交鏈。 如果我們知道H的實際 hash ID,我們可以讓 Git 提取此提交(見下文)。 或者,我們可以讓 Git 讀取H的元數據並向我們展示誰進行了提交......或者使用它來查找H的父提交G的實際 hash ID。

由於GH都持有快照,我們可以讓 Git 比較兩個快照。 所有匹配的文件都是無趣的,因為它們匹配。 任何匹配的文件都更有趣,我們可以讓 Git 找出它們的不同之處並向我們展示不同之處。 這樣,我們就可以看到我們改變了什么。 Git 不存儲更改:它只存儲快照。 但是我們可以將快照視為更改,因為提交有父級。

我們也可以讓 Git go 回到G ,並用它來找到F ,因此將G視為更改。 從那里,我們可以 go 回到F ,並使用它來找到更早的提交,等等。 但要做到這一切,我們需要鏈中最后一次提交的實際 hash ID。 這就是分支名稱的來源:像repo-branch1這樣的分支名稱只存儲一些 hash ID。 根據定義,存儲在名稱中的 hash ID 是分支中的最后一次提交。 Git 將從那里開始並向后工作。 在那之后是否有以后的提交也沒關系:

...--E--F   <-- br1
         \
          G--H   <-- br2

這里Hbr2中的最后一次提交(例如FG之后),而提交Fbr1中的最后一次提交。 通過F向上提交在兩個分支中,但br1F開始或結束(取決於你如何看待它)並向后工作,而br2H結束並向后工作。

提取的提交

因為提交是只讀的,我們實際上不能直接處理或使用它們。 我們必須選擇一些提交並將其設為當前提交 當我們這樣做時,Git 將 go 與該提交一起提取到工作區的所有文件,Git 將其稱為工作樹工作樹 這些是您可以查看和使用的文件。 它們是普通的日常計算機文件,您計算機上的每個程序都可以使用。 但它們實際上不在Git 中。

我們跑:

git checkout br2

(或 Git 2.23 或更高版本中的git switch br2 )。 Git 使用名稱br2來查找該分支的最后(或tip )提交(注意模棱兩可的詞,在這種情況下表示某些以H結尾的提交集)。 Git 然后從該提交中提取文件,以便我們可以查看和使用它們,並使該提交成為當前提交,同時將該分支名稱設為當前分支 我喜歡這樣畫:

...--E--F   <-- br1
         \
          G--H   <-- br2 (HEAD)

特殊名稱HEAD附加到分支名稱。 這就是“在分支上”的含義:名稱HEAD定位分支名稱br2 分支名稱本身定位提交, H ,它是 Git 提取的一個。

如果我們進行的提交, Git 將 package 生成快照,添加元數據,將新提交的級設置為當前提交H ,並使用所有這些來寫出新提交。 這為提交分配了新的、大而丑陋的隨機外觀——但實際上根本不是隨機的——哈希 ID,我將稱之為I 由於I的父母是HI指向H 然后 Git 只需將I的 hash ID 寫入當前名稱br2 ,給出:

...--E--F   <-- br1
         \
          G--H--I   <-- br2 (HEAD)

因此,分支名稱的特殊功能是,當我們創建它時,它會自動移動以指向新的提交 Git 通過將名稱HEAD附加到分支名稱來完成此操作。

Git 有其他名稱(例如標簽名稱和遠程跟蹤名稱)指向提交(通過存儲提交 hash ID),但您不能將HEAD附加到它們。

遠程跟蹤名稱和git fetch

遠程跟蹤名稱具有 forms ,例如origin/TLA1 :它們以遠程名稱開頭,例如origin 遠程名稱是您使用git remote add時使用的名稱; origin只是第一個標准 如果你使用git clone來運行git initgit remote add等等, git clone將使用origin 注意:您沒有使用git clone ,因此當您運行git remote add時,名稱將由您決定。

如上所述,您不能將HEAD附加到遠程跟蹤名稱。 此外,您通常不會自己創建這些名稱。 您可以使用git branch -r列出您現在擁有的那些,但如果不創建它們,您如何獲得它們?

最后一個問題的答案是git fetch命令創建它們。 git fetch命令非常復雜(有好有壞),我在這里肯定不會過多介紹,但我們可以這樣簡單地描述它:從中:

  • 首先,您的 Git 的 Git 列出了它們的所有分支名稱、標簽名稱和其他此類名稱。 這些帶有 hash ID — 主要是提交 hash ID,盡管標簽名稱有時會稍微復雜一些。

  • 然后您的 Git 會選擇這些名稱和 hash ID。 您 Git 可以判斷您是否有提交,因為每個 Git 對相同的提交使用相同的隨機外觀但非隨機的 hash ID 因此,您的 Git 會立即知道您是否有他們分支的提示提交。

    如果你不這樣做,你的 Git 會向他們的 Git 詢問他們的提交。 他們也提供提交的父母,您的 Git 會檢查您是否有這些提交。 通過這種擁有/想要的序列(通過一些重要的優化,避免每次都必須列出每個 hash ID),您的 Git 找出他們有哪些提交,您不需要,您需要,並要求他們.

  • 他們 package 完成所有這些提交並將它們發送給您。 這里的細節可能會有很大差異,但在通常情況下,您會看到“計數”和“壓縮”等,然后您的 Git 會收到一個 package 充滿提交和其他內部 Z0BCC70105AD279503E31FE7B3 對象。 您的 Git 然后將其全部保存在您的存儲庫中。

    您現在擁有了之前的所有提交,以及他們沒有的任何提交(除非您的 Git 不想要它們,例如單分支克隆)。

  • 最后,您的 Git 現在創建或更新您的遠程跟蹤名稱 對於他們擁有的每個分支名稱,您的 Git 會為您的存儲庫創建或更新相應的遠程跟蹤名稱。

這意味着您永遠不會直接獲得他們的分支名稱。 您獲取他們的分支名稱並將它們更改為您的遠程跟蹤名稱。 這充當您的 Git 分支名稱的memory 這些是由git fetch創建或更新的。 在您運行git fetch之前,您不會origin/TLA1

結論

重要的是提交 分支名稱和其他名稱可幫助您(和 Git)找到提交。

您可以通過運行git fetch遠程跟蹤名稱。 您告訴git fetch要調用的遙控器 您的 Git 調用該遠程並查看其分支並獲取其提交,除非您已經擁有它們。 然后您的 Git 會根據需要更新或創建遠程跟蹤名稱。 (旁注:您的 Git 不會在此處刪除“死”名稱,除非您告訴它,因此一旦他們刪除了某些分支名稱,您將留下陳舊的遠程跟蹤名稱。)

您可以隨時創建自己的分支名稱,但要創建名稱,您必須有一個提交以使其指向。 因此,您通常希望首先獲得他們最新的: git fetch然后是第二個 Git 命令。

另外: git pull意味着運行git fetch ,然后運行第二個 Git command 由於需要這兩個命令來做有用的事情,所以像git pull這樣的人會運行這兩個命令。 我不喜歡git pull因為我喜歡在這兩個命令之間插入命令,並且可能使用git pull為第二個命令提供的相對較薄的選擇集以外的東西,但這取決於你。

您需要先告訴 Git 跟蹤遠程存儲庫。 所以你必須做

git remote add origin <url>

接下來你可以告訴 git 只從遠程獲取一個分支

git fetch origin TLA1

然后就可以切換到分支

git checkout TLA1

將遠程添加到本地存儲庫,然后從中獲取。

git remote add REMOTE_NAME REMOTE_URL
git fetch REMOTE_NAME
git checkout -b branch_name REMOTE_NAME/branch_name

最后一個命令從遠程 ref 創建一個本地分支。

然后 git 分支應該顯示:

git branch

LOCAL1
LOCAL2
branch_name

暫無
暫無

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

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