[英]How to automatically remove remote-tracking branch when the corresponding local branch is removed using git
[英]Are their names the same: a local-tracking branch, the corresponding remote-tracking branch, and the corresponding remote branch being tracked?
遠程跟蹤分支的名稱和跟蹤的相應遠程分支是否必須相同?
如果它們可以有不同的名稱,那么git fetch
如何匹配這兩個分支呢? ( git fetch
的典型refspec
是+refs/heads/*:refs/remotes/remote/*
)
如果我是正確的,給定遠程跟蹤分支,我們可以創建一個與之關聯但具有不同分支名稱的本地跟蹤分支。 (通過git checkout
的-b
選項)
此外,如果跟蹤的遠程跟蹤分支和相應的遠程分支的名稱相同, git push
如何匹配本地跟蹤分支和遠程分支? ( git push
的典型refspec
是+refs/heads/*:refs/heads/*
)
遠程跟蹤分支的名稱和跟蹤的相應遠程分支是否必須相同?
不會。但是,讓它們不匹配會導致很多痛苦(我沒有在推動方面進行測試)。
如果它們可以有不同的名稱,那么git fetch如何匹配這兩個分支呢? (
git fetch
的典型refspec是+refs/heads/*:refs/remotes/remote/*
)
你可能有多個fetch =
行,所以你可以這樣做:
[remote "strange"]
fetch = +refs/heads/master:refs/remotes/strange/surprise
fetch = +refs/heads/other:refs/remotes/strange/surprise2
但請注意,你不能再在任何額外的fetch refspecs的左邊使用refs/heads/*
,因為那將匹配master
和other
並且(可能)將它們映射到除surprise
和surprise2
之外的名稱,並且git fetch
aborts with這種情況下的錯誤消息。 這有效地強制您列出您希望從給定遙控器復制的每個refs/heads
名稱(在這種情況下strange
)。
(正如我所說的,我沒有用push來測試它,我不知道push是否遵循與fetch相同的映射規則。最近有一些變化,大約2.5左右,以更好地處理“三角形”工作流程例如,你從localmirror
獲取並推送到centralserver
。其中一個變化是為推送遙控器添加相同類型的名稱映射。據推測,在這個新代碼進入之前,做這種推動帶來了更多的痛苦,甚至可能沒有三角形工作流程;並且可能現在它工作得更好....)
我們可能稱之為“愚蠢的重命名技巧”,我的建議是:不要使用它們。 :-)我認為它們可以與大多數命令一起正常工作,並且與其他命令一起失敗,但我不能指出任何特定的失敗例子(只是模糊的回憶我以前做過的事情)。
如果我是正確的,給定遠程跟蹤分支,我們可以創建一個與之關聯但具有不同分支名稱的本地跟蹤分支。 (通過git checkout中的-b選項)
是; 這適用於各種本地工作。 同樣,我會避免使用“本地跟蹤分支”這個短語,並且只是說“帶有上游的本地分支”,因為這是git文檔從大約1.7開始移動的方向(見下文)。
請記住,“本地分支$branch
的上游”由以下產生:
git config --get branch. $branch .remote
獲取遠程名稱git config --get branch. $branch .remote
git config --get branch. $branch .remote
,和 git config --get branch. $branch .merge
映射branch-name git config --get branch. $branch .merge
git config --get branch. $branch .merge
通過該遙控器的fetch =
git config --get branch. $branch .merge
。 因此,假設我們已經創建了兩個本地分支test1
和test2
並具有以下內容:
$ git config --get branch.test1.remote
origin
$ git config --get branch.test1.merge
refs/heads/test
$ git config --get branch.test2.remote
origin
$ git config --get branch.test2.merge
refs/heads/test
test1
和test2
引用了refs/heads/test
,它是另一個 git資源庫中一個分支的名稱,它將通過名稱origin
來定位:這就是為什么我們需要通過fetch =
map來運行它們origin
。
在沒有愚蠢的重命名技巧的情況下,“映射通過”部分保留了分支名稱部分( refs/heads
之后的所有內容)不變,只是替換了中間位,因此refs/heads/test
成為refs/remotes/origin/test
。 這很容易做出假設。 我相信一些懶惰的腳本編寫者(包括我自己過去)可能已經使用了這段shell腳本代碼:
fullbranch=$(git rev-parse --symbolic-full-name $branch) || exit 1
remote=$(git config --get branch.$branch.remote)
rmtbranch=refs/remotes/$remote/$branch
它不僅假設缺乏愚蠢的重命名技巧,它甚至假設如果我們在分支test1
,上游必須是origin/test1
,而不是origin/test
。 略微不那么懶惰的腳本編寫者(包括我自己過去)然后必須修復他們的腳本,例如:
fullbranch=$(git rev-parse --symbolic-full-name $branch) || exit 1
remote=$(git config --get branch.$branch.remote)
theirname=$(git config --get branch.$branch.merge)
rmtbranch=refs/remotes/$remote/${theirname#refs/heads/}
現在假設origin
上的refs/heads/test
映射到本地存儲庫中的refs/remotes/origin/test
。
添加愚蠢的重命名技巧意味着我們根本無法輕易找到實際的上游名稱,但各種命令(例如, git merge
, git rebase
)會自動找到正確的上游名稱。 為了使腳本更容易,git 1.7.0版增加了@{upstream}
符號:你現在可以簡單地寫$branch @{upstream}
。 git解析器為您查找上游,上面(損壞的)腳本片段可以重寫為:
rmtbranch=$(git rev-parse --symbolic-full-name $branch@{upstream}) || exit 1
這對於fetch來說都很好,但是推送呢? 好吧,如果你正在推送你正在推送的同一個遙控器,你就是做同樣的事情。 但是你可以為任意數量的原因,1拆起來:從存儲庫中取出F
推到倉庫P
。 在這種情況下,我們可能需要F
和P
不同映射。
Git 2.5引入了@{push}
,正如VonC在一些早期的SO線程中所指出的那樣,我無法隨意找到,並在此github博客中發布 。 新的@{push}
表示法只是從使用上游提取切換到使用推送上游,即使用P
映射而不是F
映射。
還有一個很好的問題,這是你最后一個問題:
此外,如果跟蹤的遠程跟蹤分支和相應的遠程分支的名稱相同,git push如何匹配本地跟蹤分支和遠程分支? (git push的典型refspec是
+refs/heads/*:refs/heads/*
)
我對git 2.5的回答是新的推送內容:我確實不知道,但是你的“典型refspec”不再是默認值(因為git 2.0)。 當您運行git push
沒有的Refspec參數,git的查找你的push.default
設置(與一群多個可選的設置一起,但push.default
實際上是要求2)。 它有五個可能的值,只有其中一個 - 不是refs/heads/*:refs/heads/*
的默認值。
其中一個設置是upstream
,該設置通過map函數運行當前分支的merge
設置(可能是在git 2.5及更高版本中,通過新的單獨推送映射(如果存在),或者通過獲取映射)。
1一個原因是使用拉取請求存儲庫,如鏈接的github博客文章中所示。 另一種方法是從本地鏡像獲取(如在大型企業設置中使用本地鏡像用於各種分支機構),但是推送到單個中央服務器(公司指定的“主”站點,所有本地鏡像實際上都是鏡像)。
2如果你沒有設置push.default
,git會發出很多煩人的文字。 關閉它的最好方法是設置push.default
,這意味着你需要(在某種意義上)“設置”它。 而且,自從git 2.0以來,默認設置(如果你還沒有設置)很simple
,禁止愚蠢的重命名技巧。
refspec
至於你說其refspec
它位於您的.git / config文件中。
git配置文件包含有關refspec
的信息
為了看到你所描述的內容,請執行以下操作:
// Checkout master
git checkout master
// rename the master branch to a new name
git branch -m <old name> <new name>
// View the .git/config file and you will see the the new branch is still
// pointing (tracking) to the master branch, just like you described
使用refspec
您可以控制pull/push
將引用哪個分支。
git branch -u <upstream>/<branch name>
當git push [$there]
沒有說要推送什么時,我們到目前為止已經使用了傳統的“匹配”語義(只要那里已經有相同名稱的分支,所有分支都被發送到遠程)。 在Git 2.0中,默認是現在的“簡單”語義,它推動:
只有當前分支到具有相同名稱的分支,並且僅當當前分支設置為與該遠程分支集成時,如果您正在推送到同一個遠程獲取; 要么
只有當前分支到具有相同名稱的分支,如果您要推送到通常不從中獲取的遠程。
您可以使用配置變量push.default
來更改此設置。
如果您是想要繼續使用matching
語義的老計時器,則可以將變量設置為“匹配”,例如。 閱讀文檔了解其他可能性。
來自@codeWizard的答案是完整而完整的答案,但簡單的英語答案(基於您對其答案的評論問題)是:
1真的是兩個問題。 第一個答案是:不,它們不必具有相同的名稱。 第二個答案是: fetch
實際上並不映射本地和遠程分支。 所有fetch
(使用您的示例 - 默認值)都會詢問遠程的refs/heads/*
列表以及關聯的blob,並使用遠程名稱將refs存儲在refs/remotes/*
root中。
2本地分支到遠程分支的映射由使用顯式的pull
和fetch
調用控制,或者在.git/config
設置所有內容。 在git/config
,pull行為由$branch.merge
控制,但push由push.default
控制:默認情況下,它將推送到遠程上與本地相同的分支名稱。 如果將其設置為upstream
那么它將使用$branch.merge
作為推送目標。
演練:
mkdir t1 && cd t1
git init
touch file
git add file
git commit -a -m "remote"
cd ..
git clone t1 t2
cd t2
git branch -a # you should see 'master' and 'origin/master'
git branch -m master local
git pull # Should say "Already up-to-date"
git branch -a # you should now see 'local' and 'origin/master'
git push # damn! It pushed 'local' to 'origin/local'!
git push origin :local # delete 'origin/local'
git config push.default upstream # tell git to use 'local.merge' as the push target
git push # Now it should say "Everything up-to-date"
畢竟這個你的t1
配置應該是這樣的:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
t2
應如下所示:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = /nas/src/t/t1
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "local"]
remote = origin
merge = refs/heads/master
[push]
default = upstream
我知道這是一個老問題,但明確的答案是正確的git-config手冊頁(輸入git help config
或man git-config
)。 關於如何使用以下信息的示例就在報價之后:
push.default
如果沒有明確給出refspec,則定義git push應采取的操作。 不同的值非常適合特定的工作流程; 例如,在純粹的中心
工作流(即獲取源等於推送目標),上游可能就是你想要的。 可能的值是:
什么都沒有 - 除非明確給出refspec,否則不要推送任何東西(錯誤輸出)。 這主要是針對那些希望通過永遠存在而避免錯誤的人
明確。
·current - 推送當前分支以更新接收端具有相同名稱的分支。 適用於中央和非中央工作流程。
·上游 - 將當前分支推回到分支,該分支的更改通常集成到當前分支(稱為@ {upstream})。 僅此模式
如果您要推送到通常從中拉出的相同存儲庫(即中央工作流),這是有意義的。
·簡單 - 在集中式工作流程中,像上游一樣工作,如果上游分支的名稱與本地分支不同,則可以更加安全地拒絕推送。
當推送到與您通常拉出的遙控器不同的遙控器時,請作為當前工作。 這是最安全的選擇,適合初學者。
此模式已成為Git 2.0中的默認模式。
·匹配 - 推送兩端具有相同名稱的所有分支。 這使得您要推送的存儲庫記住將被推出的分支集
(例如,如果你總是在那里推動maint和master而沒有其他分支,你推送的存儲庫將擁有這兩個分支,以及你的本地maint和master
將被推到那里)。
要有效地使用此模式,您必須確保在運行git push之前准備好推出所有要推出的分支,作為整個點
此模式允許您一次性推送所有分支。 如果你通常只在一個分支上完成工作並推出結果,而其他分支則是
未完成,這種模式不適合你。 此模式也不適合推入共享中央存儲庫,因為其他人可能會在那里添加新的分支,或者
更新控制范圍之外的現有分支的提示。
這曾經是默認值,但不是因為Git 2.0(簡單是新的默認值)。
因此,要將git設置為適合您的配置,請輸入:
git config push.default nothing
用您的首選配置替換nothing
。 如果您希望它是全局的(本地計算機上的所有存儲庫),請添加全局選項:
git config --global push.default nothing
回答你的問題:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.