簡體   English   中英

Git 推送功能分支變基后被拒絕

[英]Git push rejected after feature branch rebase

好的,我以為這是一個簡單的 git 場景,我錯過了什么?

我有一個master分支和一個feature分支。 我在master上做了一些工作,在feature上做了一些工作,然后在master上做了更多的工作。 我最終得到了這樣的結果(字典順序意味着提交的順序):

A--B--C------F--G  (master)
       \    
        D--E  (feature)

我對git push origin master以保持遠程master更新沒有問題,也沒有使用git push origin feature (在feature上時)為我的feature工作維護遠程備份。 直到現在,我們都很好。

但是現在我想在 master 上的F--G提交之上重新設置feature ,所以我git checkout featuregit rebase master 還好。 現在我們有:

A--B--C------F--G  (master)
                 \
                  D'--E'  (feature)

問題:當我想備份與git push origin feature feature分支的新的 rebase 功能時,推送被拒絕,因為樹由於 rebase 而發生了變化。 這只能通過git push --force origin feature來解決。

我討厭在不確定自己是否需要的情況下使用--force 那么,我需要它嗎? 變基是否一定意味着下一次push應該是--force ful?

此功能分支不與任何其他開發人員共享,因此我對強制推送實際上沒有問題,我不會丟失任何數據,這個問題更具概念性。

問題是git push假設遠程分支可以快速轉發到您的本地分支,也就是說,本地分支和遠程分支之間的所有區別都在本地,最后有一些新的提交,如下所示:

Z--X--R         <- origin/some-branch (can be fast-forwarded to Y commit)
       \        
        T--Y    <- some-branch

當您執行git rebase提交時,D 和 E 將應用於新的基礎並創建新的提交。 這意味着在 rebase 之后你有類似的東西:

A--B--C------F--G--D'--E'   <- feature-branch
       \  
        D--E                <- origin/feature-branch

在這種情況下,遠程分支無法快速轉發到本地。 雖然理論上本地分支可以合並到遠程(顯然在這種情況下你不需要它),但是由於git push只執行快進合並,它會拋出錯誤。

--force選項所做的只是忽略遠程分支的狀態並將其設置為您正在推送的提交。 所以git push --force origin feature-branch只是用本地feature-branch覆蓋origin/feature-branch -branch 。

在我看來,只要您是唯一一個在該分支上工作的人,就可以在master上重新設置功能分支並將它們強制推送回遠程存儲庫。

而不是使用-f--force開發人員應該使用

--force-with-lease

為什么? 因為它檢查遠程分支是否有更改,這絕對是個好主意。 讓我們假設 James 和 Lisa 正在開發同一個功能分支,並且 Lisa 已經推送了一個提交。 James 現在重新設置了他的本地分支並在嘗試推送時被拒絕。 當然,James 認為這是由於 rebase 和使用--force並且會重寫 Lisa 的所有更改。 如果 James 使用了--force-with-lease ,他會收到警告說有其他人完成了提交。 我不明白為什么有人會在 rebase 后推送時使用--force而不是--force-with-lease

我會改用“checkout -b”,這樣更容易理解。

git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature

當您刪除時,您會阻止推送包含不同 SHA ID 的現有分支。 在這種情況下,我只刪除遠程分支。

一種解決方案是執行 msysGit 的 rebase 合並腳本所做的事情 - 在 rebase 之后,將舊feature頭與-s ours合並。 你最終得到了提交圖:

A--B--C------F--G (master)
       \         \
        \         D'--E' (feature)
         \           /
          \       --
           \    /
            D--E (old-feature)

...您對feature的推動將是一個快進。

換句話說,你可以這樣做:

git checkout feature
git branch old-feature
git rebase master
git merge -s ours old-feature
git push origin feature

(未經測試,但我認為這是正確的......)

其他人已經回答了你的問題。 如果你重新設置一個分支,你將需要強制推送該分支。

Rebase 和共享存儲庫通常無法相處。 這是改寫歷史。 如果其他人正在使用該分支或已從該分支分支,那么 rebase 將非常令人不快。

一般來說,rebase 非常適合本地分支管理。 遠程分支管理最適合顯式合並 (--no-ff)。

我們還避免將 master 合並到功能分支中。 相反,我們變基為 master 但使用新的分支名稱(例如添加版本后綴)。 這避免了在共享存儲庫中變基的問題。

這個分支上只有一個開發人員可能會也可能不會,即現在(在 rebase 之后)不與源/功能內聯。

因此,我建議使用以下順序:

git rebase master
git checkout -b feature_branch_2
git push origin feature_branch_2

是的,新分支,這應該在沒有 --force 的情況下解決這個問題,我認為這通常是 git 的主要缺點。

我避免強制推送的方法是創建一個新分支並繼續在該新分支上工作,並在穩定后刪除重新定位的舊分支:

  • 在本地重新設置簽出的分支
  • 從重新定位的分支分支到新分支
  • 將該分支作為新分支推送到遠程。 並刪除遠程上的舊分支

feature分支上的git merge master有什么問題? 這將保留您的工作,同時將其與主線分支分開。

A--B--C------F--G
       \         \
        D--E------H

編輯:啊抱歉沒有閱讀您的問題陳述。 執行rebase時需要強制。 所有修改歷史的命令都需要--force參數。 這是防止您丟失工作的故障保險(舊的DE將丟失)。

所以你執行了一個git rebase ,它使樹看起來像(雖然部分隱藏,因為DE不再在命名分支中):

A--B--C------F--G
       \         \
        D--E      D'--E'

因此,當嘗試推送您的新feature分支(其中包含D'E' )時,您將丟失DE

對我來說,以下簡單的步驟有效:

1. git checkout myFeature
2. git rebase master
3. git push --force-with-lease
4. git branch -f master HEAD
5. git checkout master
6. git pull

完成上述所有操作后,我們也可以通過以下命令刪除 myFeature 分支:

git push origin --delete myFeature

以下對我有用:

git push -f origin branch_name

它不會刪除我的任何代碼。

但是,如果您想避免這種情況,則可以執行以下操作:

git checkout master
git pull --rebase
git checkout -b new_branch_name

然后你可以挑選你所有的提交到新的分支。 git cherry-pick COMMIT ID然后推送你的新分支。

由於 OP 確實理解了這個問題,所以只是尋找一個更好的解決方案......

這作為一種練習怎么樣?

  • 擁有實際的特性開發分支(你永遠不會變基和強制推送,所以你的特性開發人員不會討厭你)。 在這里,通過合並定期從 main 中獲取這些更改。 梅西耶的歷史,是的,但生活很輕松,沒有人會打擾他的工作。

  • 有第二個特性開發分支,一個特性團隊成員定期推送所有特性提交,實際上是重新設置,實際上是強制的。 所以幾乎完全基於最近的一次主提交。 功能完成后,將該分支推送到 master 之上。

此方法可能已經有一個模式名稱。

在最新的 master 之上獲取 master 和 rebase 特性分支的新變化

git checkout master
git pull
git checkout feature
git pull --rebase origin master
git push origin feature

我會做如下

rebase feature
git checkout -b feature2 origin/feature
git push -u origin feature2:feature2
Delete the old remote branch feature
git push -u origin feature:feature

現在遙控器將具有功能(基於最新主控)和功能2(具有舊主控頭)。 如果您在解決沖突時犯了錯誤,這將允許您稍后進行比較。

要在變基后將更改推送到分支,您需要在 Git 上的 git 推送命令中使用 -f 或 --force 標志強制推送您的提交。

可以這樣做,

在 git rebase 之后將提交推送到分支

git push origin -f FEATURE_BRANCH_NAME

這是因為遠程分支中發生了一些變化,並且遠程分支和本地分支的提交歷史記錄不同。

如果您嘗試推送本地更改,則 git 將拒絕它,並顯示一條消息,例如您當前分支的尖端位於其遠程分支的后面。 對本地分支進行強制推動可以解決問題。

不要害怕它。 如果您是唯一一個在同一分支上工作的人,這是一個很好的方法。

暫無
暫無

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

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