簡體   English   中英

如何創建git Remote-Tracking分支

[英]How to create git Remote-Tracking Branch

他們說這很簡單

您可以簡單地通過將-u標志與“ git push”一起使用來告訴Git跟蹤新創建的遠程分支。

但這對我沒有用。

如何創建git Remote-Tracking分支

Git現在可以通知您有關“未推動”和“未推動”的提交。

這是我的:

$ git status 
On branch newfeature/v4-json
nothing to commit, working tree clean

與我的期望相比,引用以上文章

$ git status
# On branch dev
# Your branch and 'origin/dev' have diverged,
# and have 1 and 2 different commits each, respectively.
#
nothing to commit (working directory clean)

即,有關“未推動”和“未推動”提交的信息。
即,我希望看到與以下內容相同的內容:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

但是從上面的實際輸出中,您可以看到, 盡管我已經進行了幾次提交但我仍然無法看到到目前為止我已經進行了多少次提交

這是我所做的:

$ git push -u origin newfeature/v4-json
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (12/12), 1.87 KiB | 958.00 KiB/s, done.
Total 12 (delta 9), reused 0 (delta 0)
remote: Resolving deltas: 100% (9/9), completed with 9 local objects.
remote: 
remote: Create a pull request for 'newfeature/v4-json' on GitHub by visiting:
remote:      https://github.com/.../pull/new/newfeature/v4-json
remote: 
To github.com:xxx/yyy.git
 * [new branch]      newfeature/v4-json -> newfeature/v4-json
Branch 'newfeature/v4-json' set up to track remote branch 'newfeature/v4-json' from 'origin' by rebasing.

但是我沒有git從'origin'設置的遠程跟蹤分支'newfeature / v4-json':

A) git remote show origin根本不顯示我的newfeature的遠程跟蹤分支:

$ git remote show origin
* remote origin
  Fetch URL: git@github.com:go-easygen/easygen.git
  Push  URL: git@github.com:go-easygen/easygen.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branches configured for 'git pull':
    master             rebases onto remote master
    newfeature/v4-json rebases onto remote newfeature/v4-json
  Local refs configured for 'git push':
    master             pushes to master             (up to date)
    newfeature/v4-json pushes to newfeature/v4-json (up to date)

根據http://www.gitguys.com/topics/adding-and-removing-remote-branches ,以下是我想看到的內容

$ git remote show origin
* remote origin
  Fetch URL: /tmp/.../git/rp0
  Push  URL: /tmp/.../git/rp0
  HEAD branch: master
  Remote branches:
    master     tracked
    newfeature tracked
  Local branches configured for 'git pull':
    master     rebases onto remote master
    newfeature rebases onto remote newfeature
  Local refs configured for 'git push':
    master     pushes to master     (up to date)
    newfeature pushes to newfeature (up to date)

請注意,在“ Remote branches:部分中,除了master tracked外,還master tracked了一個newfeature tracked 根據上述文章,被跟蹤的 newfeature tracked稱為遠程跟蹤分支

B) git branch -a都不是:

$ git branch -a
  master
* newfeature/v4-json
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

那里只有一個remotes/origin/master遠程跟蹤名稱,而我期望更多。 例如(無關緊要,只是為了顯示具有更多遠程跟蹤名稱的情況),

$ git branch -a
* master
  remotes/origin/HEAD
  remotes/origin/master
  remotes/origin/v1.0-stable
  remotes/origin/experimental

C) git branch -vv也不是:

$ git branch -vv
  master             75369c3 [origin/master] - [*] allow ...
* newfeature/v4-json 8c98d9c - [*] update ...

我希望看到,

$ git branch -vv
  master             75369c3 [origin/master] - [*] allow ...
* newfeature/v4-json 8c98d9c [origin/newfeature/v4-json] - [*] update ...

此外,

git pull也不從遠程更新我的本地分支:

$ git pull
From github.com:xxx/yyy
 * branch            newfeature/v4-json -> FETCH_HEAD
Already up to date.
Current branch newfeature/v4-json is up to date.

$ git pull
From github.com:xxx/yyy
 * branch            newfeature/v4-json -> FETCH_HEAD
Already up to date.
Current branch newfeature/v4-json is up to date.

$ git pull
From github.com:xxx/yyy
 * branch            newfeature/v4-json -> FETCH_HEAD
Already up to date.
Current branch newfeature/v4-json is up to date.

就是說,無論我拉多少次,我都不會得到相同的輸出,

$ git pull
Already up to date.
Current branch master is up to date.

以上都是正常的。 我已經使用MS VS多次創建了Remote-Tracking Branch,其結果完全符合我的預期,而不是上面的預期。 但是,我不喜歡黑魔術,所以我想知道如何使用純git來做同樣的事情。

那么創建git Remote-Tracking Branch的正確方法是什么?

編輯以更新地址( git branch -agit branch -vv )輸出:是的,缺少某些內容 目前還不清楚到底出了什么問題,但我有一個猜測。 git push -u輸出的這一部分:

  * [new branch] newfeature/v4-json -> newfeature/v4-json Branch 'newfeature/v4-json' set up to track remote branch 'newfeature/v4-json' from 'origin' by rebasing. 

顯示您的Git將您的origin/newfeature/v4-json (分為兩部分)設置為newfeature/v4-json上游。 但是您的git branch -agit branch -vv輸出顯示不存在origin/newfeature/v4-json

我可以通過進行單分支克隆來重現此行為的關鍵要素。 使用git clone --depth= numbergit clone --single-branch將產生這樣的克隆。 這樣做的副作用是,您的Git將永遠不會為任何分支創建任何遠程跟蹤名稱, 除非您告訴Git所關心的那個分支。 如果這問題所在,則解決方法是將克隆轉換為普通(多分支)克隆。 (如果使用--depth創建單分支方面,則取消克隆該副本也是明智的。)

要查看您的origin克隆是否設置為單分支:

$ git config --get-all remote.origin.fetch

在普通克隆中,將打印:

+refs/heads/*:refs/remotes/origin/*

在選擇了分支master的單分支克隆中,將打印:

+refs/heads/master:refs/remotes/origin/master

它告訴您的Git: master創建一個遠程跟蹤名稱,而不是* (即所有分支)創建前者的遠程跟蹤名稱

取消origin克隆的單分支:

$ git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

(或直接編輯.git/config ,例如git config --edit ,這是我的首選方法)。 另請參閱如何“撤消”-單分支克隆?

要將淺層克隆轉換為完整(非淺層)克隆,只需運行:

$ git fetch --unshallow

請注意,盡管git clone默認將它們git clone --depth= number --no-single-branch在一起,但此操作與單分支無關(您可以在git clone時使用git clone --depth= number --no-single-branch覆蓋此操作)。 在2.15之前的版本中,沒有針對淺薄度的命令行測試; 在2.15或更高版本中,使用:

git rev-parse --is-shallow-repository

但在此之前,您必須測試文件.git/shallow的存在:

if [ -f $(git rev-parse --git-dir)/shallow ]; then
    echo true
else
    echo false
fi

模擬git rev-parse --is-shallow-repository

順便說一句,您查看的輸出存在問題。 您說您想將newfeature看作是遠程服務器上的一個分支,但這不會發生,因為需要存在newfeature/v4-json名稱,這排除了newfeature的存在能力。

(以下行的原始答案。)


 $ git push -u origin newfeature/v4-json 

這完全按照您的要求進行。 在您顯示的其余輸出中,一切都很好。 因此,尚不清楚您認為錯在哪里; 其實沒有錯。 我將解決您顯示的其他消息:

 # Your branch and 'origin/dev' have diverged, # and have 1 and 2 different commits each, respectively. 

下面。

這是什么意思呢? (長)

回顧一下Git的工作方式和一些Git特有的術語可能會有所幫助。 我認為,特別是,您使用的短語- 遠程跟蹤分支 -是一個詞,會引起誤解。 一個Git術語,所以我們應該理解人們在使用它時的含義,但這是一個不好的術語,這意味着人們會濫用它,如果您對某人的使用感到困惑,那么可能應該退一步並考慮一下這些事情再次發生。

首先,讓我們注意Git實際上就是關於commit的全部內容。 承諾是Git的存在理由 沒有提交,我們根本不會使用Git。 因此,讓我們看看什么是提交。

每個提交都包含文件,但不僅僅是一組文件。 它是快照中所有文件的快照, 1但它也包含一些元數據: 有關存儲數據的信息。 最明顯的是您在git log輸出中看到的內容:您的姓名和電子郵件地址,以及計算機對您進行提交的日期和時間的想法,以及為進行提交而保存的原因 ,即您的日志消息。 這些都是供您(或其他人)將來使用的:某天,也許明天,也許幾個月或幾年之后,您可以回顧一下您剛才所做的提交,並問自己: 我為什么要做 答案應該在您的日志消息中。

因為提交存儲文件(作為快照,時間凍結,不可變並且可以永久存在(或只要提交本身一直存在)),所以非常適合歸檔。 在將來的任何時候,您都可以回顧過去,並准確地查看當時保存的內容。 您無法更改:它是過去的,固定的,已凍結的時間。 稍后我們將看到,即使Git也無法更改它。

為了找到提交,Git需要一個名稱。 這些名稱不是分支名稱! 或者,更准確地說,您可以使用分支名稱開始,但這不是Git所需的名稱。 相反,任何提交的真實名稱是其哈希ID 每個提交的哈希值ID 似乎是隨機的,但實際上,它是上提交的全部內容的加密校驗,以提交數據的每一個位極其敏感:所有凍結的快照,並您的姓名和時間-stamp和您的日志消息。 這就是為什么您或任何人都不能更改提交的原因:更改任何內容都會更改哈希ID,然后您將擁有一個新的不同的提交。 在進行提交之前,沒人知道哈希ID是什么。 當時,它獲得了唯一的ID。 沒有人會將該ID用於其他任何提交! 沒有人可以改變什么提交:Git會知道,如果你嘗試,因為該ID不匹配了。 2

這個特殊的拼圖游戲有最后一兩個關鍵部分。 第一個是,在每個提交中,Git都將前一次提交的哈希ID(真實名稱)存儲為該元數據的一部分。 也就是說,Git不會只是保存您的姓名和時間等,同時也節省了您的使用使這個新提交的提交的原始哈希ID。 Git將此保存的哈希ID稱為提交的父級 這意味着每個提交都在向后看的鏈中指向其父提交。

例如,假設我們在存儲庫中只有兩個提交AB A是第一個提交,因此特意沒有父提交-這是特例。 但是B是由A制成A ,因此B指向A

A <-B

如果您提取提交B ,執行一些工作,然后進行新的提交C ,則新的提交將自動指向B

A <-B <-C

意味着Git只需要知道最后一次提交的表面上隨機的哈希ID。 在這種情況下,提交C 如果其實際的哈希ID是cba9876...或其他值,Git可以使用它來查找C內容 這些內容包括提交B的實際哈希ID。 然后,Git可以使用它來查找B ,其內容包括提交A的實際哈希ID。 Git可以使用它來查找A ,而A沒有父母,所以現在,Git終於可以停止向后工作。

分支提示提交(例如,由分支名稱標識的C向后工作的過程在Git中至關重要。 歷史就是這樣存在的 Git存儲庫中的歷史記錄提交,這些提交通過這些向后的箭頭連接。 您從頭開始,一次走動一次,遍歷歷史,按照父箭頭查看可以到達的位置。

分支名稱和其他此類名稱顯示出來時,這是最后一個拼圖碎片輸入圖片的地方。 讓我們暫停一下,在這里結束腳注,然后深入研究分支名稱和圖形繪制。


1 Git實際上是從索引制作快照的,但是我們不會在這里介紹這些細節,除了說要快照的內容(對於該提交,永遠凍結的時間)就是當時索引中的內容,這至少可能與您在工作樹中看到的內容有所不同。

2 Git實際上會在方便或適當的時候進行檢查。 這會自動檢測到Git存儲庫的意外損壞,例如在您嘗試將其存儲在Dropbox中時發生的情況。Dropbox有時會四處修改(和Git的)背后的文件,而Git會抓住它。 不幸的是,很少有修復損壞的存儲庫的好方法-而是,Git傾向於依賴Git存儲庫在各處復制的想法。 您可能在其他地方有一份不錯的副本,因此您完全可以將其扔掉。


分支名稱查找提交哈希ID

任何現有的存儲庫(好吧,除了一個完全空的,新鮮的, 沒有提交的新存儲庫之外的任何其他存儲庫)都具有一組提交。 這些提交構成了我們剛剛看到的向后看的鏈,例如:

A <-B <-C

我們和Git需要某種方式來記錄該鏈中最后一次提交的哈希ID。

Git實現此目標的方法是Git稱為referencerefs 裁判的形式很多,但三巨頭是:

  • 分支名稱,如master
  • 遠程跟蹤名稱,例如origin/master (Git稱這些遠程跟蹤分支名稱遠程跟蹤分支 ,我認為這是一個壞名字;我已改用遠程跟蹤名稱 ,我認為這很難弄錯。)
  • 標簽名稱,如v1.3

它們實際上都是由相同的基礎技術實現的,但在這里我們將它們視為單獨的名稱形式。 分支名稱具有特殊屬性; 所有其他名稱都缺少此屬性。

這些名稱之一的含義非常簡單:它只是Git對象的實際原始哈希ID,通常是提交。 3因此,像master這樣的分支名稱指向分支最后一個提交-在此圖形中提交C

A--B--C   <-- master

請注意,相互連接的箭頭從子對象中出來並指向(不可變的)父對象,這為我們提供了這種向后遍歷的方法。 我們不必費心將它們插入。但是, 分支名稱中的箭頭會更改

當我們向master添加新的提交時,Git會自動更新名稱master來保存新提交的哈希ID。 因此,如果我們現在創建一個新的提交,則新的提交D將指向C

A--B--C   <-- master
       \
        D

但是Git會立即調整master使其不指向C而是指向D

A--B--C--D   <-- master

由於D指向C ,我們仍然可以找到所有提交:我們從結尾開始,然后像往常一樣向后工作。 現在, C是此過程中的第二個提交,而不是第一個。


3分支名稱必須包含提交對象哈希ID,而標記名稱則更靈活。 我們在這里不需要關心這一點。 因為遠程跟蹤名稱的值是分支名稱中復制的,所以遠程跟蹤名稱也僅包含提交哈希ID。


分支名稱是每個存儲庫專用的,但是存儲庫彼此通信

Git是一個分布式版本控制系統。 這意味着每個Git存儲庫都是一種獨立的孤島,它需要的所有內容都在該存儲庫本地。 如果有許多提交多個分支機構,他們在一個存儲庫:

A--B--C--D--G--H   <-- master
          \
           E--F   <-- dev

為了使Git真正有用,我們定期使用Git與其他Git用戶交換工作。 為此,我們交換了commits 由於這種密碼校驗和技巧,它們的哈希ID在所有地方的所有 Git中都是通用的。 給定快照和元數據, 每個地方的每個 Git都會計算相同的哈希ID 因此,如果我的存儲庫具有這樣的提交AH (請記住,這些單個大寫字母代表着唯一的,大的丑陋哈希ID),並且我連接到您的存儲庫並且具有提交H ,則您的存儲庫還必須具有與礦。

如果您沒有提交H ,那么我有您沒有提交。 如果你有一些犯I還是J有一個承諾, 不知道。 無論哪種方式,我們的Gits都可以交換哈希ID來查看誰擁有什么。 發送提交的人將發送它們,接收提交的人將接收它們,發送者將向接收者提供任何需要的提交。

假設您正在接受我的新委托。 我有新的提交IJ ,而我的新提交J名稱可以記住其哈希ID。 我的存儲庫中,我有:

A--B--C--D--G--H   <-- master
          \
           E
            \
             I--J   <-- dev

無論出於什么原因,我都沒有像 dev 那樣提交F 相反,在(共享)提交E之后,我對我的dev進行了IJ提交。

這是遠程跟蹤名稱的來源

您的Git接受了我的承諾IJ 我的承諾是I有父母E 因此, 您的存儲庫現在具有以下內容:

A--B--C--D--G--H   <-- master
          \
           E--F   <-- dev
            \
             I--J   <-- ???

您的 Git存儲庫將使用什么名字來記住我的提交I 最好不要使用dev :如果您的Git使您的dev指向commit I ,您將如何再次找到commit F 請記住,它具有一個顯然是隨機的哈希ID。 您將永遠無法猜測

因此,您的Git所做的就是使用遠程跟蹤名稱來記住我的分支。 您的Git會這樣做:

A--B--C--D--G--H   <-- master, origin/master
          \
           E--F   <-- dev
            \
             I--J   <-- origin/dev

(假設我的master指向H )。

存儲庫中的origin/masterorigin/dev名稱是您的遠程跟蹤名稱 ,記住了masterdev 4此外,假設您現在查詢Git,要求它在Git使用的普通向后走行方法中,比較devorigin/dev可以到達的提交集。

dev開始,將要訪問的提交是F ,然后是E ,然后是D ,依次類推回到A origin/dev ,將要訪問的提交是J ,然后是I ,然后是E ,然后是D ,依次類推回到A 哪些提交是哪個步行特有的? 您從dev到達的提交數量是您從origin/dev不能到達的提交數量,反之亦然?

算出這些,然后與您的Git告訴您的內容進行比較:

 # Your branch and 'origin/dev' have diverged, # and have 1 and 2 different commits each, respectively. 

實際上,這里的拼圖游戲還缺少另一部分,當我們在下面談論git push時,我們將在上一節中對其進行簡要介紹。


4 Git有時稱其為跟蹤,而不是記住 ,但這是Git嚴重濫用單詞的另一個地方。 我已經在遠程跟蹤中使用了它,但是至少在這里它是帶連字符的,並用這個詞作為形容詞修飾remote


git pushgit fetch不同

上面的過程是您的Git從origin的Git上找到的分支名稱創建遠程跟蹤名稱的過程,它特定於git fetch 當你有你的Git調出的Git在它發生origin ,把他們提交給

當然,您可以讓您的Git在origin調用他們的Git並發送提交。 這就是git push操作,非常相似。 您的Git告訴他們的Git您所擁有的提交,而他們沒有。 讓我們畫一些。 我們將從此開始:

A--B--C--D--G--H   <-- master, origin/master
          \
           E--F   <-- dev
            \
             I--J   <-- origin/dev

現在,我們將運行git checkout mastergit checkout -b newfeature/v4-json或更簡單的命令:

git checkout -b newfeature/v4-json master

現在,我們有:

A--B--C--D--G--H   <-- master, origin/master, newfeature/v4-json (HEAD)
          \
           E--F   <-- dev
            \
             I--J   <-- origin/dev

我們已經將特殊名稱HEAD附加到newfeature/v4-json以記住添加新提交時更新哪個分支名稱。

現在,我們將創建一個新提交。 它可能不止一個,甚至沒有一個 ,但我們只創建一個用於說明。 新的提交有一些大的丑陋的哈希ID,但我們在這里將其稱為K

                 K   <-- newfeature/v4-json (HEAD)
                /
A--B--C--D--G--H   <-- master, origin/master
          \
           E--F   <-- dev
            \
             I--J   <-- origin/dev

現在,我們將使用以下命令讓您的Git在origin調用Git:

git push -u origin newfeature/v4-json

您的Git撥號他們的Git並宣布您已提交KH 5他們沒有K但是他們有H所以他們讓您的Git通過其快照和元數據發送提交K 您的Git可以告訴您,由於它們具有H因此它們也具有GD及其之前的所有內容,因此您只需向他們發送K及其內容。

然后,最后,您的Git詢問他們: 請,現在,如果可以,請設置名稱newfeature/v4-json指向commit K 請注意,您沒有讓他們設置xpt/newfeature/v4-json或類似的東西。 您讓他們設置了分支! 他們實際上沒有newfeature/v4-json ,因此他們可以設置一個。 他們做到了! 現在, 他們的存儲庫中有一個newfeature/v4-json ,指向commit K

你的Git現在創建 遠程跟蹤名稱 origin/newfeature/v4-json ,指着承諾K ,記住他們的 newfeature/v4-json ,指向提交K 6但這僅表示您的圖形中有一個額外的名稱 ,如下所示:

                 K   <-- newfeature/v4-json (HEAD), origin/newfeature/v4-json
                /
A--B--C--D--G--H   <-- master, origin/master
          \
           E--F   <-- dev
            \
             I--J   <-- origin/dev

由於使用-u選項,您的Git也會立即運行:

git branch --set-upstream-to=origin/newfeature/v4-json newfeature/v4-json

這將為分支newfeature/v4-json設置上游設置。 您的每個分支都可以具有 (1)個上游設置,以這種方式使用它非常典型。 請參閱為什么我總是需要執行--set-upstream`嗎? 更多。


5您的Git 可以告訴他們有關F ,但前提是您在這里說過git push origin dev 使用帶有或不帶有-u git push origin newfeature/v4-json ,您告訴Git:根據需要告訴他們有關KHGDCB和/或A提交。 您其他未共享的提交則有意保留為私有。

6請記住,由於哈希ID的魔力,提交K在世界各地的每個 Git中都是通用的。 每個 Git通過其哈希ID都具有K ,然后就是提交; 或者根本沒有K ,所以沒關系。

(這並不一定是100%的保證。假設的哈希ID K實際上是b5101f929789889c2e536d915698f58d5c5c6b7a ,這是在Git倉庫的Git的本身提交的哈希值ID。如果你從來沒有你的 Git倉庫連接到一個Git倉庫GIT中,它是好的,您和他們具有相同的哈希ID的不同提交,但是如果您確實將Git存儲庫連接到Git的Git存儲庫,則會發生一些不太理想的事情。簡短的版本是您不會Git的提交,而他們卻沒有得到您的支持:這兩個倉庫現在根本無法合並,這對您和維護Git的人來說都完全可以,但另請參見新發現的SHA-1碰撞對您的影響git?

暫無
暫無

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

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