我開始學習/使用rebase并有疑問:
master創建feature-1分支push放到feature-1。
master推送了一些修改,在每天的開始,我進行rebase(進入feature-1)feature-1創建拉動請求到master一段時間后,我讀到,如果我把修改推送到我的分支(我每天結束后都會這樣做),就不應該使用rebase - 所以我想知道我是否以正確的方式使用rebase,或者我應該改變我的方法?
uj5u.com熱心網友回復:
Rebase是一個破壞歷史的命令,因此[作為經驗法則]它不應該被用在其他人檢查出來的分支中,因為強制推送可以并且會破壞作業流程。
盡管如此,如果feature-1只被你簽出,你所描述的作業流程在我看來完全沒有問題。這將使合并和更新變得更加干凈。
uj5u.com熱心網友回復:
"不要強制推送公共分支"的經驗法則是一種概括,以防止普通用戶的混亂。
在你描述的作業流程中,在第2步的一天結束時,顯然你第一次推送的分支將是干凈的,但隨后幾天的推送將需要強制推送(除非master沒有改變,并且當天的重定位沒有影響)。
你的用例是完全正確的,我在我的個人分支上也會(并且正在做)同樣的事情。經驗法則應該是 "不要強制推送共享分支",特別是分支策略中的長期分支(例如,main、master、develop,等等),但即使如此,我還是建議將這些特殊分支保護起來,這樣即使你嘗試也無法強制推送,除非是那些知道自己在做什么的 repo 管理員。如果你適當地保護了某些共享分支,那么讓每個人都能隨時強制推送(自己的)分支就很好了。如果開發人員在一個分支上合作,那么他們只需讓對方知道他們是否強制推送該分支。(在作業環境中,如果開發人員開始未經允許就強行推送其他人的分支,那么也許他們需要更多的培訓,或者取消他們的權限。)
重要的是,要讓每個人都能在自己的分支上強行推送。
需要注意的是,即使你在第2步結束時從未推送過,一旦你將你的PR創建到master,你可能仍然希望重新定位,并因此在之后強制推送。例如,在代碼審查期間,有人可能會發現一個你需要修復的一個字符的錯誤。當然,你可以在新的提交中修正這個錯別字,但如果你能修正現有的提交,又何必再為這個錯別字弄亂歷史?無論你是在分支上修改提示提交還是修復先前的提交(用rebase -i),你都需要在事后強制推送,而且我認為重寫該提交應該是默認的,而不是例外。如果錯別字是在PR完成到master之后才發現的,那就是完全不同的情況了,通常需要重新提交和額外的PR。我想說的是,如果你的作業流程是用PR將修改帶入共享分支,那么強制推送應該是作業流程的一個常規部分。相反,在基于主干的開發(TBD)中,你永遠不會想要強制推送,例如每個人都在master上作業,一旦你推送,你就不會重寫任何這些提交。
什么時候真正需要強制推送?
當你想從已經推送的分支中移除提交時,你需要強制推送。
你可能會覺得你沒有洗掉提交,因為從概念上講你是在改變它們。然而,當你重寫時,你實際上是在重寫提交,但這樣做也是在洗掉分支中的前一版本的提交。任何時候你重寫一個提交,你都在改變該提交的某些內容。在重寫的情況下,你通常至少會改變父提交和提交者的日期(現在)。當一個提交的內容發生變化時,提交ID(哈希值)也會發生變化,因為沒有兩個不同的輸入能夠產生相同的哈希值*。這相當于你在遠程分支上 "洗掉 "了至少一個提交ID,并添加了一個新的ID。因此,如果你在一個已經被推送的分支上使用rebase、commit --amend或reset這樣的命令來處理先前的提交,你就需要再次強制推送。
額外的想法和提示:
- 除非有理由不推送,否則,你需要再次強制推送。
- 除非有不推送的理由,否則當你停止作業時,就推送你的分支(就像你正在做的)。在你的本地機器萬一丟失或損壞的情況下,這可以作為一個偉大的備份。如果你在多臺機器上作業,它還可以確保你不會踩到自己的腳趾。
- 定期獲取并重新建立目標,例如
origin/master,以便及時了解可能導致與你的分支沖突的變化。當沖突出現時,立即處理它們通常會更容易。我通常每天會在origin/master上重設分支,大約1-5次,并在創建PR前再重設一次。 - 當強制推送時,默認使用
git push --force-with-lease(甚至可能使用較新的--force-if-includes)而不是眾所周知的--force。這將防止你意外地吹走遠程分支上你還沒有看到的新提交(要么是你從另一臺機器上添加的,要么是你的分支上的合作者)。 - 有些 Git SCM 工具可以讓你在更新分支時跟蹤 PR 的歷史。這有很多原因,其中之一是為了隔離由重設或合并帶來的變化,否則你可能不會注意到。每當你重新建立和強制推送你的分支時,PR 可以檢測到自該分支上一版本以來的變化,它將突出顯示差異(這些差異可能是默默地合并進來的,沒有沖突),這樣你就可以很容易地看到它們是否與你的變化兼容。
反駁意見:
有些人可能會說,即使是你自己的個人分支,你也不應該強制推送,以防其他人可能使用你所替換的先前的提交ID。也許這在有許多合作者的公共 repo 中是真的,然而,我認為這只需要由組織或 repo 的所有者來定義。一種方法是用你的名字來命名分支(例如:user/first.last/description-the-change)。這樣一來,誰是它的 "主人 "就一目了然了。如果有人想使用我的分支,他們可以,但在合并到main之前,它很可能會被重寫多次,如果他們對此有意見,可以要求我幫助做一個花哨的rebase --onto。我個人認為沒有任何理由禁止在私有 repo 中強制推送,事實上我更喜歡 BitBucket 的 "rebase, merge "或 Azure DevOps 的 semi-linear merge 策略,它們都有目的地在 PR 完成時進行另一次 rebase。(同樣,我可以想到的唯一例外是,強制推送應該很少,如果有的話,就是TBD。
*理論上有可能出現哈希碰撞,即兩個不同的輸入可以產生相同的哈希值。Git 默認使用 SHA-1 哈希演算法,該演算法確實存在已知的碰撞,但是 AFAIK 它們足夠罕見,從未在 Git 版本庫中造成過問題,而且可能永遠不會。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/325286.html
標籤:
