簡體   English   中英

Git:如何更新master分支,一步切換到master分支?

[英]Git: How to update the master branch and switch to it in one step?

我正在處理一個托管在 GitLab 上的項目,並使用問題/工作分支和合並請求在完成后將該工作帶入主分支。 通常我在問題分支上工作。 當它被 GitLab 合並后,我需要切換到當前 master 在本地進行構建。

我的工作流程是這樣的:

  • 轉主
  • 從遠程拉取(--ff-only)
  • 刪除陳舊的遠程跟蹤分支
  • 同時刪除他們的本地跟蹤分支

還有一個客戶端工具可以監視代碼目錄並更新一些文件(CSS、JavaScript)。 當它看到第一步發生變化(切換到master)時,我首先需要等待它完成再繼續(避免混淆)。 如果 issue 分支和舊 master 之間存在差異,那么在更新 master 時差異很可能會消失(因為該 issue 分支現在已合並)。

我正在尋找一種方法來一步切換到已經更新的 master 分支。 我如何使用git命令執行此操作? 我想將所有這些操作捆綁在一個批處理文件中,以避免每次都在 TortoiseGit 中重復所有這些手動步驟。

這個問題和建議的不同,本地master分支已經存在了。 我不是從遠程切換到一個新分支,而是切換到一個已經存在的分支,它就在遠程后面

長話短說

除非您編寫自己的腳本(或使用 Git 別名來運行多個命令和/或腳本),否則您無法將其簡化為單個命令,但可以更接近。 請參閱許多警告的長部分:最大的一個是它假設您在執行此操作時還沒有master 如果是,則第二步將不起作用(請參閱詳細部分了解會發生什么)。

git fetch -p &&
    git fetch . refs/remotes/origin/master:refs/heads/master &&
    git checkout master

將通過單個工作樹更新git checkout step處理前三個要點(順序不同)。

(請注意,出於發布目的,我將其分成三行,但作為使用!的 Git 別名,它實際上是一大行。)

有幾種方法,包括實際的文字批處理文件(類 Unix 系統上的 shell 腳本,或 .BAT 文件,或其他)和別名(如Joe 在評論中所建議的那樣)。

還有一個客戶端工具可以監視代碼目錄並更新一些文件......

這……不一定是個好主意,比方說。 :-)

git checkout master運行時,它正在更改各種文件。 假設由於某種原因,它更改了觀察者觀看的幾個文件之一,但隨后它暫停了幾分鍾(或幾秒、幾微秒,或無論如何是某個時間單位)。 暫停時,觀察者會嘗試合並現在不同步的多個文件。

當 Git 取消暫停並完成結帳時,這可能是 OK 和自我更正 - 但如果您可以確保更新僅在結帳完成時發生,則可能會更好。

除此之外,讓我們看一下這個特定的命令系列,並非常具體地說明您正在使用哪個 Git 命令:

  • 轉主

我假設這是git checkout master

從遠程拉取(--ff-only)

我假設這是git pull origin master --ff-only或者可能只是git pull --ff-only

  • 刪除陳舊的遠程跟蹤分支

我現在假設這是git fetch --prune 如果您正在做不同的事情,則應將其包含在您的問題中。

  • 同時刪除他們的本地跟蹤分支

如果我明白你的意思,這需要一個腳本。 請注意,這有點危險:假設您有自己的分支X ,您正在其上進行開發。 這個X與其他任何人的X無關。 然后有人創建了他們自己的X使用相同的名稱——並將其發送到你git fetch的機器。 你現在有了origin/X 然后他們刪除他們的X (因為他們已經完成了)並刪除origin/X 如果你現在讓你的腳本刪除你的X ,因為origin/X消失了,那可能很糟糕。

如果您僅在X明確將origin/X設置為其上游時才將其刪除,則不會發生這種特殊情況——但如果有人不小心刪除了您的origin/X並認為這是他們的origin/X ,同樣的問題會再次出現,而這次特定的保護不起作用。

無論如何,撇開所有這些不談,讓我們看看我上面建議的變體。

git fetch -p

這會更新您所有的origin/*名稱, 1包括origin/master ,而不會影響工作樹中的任何文件 -p--prune的縮寫,因此它會刪除在 Git 中不再具有相應分支的所有origin/*名稱,這些名稱存儲在名稱origin下的 URL 中。


1我在這里假設您只有一個遙控器,名為origin 如果您有多個遙控器,請使用git fetch origin -p確保您專門從名為origin的遙控器中獲取。 我還假設您沒有將 Git 配置為單分支克隆。


git fetch. refs/remotes/origin/master:refs/heads/master

這個看起來很神奇的命令告訴你的 Git 調用它自己 也就是特殊的名字. 指的是你自己的 Git 倉庫 我們正在使用它來欺騙您的 Git 根據您更新的origin/master快進您的master分支。 最后一個論點是這樣做的:我們對你的 Git 說:好的,我的 Git,當你與另一個 Git 交談時,找出它的refs/remotes/origin/master標識的提交。 然后,如果這是一個快進操作,請更新我的refs/heads/master以匹配。

當然,你的 Git 正在與之交談的“其他 Git”就是它本身——所以這意味着快進 my master從 my origin/master 2大致相當於:

git checkout master && git merge --ff-only origin/master && git checkout -

除了沒有實際簽出發生:工作樹中的文件沒有更改。


2您可能想知道為什么其中一些使用origin/master而另一些使用refs/remotes/origin/master 較長的只是名稱的完整拼寫 使用git fetch時,最好使用完整拼寫。 事實上,一般來說,在腳本中,您可能希望更頻繁地使用完整拼寫,但特別是git fetch可能會變得混亂,例如,如果您與之交談的另一個Git 不小心同時具有同名的分支和標簽。 所以我用git fetch來說明全名。 您將使用它與您自己的 Git 通話,因此如果您不混淆標簽和分支名稱或以其他方式造成歧義,您實際上不需要全名。 但這是git fetch的好習慣。


如果你在你的master身上,上面的失敗

git fetch命令將拒絕提取到您簽出的任何分支名稱。 所以如果你master上,這個git fetch. 技巧會失敗。

在某種程度上,這沒問題! 如果你你的master上,你應該做的是運行:

git merge --ff-only origin/master

或任何等效的東西。 這就是你的git pull --ff-only所做的:首先它運行git fetch (沒有-p並且僅限於僅獲取其他 Git 的master ); 然后它運行git merge --ff-only

更完整的版本

那么,這個序列的一個更完整的版本是首先檢查:我在哪個分支? 為此,您可以使用兩個 Git 命令之一:

git rev-parse --abbrev-ref HEAD

要么:

git symbolic-ref --short HEAD

如果您當前在自己的master分支上,這兩個都會打印master 它們之間的區別在於它們在完全沒有分支的情況下會做什么:例如,在 rebase 的中間,當您處於“分離的 HEAD”state 時。在這種情況下,第二個命令 - git symbolic-ref出錯了,而第一個只是打印HEAD

如果您想避免在這樣的 state 中執行任何這些操作,請使用第二個命令並檢查是否失敗。 否則,使用第一個。 我將在這里僅說明第一個:

if test $(git rev-parse --abbrev-rev HEAD) = master; then
    # already on master - use alternative strategy
    git fetch -p && git merge --ff-only refs/remotes/origin/master
else
    # not currently on master: use fancy tricks to update
    git fetch -p &&
        git fetch . refs/remotes/origin/master:refs/heads/master &&
        git checkout master
fi

以上雖然未經測試,但應該適合作為 shell 腳本。 如果你安裝了 Git,你就可以運行 shell 腳本——或者你可以把上面的變成一個很長的 Git 別名,使用! 和適當的分號集。

暫無
暫無

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

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