因為我的回購git branch -vv回傳以下
dev 5eed80e [origin/dev: behind 1] Create NeweestFileBaby
dev2 9a50723 commiting first1 change
* main 8898177 [origin/main] Create NewDev
所以我在當地的main分店結賬
然后我在 github中的遠程dev分支中進行了更改,然后我做了一個實驗
git fetch
在這一點上,我不希望從遠程獲取更改,dev因為我的本地main分支設定為跟蹤遠程更改,main但出于某種原因,它確實從遠程獲取更改dev,我再次在本地簽出main。
你能告訴我為什么會這樣嗎?
這很有趣,因為git push這種邏輯可以正常作業,因為我只能將 cahnges 從設定在各個遠程分支上游的各個本地分支推送到我各自的跟蹤分支。
uj5u.com熱心網友回復:
首先附注:“未跟蹤的分支”在這里是錯誤的短語。
Git 的術語不好,因為:
- 動詞軌道適用于檔案:某個檔案是tracked還是untracked,取決于該檔案此時是否出現在 Git 的索引中;但
- 動詞track適用于分支名稱,因為
B上游設定為的分支U被稱為trackU。
這兩個概念完全不同。第一個意味著被跟蹤的檔案將在下一次提交中(如果它當時仍然被跟蹤),而第二個意味著將報告git status可從Band到達的不同提交,U并且如果是當前分支。git mergegit rebaseUB
在其他情況下,我們對這個問題很熟悉:例如,set這個詞,即使被視為一個名詞或一個動詞(“在餐桌上設定一個地方”),也有很多含義;當被視為形容詞時,它還有另一組。但至少對于 Git,曾經有人希望我們不必處理這種瘋狂。如果一個分支的上游只被稱為“上游”,我們不需要額外的track含義。但近 20 年過去了,我們仍然擁有這兩個術語。(當然,上游這個詞也有點問題,但我們現在不要去那里。)
git fetch但是這里和之間有兩個很大的不對稱性git push:
這很有趣,因為
git push邏輯型別可以正常作業,因為我只能將更改從各自的本地分支推送到各自的跟蹤分支,這些本地分支在上游設定到各自的遠程分支。
從技術上講,您推送提交(不是更改,因為提交是快照加上元資料),但是是的:git push,沒有額外的引數,告訴 Git:
- 找出你現在“在”哪個分支(如
git status所說on branch main或其他); - 使用此分支的上游設定來確定遠程(例如,
origin)和該遠程上的分支名稱;和 - 實際上,運行,假設設定為or 。
git push remote branchpush.defaultsimplecurrent
請注意,使用push.defaultset to upstream,這里的效果是相反的,即分支可以在遠程上具有不同的名稱,但是使用and ,推送會在遠程上使用相同的名稱。設定為時,此處的行為是 Git 版本 1 中的行為:等效于,尚未發現它非常有用,但為了向后兼容而保留。git push remote branch:reverse-map-of-upstreamsimplecurrentpush.defaultmatchinggit push remote :
但是,使用git fetch時,默認仍然使用第 1 步和第 2 步的一半:Git 將從當前分支找出正確的遠程(或使用硬編碼后備origin,如果失敗)。但在那之后,Git 使用設定(這是一個多值配置設定,因此可以列出多個條目)。這些提供了 refspec 引數,上面的-for - 是單個分支名稱或一對以冒號分隔的分支名稱,用于兩個推薦值(是非推薦值,并導致失敗)。remote.remote.fetchgit pushmatchingnothinggit push
此處的默認值origin(如果您尚未設定)為:
refs/heads/*:refs/remotes/origin/*
請注意此處的兩個“類似 glob 的”星號*字符。此 refspec 表示匹配遠程上的所有分支名稱,并將每個分支名稱復制到本地遠程跟蹤名稱。因此,我們將git fetch 所有來自 的新提交origin,都帶入我們的本地存盤庫,然后我們更新所有遠程跟蹤名稱。refs/remotes/origin/whatever
效果是這git fetch意味著從 獲取所有分支origin,這正是您所看到的。遠程跟蹤名稱的更新由 refspec 暗示refs/heads/*:refs/remotes/origin/*(前導 設定“force”標志,因此即使操作不是快進操作,每個名稱也會更新)。
請注意,運行:
git fetch origin main
將限制git fetch操作,因此,盡管在originURL 串列中 Git 軟體有許多分支名稱,我們只帶來更新origin/main遠程跟蹤名稱所需的那些新提交。我們的 Git 軟體將這些新提交添加到我們的物件資料庫中。奇怪的是,盡管沒有冒號并且refs/remotes/origin/main——我們沒有運行——我們的git fetch origin main:refs/remotes/origin/mainGit 現在繼續更新我們的origin/main. 但為什么?
答案在于困擾著同樣的向后兼容性問題,git push這matching意味著git push使用冒號 refspec。在這里不討論所有無聊的歷史,讓我們注意git fetch現在(從 Git 1.8.2 開始)“機會性地更新”遠程跟蹤名稱,如行中配置的那樣,無論您是否提供特定的 refspec。remote.remote.fetch
這里的底線是:
git fetch origin
從 獲取所有配置的提取分支,origin并且“所有配置的提取分支”默認為“所有分支”。有一個--all標志git fetch,但它意味著所有遙控器:它對要獲取哪些分支沒有影響。然后,還有術語問題:我們實際上并沒有獲取分支。我們取提交。我們只是使用名稱找到要獲取的提交,這些名稱可能是分支名稱。這些是遠程上看到的分支名稱。提交進入我們自己的本地 Git 物件資料庫,然后 Git 更新(或不更新)通過 refspec 引數指定的遠程跟蹤名稱。
未編號的腳注
refspec實際上是一對由冒號分隔的名稱:,并且可以選擇以加號作為前綴 。名稱可以是分支名稱或標簽名稱(縮寫)或完全拼寫,例如,refs/heads/main或refs/tags/v1.2。在任何自動代碼中進行完整的拼寫都是明智的,因為 Git 嘗試將部分名稱與全名匹配可能會產生意外。冒號左邊的名字是源,forgit push是本地的,forgit fetch是遠程的。冒號右邊的名字是destination,forgit push是remote,forgit fetch是local。如上所述,加號設定該--force特定參考的標志。Refspecs 可以使用 glob*以有限的方式;必須出現在*兩邊。匹配的限制*在某些時候得到了改進,例如, refs/heads/pr-*:refs/remotes/pr-*如果你愿意;在此*之前必須匹配“整個組件”部分(即,就在斜線之前或之后)。
我稱之為遠程跟蹤名稱(origin/main或者,完全拼寫出來refs/remotes/origin/main),現代 Git 檔案稱為遠程跟蹤分支名稱。這些不是分支名稱,因為分支名稱以refs/heads/.
對于從多個遙控器獲取,我建議使用git remote update而不是git fetch. 這部分是因為古代 Git 需要它,但我認為總體上代碼得到了更好的維護。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/529835.html
標籤:混帐github
