一切都與 GitHub 上的遠程存盤庫同步。
然后我在 Sublime Merge 中重命名了一個本地分支(右鍵單擊 → 重命名分支)。
然后我推送了——這并沒有同步遠程倉庫,而是我現在有兩個相同的分支,一個是舊的,一個是新的。所以我通過 GitHub 洗掉了舊分支,因為我不知道如何從 Sublime Merge 中洗掉。
現在,當我嘗試引入 Sublime Merge 時,它??說:
Ihre Konfiguration gibt an, den Merge mit Referenz 'refs/heads/<old-branch-name>' des Remote-Repositories durchzuführen, aber diese Referenz wurde nicht angefordert.
通過谷歌翻譯的英文翻譯:
Your configuration says to merge with reference 'refs/heads/<old-branch-name>' of the remote repository, but this reference was not requested.
我能做些什么來解決這個問題?我想我必須從我的配置中洗掉舊的分支條目,但是如何以及在哪里?
uj5u.com熱心網友回復:
短版:用于git branch --set-upstream-to修復上游設定,例如:
git branch --set-upstream-to=origin/bract bract
(請注意origin/,在這種格式中,名稱的版本在等號之后,不帶空格;分支名稱本身是可選的,如果您將其省略,Git 將假定為“當前分支名稱”)。
更長:如何理解這里發生了什么
在 Git 中,分支名稱實際上并不重要。這意味著您可以隨時更改它們。但是這里有一些問題,因為每個 Git 存盤庫都有自己的(單獨的)分支名稱。更改一個存盤庫中的名稱不會影響另一個存盤庫中的名稱。
除了分支名稱之外,Git 還有其他型別的名稱,例如標簽名稱(通常用v, egv1.7或撰寫v2.12.1)和遠程跟蹤名稱。1 您可能至少熟悉或非常熟悉諸如origin/mainor之類的名稱origin/master,這些是這些遠程跟蹤名稱的示例。
每當你運行git fetch——包括git fetch那個git pull運行——你是在指示你的 Git 軟體,使用你的存盤庫中的資料,在某個 URL 呼叫一些其他的 Git 軟體。URL 本身通常是 Git 在您運行git clone以創建Git 存盤庫時保存的 URL。Git 會將該 URL 保存在 name 下origin。這個名字origin——實際上是可以改變的,但人們通常不會改變origin太多,如果有的話。
這個簡短的名稱,通常origin在這里,只是幫助您跟蹤 Internet 上某個地方“外面”有另一個 Git 存盤庫這一事實的一種方式。短名稱既存盤了 URL,以便您以后可以運行git fetch而不必自己記住它,也構成了遠程跟蹤名稱的基礎。
所以,當你運行時git fetch——包括git fetchthatgit pull runs和你最初創建存盤庫時運行的git fetchthat git clone——你的 Git 軟體會呼叫另一個 Git 軟體,它從某個現有的 Git 存盤庫中讀取。該 Git 存盤庫有自己的分支和標簽名稱。它甚至可能具有遠程跟蹤和/或其他型別的名稱。您的 Git 軟體可以看到所有這些名稱——或者至少,它們愿意顯示給你的所有名稱——以及它們附帶的 Git 哈希 ID。事實上,有一個命令可以用來轉儲所有這些:
git ls-remote origin
將在 處呼叫另一個 Git origin,讓它列出它會讓你看到的名稱,然后將它們全部列印出來而不實際對它們做任何有用的事情。
但是當你運行時git fetch,Git 使用相同的機制來查看它們的所有分支和標簽名稱,并使用它從它們那里獲取提交(如果啟用,則獲取標簽,因為它通常是默認設定的)。然后——一旦你的 Git從他們的提交集中添加了任何新提交到你的存盤庫——你的 Git 通常會更新你所有的遠程跟蹤名稱。這涉及創建新名稱(如果它們顯示您還沒有作為遠程跟蹤名稱的名稱),或者更新現有名稱(如果它們顯示您確實擁有的名稱)。
這意味著,如果您克隆一個存盤庫,在您克隆它時,它具有名為main、br1和的分支br2,您將在自己的克隆中獲得:
origin/main (corresponds to their main)
origin/br1 (corresponds to their br1)
origin/br2 (corresponds to their br2)
此時你沒有分支,這是在 Git 中作業的一種非常悲慘的方式(盡管可以做到)。因此,git clone現在根據您提供給的引數,在您的存盤庫中創建這三個分支名稱之一。如果您沒有給出論據,而大多數人大多沒有給出論據,那么您會得到他們的軟體推薦的名稱,通常是或. 2-bgit clone-bmainmaster
但是現在假設您使用git push洗掉br1托管站點上的名稱并將其替換為 name anch。如果現在運行git ls-remote origin,您將看到三個名稱main、br2和anch。這也是您的 Git 軟體將看到的內容,因此git fetch origin將創建一個anch, 拼寫為origin/anch. 這是您為他們的anch.
會發生什么br1? 沒有什么。 它仍然存在,作為陳舊的剩余物。您的 Git 軟體為它們現在擁有的分支名稱創建或更新適當的遠程跟蹤名稱,但不會為您的 Git 軟體之前創建的名稱清除死的名稱,這些名稱不再具有任何明顯的用途。
1 Git 現在相當一致地稱這些“遠程跟蹤分支名稱”,但在我看來,這里的分支一詞只是把事情搞得一團糟。這些名稱是“遠程跟蹤”,因此這部分是有道理的。他們跟蹤的是其他存盤庫的分支名稱,因此是名稱的其余部分 - 但由于它們在您的存盤庫中,并且實際上不是分支名稱,我認為完全省略分支一詞更有意義。它們是名稱,它們跟蹤——如“跟隨”——遠程的分支名稱,但它們根本不是分支名稱。
2要更改 GitHub 上的推薦,請使用 GitHub 的 Web 界面設定“默認分支”。要在 Bitbucket 上更改它,請使用 Bitbucket 的 Web 界面。要在 Google Hosting 上更改它......好吧,他們忘了給你一個改變它的方法!哎呀。但這是一般的想法:你不能在 Git 中做到這一點,你必須使用一些附加組件。這可能是 Git 中的一個錯誤,但考慮到這種方式已經持續了將近 20 年,它可能還會保持這種狀態一段時間。
分支名稱的特殊屬性
在 Git 中,所有不同種類的名稱都只包含一 (1) 個哈希 ID,或者更正式地說是物件 ID,一個大而難看的字母和數字字串,例如c3ff4cec66ec004d884507f5296ca2a323adbbc5. 這實際上只是一個非常大的數字的十六進制編碼,用于在 Git 的“物件資料庫”中定位物件,這是構成 Git 存盤庫核心的兩個資料庫之一(另一個資料庫是名稱-to-IDs 資料庫)。正是這兩個資料庫的組合使 Git 存盤庫作業;這兩個資料庫,加上一組最小的輔助檔案,是任何 Git 存盤庫的必要基本部分。
使分支名稱在 Git 中特別神奇的原因在于三個部分:
它被迫只保留一個提交哈希 ID。不允許使用其他型別的物件。(還有其他三種物件,例如,標簽名稱可以包含這四種中的任何一種。)
您可以使用
git checkoutor (從 Git 2.23 開始)來“打開”一個分支git switch。分支名稱支持其他名稱缺少的特定設定。
實際上,這里最關鍵的是第 2 項。“在”一個分支上是 Git 跟蹤最新提交的方式。每當您“在”某個分支上并進行新提交時,Git都會更新存盤的哈希 ID以使用新提交的新的、唯一的、明顯隨機的哈希 ID。Git需要提交的哈希 ID 才能找到該提交。分支名稱存盤最新提交的哈希 ID。提交本身存盤了較早提交的哈希 ID,因此通過查找latest,Git 可以找到較早的。
鑒于在您進行新提交時分支名稱將自動更新,這使得分支名稱可以查找所有提交。但由于這不是本答案/文章的目的,我們將在此停止,無需進一步解釋。相反,我們將繼續進行第 3 項,即設定。
任何一個特定分支名稱的設定包括:
git pull如果您選擇使用,您是否希望此分支名稱與git pull;進行“合并”或“變基” 和- 存盤庫中另一個分支的名稱,或在存盤庫中查找遠程跟蹤名稱所需的資訊。3
第一項是嚴格的git pull。第二項也被 git pull, 和git rebase和使用git merge。
git pull命令的意思是:
- 運行
git fetch,然后 - 運行我選擇的第二個命令,通常
git merge但有時git rebase.
因為它背靠背地運行這些,它實際上可以比單獨的每個命令知道更多的資訊(這意味著您會收到一條資訊模糊的錯誤訊息,正如我們將看到的那樣)。
3這個有趣的措辭的原因是,由于歷史原因,這種“上游”設定的實際編碼相當奇特。要參考存盤庫中的分支,設定為文字字串(句點)并設定為,其中和是它們出現在存盤庫中的兩個分支名稱。但是,要參考存盤庫中的遠程跟蹤名稱,這兩個設定為和where is the remote 和是在 remote上看到的分支名稱。然后通過默認提取設定中的 refspec(s) 確定的映射運行這些映射branch.B1.remote.branch.B1.mergerefs/heads/B2B1B2Rrefs/heads/B2RB2,由于篇幅原因,我不打算討論。這是瘋狂的復雜,??即使正常的效果就是,例如,分支作為main其origin/main上游。
git pull操作_
命令需要一git fetch兩條資訊,git mergeorgit rebase操作還需要多一條資訊。特別是,git fetch需要知道從哪個遙控器。我們是在做,或者也許,還是……?當然,結果幾乎總是如此(這是內置于的后備默認設定),但它想知道。git fetch git fetch origingit fetch rumpelstiltskingit fetch bruceorigingit fetch
第二個命令,無論是合并還是變基,至少需要知道一件事。它真正需要的是一個哈希 ID。它可以取一個名字:
git merge origin/br2
或者:
git rebase origin/br2
例如,兩者都可以正常作業origin/br2,當然前提是您有一個,但是在這兩種情況下,Git 都會將該名稱轉換為原始哈希 ID 以完成其作業。然后Git可以使用該名稱,例如,git merge將根據該名稱生成默認的合并訊息。但是,如果git pullis running git merge,則git pull生成自己的合并訊息并覆寫此默認值。
在任何情況下,這兩個資訊位都被編碼到分支的上游設定中。一個名為的分支的上游B通常是. 也就是說,如果你在你的 branch 上,你是根據你呼叫的 's做的,并且你打算將你的新提交提交給他們等等。origin/Bmainoriginmainorigin/mainmain
沒關系,當您br1根據br1您呼叫的分支創建分支時origin/br1,您會得到br1一個上游設定為origin/br1. 如果你運行,你會看到這個:
git branch -vv
(或者git branch --verbose --verbose如果你喜歡長拼寫)。但是,如果您隨后使用git push更改名稱,在另一個存盤庫中,從tobr1,anch然后運行:
git fetch
你的 Git 將帶來一個新名稱,anch并將其轉換為origin/anch. 如果您提前考慮,您還將本地重命名br1為anch:
git switch br1
git branch -m anch
(在 GitHub 或任何地方重命名分支之前或之后)。但是:您的分支,現在稱為anch,仍然說它的上游是origin/b1. 您已b1在本地重命名,并且 - 無論是使用 Web 界面還是 -您已在托管站點上git push重命名,但存盤庫中的上游設定只是一個特殊格式的字串,它沒有更改。b1
跑步:
git fetch --prune origin
告訴你的 Git:查找origin,使用它來獲取 URL,呼叫其他 Git 軟體,檢查分支名稱集,并清除我擁有的任何舊的過時名稱。那將拋棄你的陳舊origin/b1。但是您的anch分支仍然使用舊origin/br1的作為上游設定。所以現在你需要:
git branch --set-upstream-to=origin/anch
將當前分支(您現在稱為anch)的上游設定為您的origin/anch,這就是您所說的他們的 anch.
沒有這個,git pull認為它應該運行git fetch origin,然后使用對origin/br1. 由于沒有進行任何更新,因此git pull抱怨:
Your configuration says to merge with reference
'refs/heads/br1' of the remote repository, but this
reference was not requested.
(雖然實際上英文版與德文的反向翻譯有點不同)。
如果您運行git merge或git rebase不提供其他引數,您會收到類似(但有些不同)的投訴,例如:
fatal: No remote-tracking branch for refs/heads/br1 from origin
請注意,這需要首先清除“陳舊”名稱以獲取錯誤。如果我們不先跑git fetch --prune,就會有一個“陳舊的”origin/br1存在。rebase 或 merge 命令將使用存盤在該陳舊名稱中的哈希 ID!由此產生的變基或合并可能什么都不做,但總的來說這不是一個好主意。
一些小瑕疵git fetch
理想情況下,如果git fetch總是這樣做就好了--prune。你可以讓它這樣做:
git config --global fetch.prune true
這使得git fetch包括 run by 在內git pull,只要有可能就會自動執行修剪操作。這里有一些小 bug-ettes,雖然它們通常很安全:如果你遇到了一個奇怪的角落案例,只需git fetch再次運行以修復問題,省去任何導致你遇到小 bug 的額外引數。
還有兩件事我必須在這里提到:
- 非常舊的 Git 版本(1.8.4 之前)經常無法更新某些遠程跟蹤名稱。
- 有一些方法可以運行
git fetch,使其無法更新大多數遠程跟蹤名稱。
特別是,如果您運行:
git fetch origin main
你是在告訴你自己的 Git,無論其他 Git 為我們溢位的分支名稱串列如何,我們都應該只更新 我們的 origin/main. (這里的斜線是隱含的;這可以追溯到腳注 3 和其中提到的歇斯底里的葡萄干。)當您使用這種形式的 時, fetch 不能修剪(即使設定為git fetch也不會這樣做)。如果你的 Git 版本真的很舊,它甚至不會更新:它只會留下足夠的資訊讓這個舊版本的 Git 完成操作。fetch.prunetrueorigin/main.git/FETCH_HEADgit pull
請注意,當您git pull這樣運行時;
git pull
這運行git fetch,不是git fetch origin main,所以這兩種奇怪的情況不會發生。但是當你運行時:
git pull origin main
該git pull命令將整個引數集傳遞給git fetch,git fetch origin main因此在古代 Git 中,這兩種特殊情況(沒有修剪和沒有遠程跟蹤更新)確實發生了,而在現代 Git 中,一種情況(沒有修剪)發生了。
它如此復雜,我需要提到這一點,這是對 Git 的一種控訴。我發現 Git 非常有用,而且大部分都非常好,但它確實有很多含義 3 here的實體。
uj5u.com熱心網友回復:
我做了什么:
# Read eftshift0′s and torek′s comments
# Duckduckify "upstream" knowledge, find shorturl.at/tEXY3.
git help # too broad
git branch help # better
git branch --list # OK, renamed branch is active, but too terse
git branch --list --all # too terse
git branch --list --all --verbose # too terse
# make console full screen
git branch --list --all -vv # or `--verbose --verbose`
# OK, better
# lists deleted remote
# blue shows deleted remote
# thats wrong
git fetch --prune # eftshift0′s comment
git branch --list --all -vv # SUCCESS, deleted remote branch not listed
git branch --set-upstream-to=origin/new-correct-remote
# torek′s comment
git branch --list --all -vv # SUCCESS, correct blue remote branch
添加到以~/.bash_aliases供將來參考:
gitlistbranches() {
git branch --list --all -vv
}
gitsetremote() {
git fetch --prune
git branch "--set-upstream-to=origin/$1"
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/515215.html
標籤:混帐github升华
