是 Ray 不是 Array

整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ

Advertisement
2026-02-26 Git

取代 git push --force 更好的方式,git push --force-with-lease

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

前言

我們在開發上,經常會使用 git rebasegit commit --amend 來整理 commit 歷史,但這些操作會重寫已經推送過的 commit,導致本地的歷史與遠端不同,這時候普通的 git push 會被拒絕,必須使用強制推送。

所以這一篇來聊一下 git push --force-with-lease,這是一個更安全的強制推送方式,它會在推送前先確認遠端沒有新的變更,才允許你強制推送。

git push

我相信大家應該非常熟悉 git push 這個指令了,基本上就是把你當前的修改進度推到遠端的 Git 儲存庫上(GitHub、GitLab、Bitbucket 等等),這樣其他同事就可以看到你的修改了。

所以大多人對於這指令只認識這幾個用法:

  • git push:把當前分支的修改推到遠端。
  • git push origin <branch>:把指定分支的修改推到遠端。
  • git push -u origin <branch>:把指定分支的修改推到遠端,並且設定上游分支,以便於以後可以直接使用 git push 而不需要指定分支。
  • git push --force:強制推送修改到遠端,會覆蓋掉遠端的修改(今天介紹的主角)。

但其實它有非常多的進階用法,例如:

  • git push --all or git push --branches:把所有分支的修改推到遠端。
  • git push --tags:把所有標籤推到遠端。

因此你可以這樣做:

1
2
# 刪除遠端分支
git push origin :<branch>

等等,這些都是一些比較進階的用法,但今天我們要聊的重點是 git push --forcegit push --force-with-lease,對於其他有興趣可以直接觀看 Git 官方文件

git push –force & git push –force-with-lease

這個大概是萬惡的用法,你可以輸入 git push -fgit push --forcegit push origin +<branch> 等等這些指令來 強制 把你的當前修改進度推到遠端上,這樣就算遠端上有其他同事的修改了,你也會直接覆蓋掉他們的修改(簡單來講,就是讓你同事今天做白工)。

所以許多公司跟單位是直接禁止使用 git push --force 的。

但我們實際開發上不可能完全不使用 git push --force,因為有時候我們可能會需要重寫 commit 歷史(例如使用 git rebase),這時候就會需要使用 git push --force 來把修改推到遠端上。

所以 Git 官方就提供了一個更安全的方式,也就是 git push --force-with-lease

它的運作機制是:在你強制推送之前,Git 會比對遠端分支目前指向的 commit 是否與你本地記錄的遠端追蹤分支(例如 origin/main)一致。如果一致,代表在你上次 git fetch 之後沒有其他人推過新的 commit,就允許強制推送;如果不一致,就代表有人在這段期間推了新的東西,Git 會拒絕你的推送,避免你覆蓋掉別人的工作。

因此當你使用 git push --force-with-lease 的時候,如果遠端上有其他同事在你之後推了新的 commit,你就會看到類似下面的錯誤訊息:

1
2
3
To <remote>
! [rejected] <branch> -> <branch> (stale info)
error: failed to push some refs to '<remote>'

這裡的 (stale info) 代表你本地記錄的遠端狀態已經過時了,這時候你就需要先 git fetch 拉取遠端的最新狀態,重新整理你的修改(例如重新 git rebase),最後再使用 git push --force-with-lease 來推送。

什麼時候需要強制推送?

你可能會想:「我只要 git push 被拒絕的時候,先 git pull 然後再 git push 就好了啊?那幹嘛用 --force?」

沒錯,如果你的 commit 歷史跟遠端只是單純的分叉(例如你跟同事同時在同一個分支上各自 commit),確實用 git pull + git push 就可以解決。

但當你使用了以下這些會改寫 commit 歷史的操作時,情況就不同了:

  • git rebase:變基,重新排列 commit
  • git commit --amend:修改最後一個 commit
  • git reset 後重新 commit:重置後重寫歷史

這些操作會產生全新的 commit SHA,導致你本地的歷史跟遠端的歷史完全不同,不是單純的「落後」而是「分叉且無法合併」,所以必須強制推送。而這時候用 --force-with-lease 就比 --force 安全得多。

–force-with-lease 的已知陷阱

--force-with-lease 雖然比 --force 安全,但它並不是萬無一失的。

它的保護機制是比對你本地記錄的遠端追蹤分支(例如 origin/main),而不是即時去查詢遠端。所以如果你在強制推送之前做了 git fetch(或 git pull),你本地的遠端追蹤分支就會被更新到最新狀態,這時候 --force-with-lease 會認為「你已經知道遠端的最新狀態了」,就會允許強制推送——保護就失效了

舉個例子:

1
2
3
4
5
6
7
8
# 你做了 rebase,準備強制推送
git rebase -i HEAD~3

# 習慣性先 fetch 一下(這一步讓保護失效!)
git fetch origin

# 這時候 --force-with-lease 不會阻止你,即使遠端有新的 commit
git push --force-with-lease origin main

–force-if-includes

為了解決這個陷阱,Git 2.30 之後提供了 --force-if-includes,它會額外檢查:遠端追蹤分支的最新 commit 是否已經被整合到你的本地分支中。如果你只是 git fetch 但沒有實際把遠端的變更整合進來,推送就會被拒絕。

建議搭配使用:

1
git push --force-with-lease --force-if-includes origin main

如果你覺得每次都要打這麼長太麻煩,可以設定 Git alias:

1
git config --global alias.pushfl "push --force-with-lease --force-if-includes"

之後就可以直接使用:

1
git pushfl origin main

總結

指令 行為 安全性
git push 只允許快轉(fast-forward)更新 最安全
git push --force-with-lease 比對本地遠端追蹤分支,一致才允許強制推送 安全
git push --force-with-lease --force-if-includes 額外確認遠端變更已被整合到本地 更安全
git push --force 無條件覆蓋遠端 危險

簡單來說:

  • 永遠不要用 git push --force,除非你非常確定你在做什麼。
  • git push --force-with-lease 取代 --force,這是最基本的安全措施。
  • 搭配 --force-if-includes 可以獲得更完整的保護。

養成好習慣,保護自己也保護同事的心血。

整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ

Advertisement

你的支持會直接轉換成更多技術筆記

如果我的筆記讓你少踩一個坑、節省 Debug 的時間,
也許你可以請我喝杯咖啡,讓我繼續當個不是 Array 的 Ray ☕

buymeacoffee | line | portaly

Terminal

分享這篇文章

留言

© 2026 Ray. All rights reserved.

Powered by Ray Theme