簡體   English   中英

git push --force-with-lease 與 --force

[英]git push --force-with-lease vs. --force

我試圖理解兩者之間的區別

git push --force

git push --force-with-lease

我的猜測是,如果遠程沒有本地分支沒有的提交,后者只會推送到遠程?

force用您的本地分支覆蓋遠程分支。

--force-with-lease是一個更安全的選項,如果更多的提交被添加到遠程分支(由另一個團隊成員或同事或你擁有的東西),它不會覆蓋遠程分支上的任何工作。 它確保您不會通過強制推送覆蓋其他人的工作。

我認為您對命令的總體看法是正確的。 如果遠程分支與本地機器上的遠程分支具有相同的值 - 您將覆蓋 remote。 如果它沒有相同的值 - 它表示在您處理代碼時其他人對遠程分支所做的更改,因此不會覆蓋任何代碼。 顯然,如果遠程中有其他提交,則值將不相同。

我只是認為--force-with-lease作為我想確保不覆蓋任何隊友代碼時使用的選項。 我公司的很多團隊都使用--force-with-lease作為故障安全的默認選項。 在大多數情況下它是不必要的,但是如果您碰巧覆蓋了另一個人為遠程貢獻的內容,則會為您省去很多麻煩。

我確定您查看了文檔,但此處可能包含一些更冗長的解釋:

https://git-scm.com/docs/git-push

尋找來自可靠和/或官方來源的答案。

torek評論他的其他答案中提到的“比較和交換”由Git 本身來源進一步說明。

如果遠程沒有本地分支沒有的提交,后者只會推送到遠程?

該功能在此提交中引入(2013 年 12 月,Git v1.8.5-rc0)

--force-with-lease將通過要求它們的當前值與某些合理的默認值相同來保護所有將要更新的遠程引用,除非另有說明;

目前,“一些合理的默認值”被暫時定義為“我們擁有的遠程跟蹤分支的值,用於更新遠程的引用”,如果我們沒有這樣的遠程跟蹤分支,這是一個錯誤。

所以“租賃”的意思是:

force-with-lease ”:您假設您在獲取時對 ref 進行了租約,以決定重新定位的歷史記錄應該是什么,並且只有在租約沒有被破壞的情況下才能推遲。

消息來源仍然提到“cas”:

  • 這個選項最初被稱為“ cas ”(代表“比較和交換”),這個名字沒有人喜歡,因為它太技術化了。
  • 第二次嘗試將其稱為“lockref”(因為它在概念上類似於在獲取鎖后推送)但是“鎖”這個詞被討厭,因為它暗示它可能會拒絕其他人的推送,這不是此選項的工作方式。
  • 這一輪稱之為“強制租賃”。
    您假設您在獲取時租用了 ref 以決定重新定位的歷史記錄應該是什么,並且只有在租用未被破壞的情況下才能推遲。

所以:“ git push --force-with-lease vs. --force

正如我在“默認push --force-with-lease ”中提到的,正如 Git 2.13(2017 年第二季度)所提到的,選項--force-with-lease可以是忽略如果后台進程(例如您在帶有 Git 插件的 IDE 中找到的那些)運行git fetch origin
在這種情況下, --force占上風。

正如Pavlus 在評論中補充的那樣

它本身並沒有被忽略,只是現在您對本地遠程頭和遠程頭具有相同的參考,因此--force-with-lease將正確運行 -- 比較這兩者,如果在 fetch 和推,有人更新遠程,它不會表現為--force ,它仍然會失敗。


另一個區別:在 Git 2.29(2020 年第四季度)之前,使用“ --force-with-lease ”選項推送名稱包含非 ASCII 字符的引用在智能 HTTP 協議上不起作用。
它可以與git push --force

請參閱brian m 的commit cd85b44 (2020 年 7 月 21 日) 卡爾森 ( bk2204 )
(由Junio C gitster合並-- gitster -- in commit c2796ac ,2020 年 7 月 30 日)

remote-curl : 使--force-with-lease使用非 ASCII 引用名稱

報道者:Frej Bjon
簽字人:brian m. 卡爾森

當我們調用遠程傳輸助手並傳遞帶有參數的選項時,如有必要,我們將參數引用為 C 樣式字符串。
當我們傳遞非 ASCII 引用名稱時,cas 選項就是這種情況,它實現了--force-with-lease命令行標志。

然而,遠程curl助手並不是為了解析這樣的參數而設計的,這意味着如果我們嘗試將--force-with-lease與 HTTP 推送和非 ASCII 引用名稱一起使用,我們會收到如下錯誤:

 error: cannot parse expected object name '0000000000000000000000000000000000000000"'

請注意雙引號, get_oid提醒我們在十六進制對象 ID 中無效。

即使我們能夠解析它,我們也會將錯誤的數據發送到服務器:我們會發送一個轉義的引用,它不會像用戶想要的那樣運行,並且可能會意外地導致更新或刪除我們沒有的引用故意的。

由於我們需要在這里期待一個帶引號的 C 樣式字符串,只需檢查第一個參數是否是雙引號,如果是,則取消引用它。
請注意,如果 refname 包含雙引號,那么我們已經將其雙引號,因此沒有歧義。

我們僅在智能協議中測試這種情況,因為基於 DAV 的協議無法處理此功能。
我們使用 UTF-8 是因為這在我們的測試中更好,對 Windows 更友好,但代碼應該適用於所有非 ASCII 引用。

雖然我們在這里,因為選項的名稱現在已經很好地建立並且不會改變,讓我們內聯它而不是使用 #define 常量。

git push --force是破壞性的,因為它無條件地用本地的任何內容覆蓋遠程存儲庫。 強烈建議不要使用 git 的push --force因為它會破壞已經推送到共享存儲庫的其他提交。 強制推送的最常見原因之一是當我們被迫重新設置分支時。

例如。 我們有一個帶有功能分支的項目,Alice 和 Bob 都將在該項目上工作。 他們都克隆了這個存儲庫並開始工作。 Alice 最初完成了她的部分功能,並將其推送到主存儲庫。 這一切都很好。 Bob 也完成了他的工作,但在推動它之前,他注意到一些更改已合並到 master 中。 為了保持一棵干凈的樹,他對主分支執行了變基。 當然,當他去推送這個 rebase 的分支時,它會被拒絕。 然而沒有意識到 Alice 已經推動了她的工作,他執行了 push --force。 不幸的是,這將刪除 Alice 在中央存儲庫中的所有更改記錄。

--force-with-lease所做的是拒絕更新分支,除非它是我們期望的狀態; 即沒有人更新上游分支。 在實踐中,這是通過檢查上游 ref 是否符合我們的預期來實現的,因為 ref 是散列,並將父鏈隱式編碼為它們的值。

這是一篇關於git push --forcegit push --force-with-lease的好帖子: –force 被認為是有害的; 理解 git 的 –force-with-lease

假設服務器上的任何 pre-receive 鈎子接受推送,這將始終成功:

git push --force

而這會在繼續之前運行特定的客戶端檢查:

git push --force-with-lease

您可以自己手動運行特定檢查。 這是“租約檢查”算法:

  1. 找出你當前的分支。

  2. 運行git for-each-ref refs/remotes 記下您的 git 客戶端認為對應於您當前分支的上游狀態的 commit-id。

例如,如果您在分支“foo”上,請注意與“refs/remotes/origin/foo”相關聯的提交 ID。

  1. 立即確定上游 git 服務器上遠程分支的實際提交 ID。

  2. 如果您從第 2 步和第 3 步中提取的提交 ID 一致,則僅讓“git push”繼續。 換句話說,只有當您本地 git clone 的上游概念與實際上游一致時才繼續。

這里有一個可悲的含義:由於git fetch “refs/remotes/origin/*”下的所有 refs 更新為最新版本,因此這種命令組合與git push --force基本相同:

git fetch

# The command below behaves identically to "git push --force"
# if a "git fetch" just happened!

git push --force-with-lease

為了解決git push --force-with-lease這個固有弱點,我嘗試從不運行git fetch 相反,每當我需要與上游同步時,我總是運行git pull --rebase ,因為git pull只更新 refs/remotes 下的單個 ref,保持--force-with-lease的“租約”有用。

強制租賃不一定安全。 它就像 Sylvie 所說的那樣工作。 一個注意事項:在 git 中,分支只是提交上的一個指針。 並且提交指向零個或多個父提交。 即使您完全使用硬 git reset 和強制推送或使用 --force-with-lease 推送而完全更改了分支,這也不一定是大問題。 您可以使用本地 git reflog 來查看分支上的本地提示(當時 HEAD 在哪里?)已更改並重置並再次推送分支。 然后你只會丟失遠程分支上的新提交,但即使它們也可能被團隊成員恢復。

暫無
暫無

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

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