簡體   English   中英

git pull 是否更新所有跟蹤的分支?

[英]Does a git pull update all tracked branches?

假設我在本地跟蹤 3 個遠程分支, masterbranch1branch2

如果我目前在master分支上, git pull fetchmerge每個分支上的更改?

我想我也可以做一個實驗……

簡短的回答是“不”——或者甚至“不和是”,如果人們只看到你的問題的標題——但這有點誤導。

pull 命令允許選項,其中許多選項具有有趣(且令人困惑且可能非常不友好)的效果。

邊欄:確保您正確理解Git 文檔所稱的遠程分支、遠程跟蹤分支和跟蹤分支之間區別,以充分利用以下解釋。 請注意,這些是 Git(和 git-scm.com)使用的術語。 在我最初寫下這個答案很久之后,我發現這些術語只會混淆人們——包括我!——而現在,我更喜歡我自己的術語。 我喜歡說在另一個(遠程)Git 存儲庫中看到的分支名稱,而不是remote branch 而不是遠程跟蹤分支名稱(例如, origin/master ),我稱之為遠程跟蹤名稱; 而不是跟蹤分支,我使用帶有上游集的短語分支名稱 但是准備好 Git 文檔使用他們的術語。

請記住, git pull基本上是git fetch后跟git merge簡寫。 1 pull命令將其大部分參數直接傳遞給fetch步驟。 例如,如果您git fetch origin br ,則fetch步驟獲取遠程名稱( origin )和br作為“refspec”。 在 1.8.4 之前的 Git 版本中,這會阻止git fetch更新您的任何遠程跟蹤分支,但自 1.8.4 以來,顯式獲取分支br也會更新您的origin/ br (假設有問題的遠程名為origin )。

如果您不傳遞額外的參數, git fetch獲取遠程的默認 refspecs 集,通常是2 個“所有分支”。 這意味着,無論是git fetch (假設origin )或git fetch origin將更新所有遠程跟蹤分支origin ,只要你運行的是比較現代的(1.8.4或更高版本)的Git。 (在足夠舊的 Git 版本中,我認為pull命令在 fetch 步驟中變得更加嚴格。)

但是,在潛在地獲取和更新所有origin/*遠程跟蹤分支后, pull代碼繼續執行git merge步驟。 對於這一部分,Git 非常關心您現在在哪個分支上,以及它與哪個“遠程分支” 3合並。 如果像您的示例一樣,您當前在master並且它與originmaster合並,則 Git 將使用它在origin/master下引入的任何新內容運行git merge步驟(注意這里的斜杠)。

技術細節:“refspec”

我在上面多次使用了“refspec”這個詞,但從未定義過它。

“refspec”是第二簡單的,只是一對分支名稱,例如master:masterdevelop:develop等。

這對通常(但不總是)在冒號的兩側具有相同的兩個分支名稱:在它們之間。 其中之一是你的名字,你的分支,在你的倉庫,另一個是他們的名字,也就是說,他們在倉庫使用及其分支機構的名稱。

通常你在推送時會看到這個兩個名字的形式:例如git push origin master:master 這意味着“打包我的master分支,通過互聯網電話調用遠程命名origin ,將包發送給他,並詢問他是否會將其設master分支。” 您還可以在左側使用提交 ID 或單詞HEADgit push origin HEAD:master表示“接受我現在正在進行的任何提交,並要求遠程origin使其成為他的master ”。

執行git fetch ,雙方會顛倒,通常您還會在您想要的名稱前添加origin/ (或遙控器的名稱)。 也就是說,您獲得了他的master ,但在您的存儲庫中將其稱為origin/master 所以你git fetch origin master:origin/master ,等等。 4如果你執行了git fetch origin master:master你會(可能)抹掉你在你自己的 master 上所做的工作。 5

fetchpull還有另外一件奇怪的事情。 我說過這是 refspec 的“第二簡單”形式。 最簡單的就是像master這樣朴實無華的名字。 這的含義取決於您在做什么:對於fetch ,它的意思是“帶上他的master ,但不必在我的本地存儲庫中為其指定任何名稱,只需保存哈希 ID。” 對於push ,它的意思是“把我的master給他,讓他叫它master ”。

同樣,在舊版本的 git 中,如果您要求git fetch帶來他們的 master(可能還有其他人),而不給fetch一個本地名稱來使用它,它只會保存 ID(和他們的分支名稱) Git 的FETCH_HEAD文件。 在較新(1.8.4 及更高版本)的 Git 中,git 使用fetch =配置條目來確定要更新的遠程跟蹤分支。

丑陋的: git pull origin master branch (不要這樣做)

如果你告訴git fetch帶來幾個分支,那工作正常(無論如何使用 Git 1.8.4 或更高版本)。 但是如果你告訴git pull取幾個分支,它的行為就會很糟糕。

fetch步驟工作正常。 merge步驟出現問題。

pull代碼要求git merge將多個分支合並到您當前的分支中。 Git 稱之為“章魚合並”。 除非您進入高級分支,否則您幾乎肯定不想要那樣。 所以不要這樣做。

底線

我建議做一個git fetch ,默認情況下會帶來所有,然后做單獨的git mergegit rebase操作。 你將能夠看到你在做什么。


1git rebase ,如果這樣配置或指導。 變基通常比合並要好,盡管它總是取決於細節。 我的建議是首先使用git fetch ,然后將自己的git rebasegit merge作為單獨的步驟進行,至少在您不熟悉 Git 時是這樣。 我認為這種方式實際上不那么令人困惑,盡管不可否認,您必須輸入兩個命令而不是一個。

2從技術上講,它是該遠程配置中fetch =行中的任何內容。 遠程origin的正常行讀取fetch = +refs/heads/*:refs/remotes/origin/* ,這就是 git 知道將源的分支重命名為您的origin/ whatever分支的方式。

3從技術上講,Git 只使用原始哈希 ID,保存在名為FETCH_HEAD的文件中。 此處引號中的術語遠程分支是標准的 Git 術語:在存儲庫上看到的分支名稱,它通過您的git fetch命令將提交提供給您的 Git。

4我又遺漏了一件事,即前導+符號:在獲取“他們的主人”時,您通常想忘記之前關於“他們的主人”的任何想法,因此fetch =行具有該前導加號. 這會打開“強制”標志,即更新,即使它不是快進操作。 fetch =行還完整地拼寫了所有內容,以避免在您不小心命名本地分支origin/something ,並使用*字符匹配多個分支名稱。

5如果撞你自己的工作,你幾乎總是可以找回來。 Git 確實嘗試將所有內容保留至少 30 天。 不過,我們會將“如何取回”留給其他 SO 條目。

不會。 git-pull只會將更改合並到您的本地分支 如果您想要每個其他分支的更新,您必須檢查它們並單獨pull它們的更新。

您可以使用git pull --all來拉取所有跟蹤的遠程分支,或者使用git fetch --all來獲取它們並稍后決定如何繼續。 請注意, pull通常會自動合並任何更改,而且很少是您想要的。

不,僅將合並更改拉到當前本地分支。

基於這個答案https://stackoverflow.com/a/59793998/14557599我在/etc/bash.bashrc中添加了一個函數來做到這一點:

git_pull() {
    echo - pulling all tracked local branches from "origin" remote
    orig_branch=$(git branch | grep "*" | sed "s/[ *]*//") # getting name of current branch via asterisk
    git fetch | return 1
    for branch in $(git branch | sed "s/[ *]*//") ; do # remove spaces and asterisk
        git checkout $branch && git merge --ff-only FETCH_HEAD
    done
    echo - checking out to branch where function was called from 
    git checkout $orig_branch
}; export -f git_pull

暫無
暫無

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

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