news 2026/8/14 13:56:05

20 — 远程进阶:强制推送的保险绳——force-with-lease

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
20 — 远程进阶:强制推送的保险绳——force-with-lease

写在前面:这一章要解决什么

你写完代码git push却被拒:! [rejected] main -> main (non-fast-forward)。本章帮你理解推送被拒的原因,学会安全处理,避免覆盖他人代码。

学完后,你应能:

  1. 解释「非快进」
  2. 区分fetchpull
  3. 知道何时用git pull --rebase
  4. 理解--force的危险,以及--force-with-lease的安全
  5. 理解远程跟踪分支
  6. 配置多远程,走通三角工作流

读者设定:大一同学,已学过基本远程协作,想搞懂推送被拒与强制推送。


1. 定位:为什么要单开一章讲远程进阶

1.1 一句话先记住

推送被拒 = 你想往信箱塞信,但信箱里已经有别人的信了。你的提交的前驱是 A,但远程 A 后面已有 B,Git 拒绝覆盖。

1.2 没有这些知识会怎样

场景不知道怎么办知道以后
push 被拒慌乱,乱敲命令先拉再推
想强推覆盖--force会丢失同事代码--force-with-lease安全兜底
fetch 和 pull 分不清每次 pull 产生合并提交按需选择,历史更干净
多人改同一分支互相覆盖,越推越乱理解远程跟踪分支,有条有理

1.3 生活里的类比

你已经会的远程进阶对应
往信箱塞信push
信箱里已有别人的信,塞不进去非快进
先取出信箱里的信,再塞自己的fetch + merge / pull
强行把别人的信换成自己的force push(危险!)
换之前先确认信箱里还是你上次看到的那几封force-with-lease

1.4 本章内容目标

目标你能做到
理解非快进说清「远程有新提交,你本地没有」
区分命令fetch 只下载,pull = fetch + 整合
安全强推--force-with-lease代替--force
看懂跟踪分支解释origin/main是什么
多远程协作配置 upstream,走通三角工作流

2. 本质:推送被拒到底发生了什么

2.1 一张图先建立感觉


图:本地与远程之间的同步——fetch 拉取,push 推送。


图:分布式版本控制——每个人都有完整副本。

2.2 用白话拆开

  1. 远程仓库是共享的「中心信箱」。
  2. 远程跟踪分支(如origin/main)是你本地对远程分支的缓存快照,由fetch更新。
  3. 推送是把本地提交上传到远程。
  4. 非快进是远程有你不包含的新提交,Git 拒绝推送。

2.3 非快进到底是什么

你上次看信箱:信 A(origin/main指向 A)。现在信箱:A → B(别人推了 B)。你要塞:A → C(你的本地提交 C 基于 A)。C 未包含 B,若硬塞,B 丢失。Git 拒绝,这就是非快进。

2.4 fetch vs pull:关键区别

命令干什么动了哪些指针
git fetch只下载远程提交和对象只更新远程跟踪分支
git pullfetch + 自动合并更新远程跟踪分支 + 合并到本地分支

白话:fetch是「先看看信箱里有啥新信」,pull是「看完后自动归档到你的文件夹」。多数时候先fetch再决定如何整合。

2.5 几条硬规矩

规矩白话
远程跟踪分支不可手动提交origin/main只能由 fetch 更新
push 前先 fetch看看远程是否有新东西
永远不要对共享分支用--force会覆盖别人的提交
--force-with-lease只用于自己的功能分支保险绳,不是通行证
push 被拒是 Git 在保护你别慌,先拉再推

2.6 新手最常踩的坑

表现办法
push 被拒就--force别人提交丢失fetch+ 整合,实在要强推用--force-with-lease
分不清 fetch 和 pull产生大量合并提交想看再用fetch,想一步到位用pull(建议配--rebase
不知道origin/main是什么以为是远程分支,实际是本地快照记住:由 fetch 更新的记忆
改了已推送的提交又推被拒,历史变了变基后--force-with-lease
多人推同一分支互相覆盖各开功能分支,走 PR/MR

3. 建议学习顺序

理解非快进 → fetch 和 pull 的区别 → pull --rebase → 远程跟踪分支 → force-with-lease → 多远程 → 三角工作流

4. 动手准备

要求 Git 2.43.0,使用本地模拟远程仓库,无需联网。

# 建假远程mkdir-p/tmp/fake-remote.git&&cd/tmp/fake-remote.git&&gitinit--bare-bmain# 建本地工作区mkdir-p/tmp/my-work&&cd/tmp/my-work&&gitinit-bmaingitconfig user.name"Ada Example"&&gitconfig user.email"ada@example.com"gitremoteaddorigin /tmp/fake-remote.git# 初始提交并推送printf'v1\n'>file.txt&&gitaddfile.txt&&gitcommit-m"init: 第一个版本"gitpush-uorigin main

输出显示远程分支已建立,本地main跟踪origin/main


5. 跟着做:一次完整远程进阶实验

5.1 制造非快进:模拟别人先推了代码

创建另一个工作区模拟 Bob:

mkdir-p/tmp/other-work&&cd/tmp/other-work&&gitclone /tmp/fake-remote.git.gitconfig user.name"Bob Example"&&gitconfig user.email"bob@example.com"printf'v2 from Bob\n'>file.txt&&gitaddfile.txt&&gitcommit-m"feat: Bob 的修改"gitpush

回到你的工作区,在不知情下提交并推送:

cd/tmp/my-workprintf'v2 from Ada\n'>file.txt&&gitaddfile.txt&&gitcommit-m"feat: Ada 的修改"gitpush

推送被拒,提示non-fast-forward。这是非快进。

5.2 先 fetch 看看远程有什么

gitfetch

输出显示origin/main更新到 Bob 的提交,但本地main未变。

git log --oneline --graph --all显示分叉:远程origin/main指向 Bob,本地main指向 Ada。

5.3 用 pull 整合(merge 方式)

gitpull

产生合并提交。若遇到冲突,解决后 push 成功。

5.4 用pull --rebase代替 pull

gitfetchgitpull--rebase

把你的提交移到远程最新之后,历史成一条直线。设置默认:

gitconfig pull.rebasetrue

5.5 远程跟踪分支是什么

git branch -r列出origin/maingit branch -vv显示本地分支与远程跟踪的关联。远程跟踪分支是只读的,由fetch更新。

5.6--force为什么危险

变基后推送被拒,git push --force会覆盖远程,可能丢失他人提交。

5.7--force-with-lease:保险绳

--force-with-lease要求远程与你本地origin/main一致,否则拒绝。若别人在你 fetch 后推送了,再--force-with-lease也会被拒,保护了他人代码。

5.8 远程管理:查看、添加、删除

  • git remote -v查看远程
  • git remote rename重命名
  • git remote remove删除
  • git remote add添加

5.9 多远程与三角工作流

你 fork 了老师的仓库为origin,老师的仓库为upstream。从upstream拉取,往origin推送,通过 PR 贡献。

gitremoteaddorigin https://github.com/你的用户名/课件作业.gitgitremoteaddupstream https://github.com/老师用户名/课件作业.gitgitfetch upstreamgitmerge upstream/maingitpush origin main

设置本地main跟踪origin/main


6. 命令按「用途」分组

6.1 拉取与整合

命令干什么
git fetch下载远程更新,不动本地分支
git fetch --all下载所有远程的更新
git pullfetch + merge
git pull --rebasefetch + rebase(推荐)
git config pull.rebase true让 pull 默认用 rebase

6.2 推送

命令干什么
git push正常推送
git push -u origin main推送并设置上游跟踪
git push --force强制推送(危险)
git push --force-with-lease安全强推(远程变了就拒绝)

6.3 远程管理

命令干什么
git remote -v列出所有远程
git remote add 名字 地址添加远程
git remote remove 名字删除远程
git remote rename 旧名 新名重命名远程

6.4 查看跟踪关系

命令干什么
git branch -r列出远程跟踪分支
git branch -vv列出本地分支及其跟踪关系
git branch --set-upstream-to=origin/main main设置上游跟踪

7. 对照表:降低记忆负担

7.1 push 被拒时怎么办

情况做法命令
远程有新提交,我落后了先整合再推git pull --rebasegit push
我改写了历史(自己的分支)安全强推git push --force-with-lease
改写了历史(共享分支)别推revert或沟通
不关心历史不推荐git push --force(极度危险)

7.2 fetch vs pull vs pull --rebase

命令下载了代码?合并了?历史形状
git fetch不变
git pull是(merge)多一个合并提交
git pull --rebase是(rebase)一条直线

7.3 --force vs --force-with-lease

命令会覆盖别人的提交吗?安全吗?
git push --force会,不检查危险
git push --force-with-lease远程有新提交就拒绝有保险绳

7.4 远程跟踪分支 vs 本地分支

概念例子谁更新它你能直接提交到上面吗
远程跟踪分支origin/maingit fetch不能
本地分支main你自己

8. 安全习惯

8.1 建议这样做

习惯原因
push 前先git fetch查看远程是否有新东西
设置pull.rebase true避免无意义合并提交
--force-with-lease代替--force多一层保护
--force-with-lease只用于自己的功能分支共享分支不要强推
强推前先fetch确保origin/main最新保险绳才有效
push 后用git log确认确保推了你想推的

8.2 绝对不要做的事

操作后果
对共享分支--force别人提交丢失
fetch--force-with-lease保险绳可能失效
推送包含密钥的提交密钥泄露,历史难清

8.3 推荐工作流(团队协作)

1. 开始干活前:git fetch 2. 整合远程:git pull --rebase 3. 开分支改代码、提交 4. 推之前再 fetch 一次 5. 正常推送:git push 6. 如果改写了历史(自己的功能分支):git push --force-with-lease

9. 真实场景

9.1 课程作业:和同学共用一个仓库

  • 各自开功能分支,不直接推main
  • 提 PR 让助教或组长审
  • 若 push 被拒,git pull --rebase再推

9.2 开源贡献:三角工作流

  1. fork 项目到自己的账号
  2. git remote add upstream 原仓库地址
  3. git fetch upstreamgit checkout -b fix/xx upstream/main
  4. 改好提交,git push -u origin fix/xx
  5. 在 GitHub 上从你的 fork 发 PR 到 upstream

9.3 推送被拒但急着想推

gitfetchgitlog--onelineorigin/main..HEAD# 查看本地独有提交gitpull--rebasegitpush

9.4 变基后要强推

在自己的功能分支上 rebase 后,推送被拒,使用git fetch && git push --force-with-lease origin feature/xxx

9.5 误推了敏感信息

删除文件并提交,但历史仍存在;紧急情况需重写历史(见后续章节),立即通知团队不要拉取。


10. 稍微多懂一点点(可选)

  1. 远程跟踪分支保存在.git/refs/remotes/origin/main,由 fetch 更新。
  2. --force-with-lease比较本地origin/main与远程最新哈希,不一致则拒绝;故需先 fetch。
  3. 可通过git remote set-url --push origin 禁止推送的地址防止误推。
  4. git push --force-if-includes(Git 2.30+)更严格,要求本地已整合远程提交。
  5. 即使被强推覆盖,远程 reflog 可能找回提交。

11. 小实验(请一定动手)

实验甲:制造并解决非快进

用假远程和两工作区,A 推,B 推被拒,Bfetchpull --rebase再推成功。

实验乙:force-with-lease 拦截

B 不 fetch 直接--force-with-lease被拒,fetch 后如有 A 新提交,仍会被拒,需整合再推。

实验丙:三角工作流

一个仓库当 upstream,一个当 fork,从 upstream 拉,推到 origin,模拟 PR。

通过标准:能独立处理推送被拒,知道何时用--force-with-lease,能说出它比--force安全在哪里。


12. 常见问题

问 1:推送被拒是不是我做错了?
不是,远程有你不包含的新提交,先 fetch 再整合。

问 2:fetch 和 pull 到底用哪个?
想看再决定用fetch,想一步到位用pull --rebase。建议配置pull.rebase true

问 3:--force-with-lease一定能保护我吗?
在 fetch 后、别人又推了这种时间差内,可能拦不住,但比--force安全得多。

问 4:能不能对main--force-with-lease
技术上能,但共享分支不应强推,用revert更安全。

问 5:pull 出了合并提交怎么办?
设置pull.rebase true,以后不会出现。

问 6:origin/mainmain有什么区别?
origin/main是本地对远程 main 的快照,main是你本地分支。

问 7:删了 remote 会删代码吗?
只删关联关系,不删本地代码和远程仓库。

问 8:三角工作流和普通推送有什么区别?
普通推送直推主仓库,三角工作流推自己的 fork,再通过 PR 合并。


13. 总结、学习路线与思维升华

13.1 这一章请记住的

记住什么
非快进远程有你不包含的提交,推送被拒是 Git 在保护你
fetch vs pullfetch 只下载,pull = fetch + 整合
pull --rebase避免合并提交,保持历史一条线
–force危险,直接覆盖别人的提交
–force-with-lease安全强推,远程变了就拒绝
远程跟踪分支origin/main是本地快照,由 fetch 更新
多远程origin + upstream,三角工作流
下一章额外命令速查(21 章)

13.2 在整个系列中的位置

01 认识 Git 02 三区模型 03 基本工作流 04 安全地撤销 05 分支与合并 06 远程协作 …… 19 暂存与清理 20 远程进阶 ← 当前 21 额外命令速查 22 冲突策略 23 安全实践 ……

13.3 思维升华

保险绳不是鼓励你冒险,而是当你必须强推时多一道确认。
推送被拒是 Git 在说「远程有新东西你还没看」,不是在跟你作对。
先 fetch 看清楚,再决定怎么整合。能不强推就别强推,必须强推就用--force-with-lease
信箱类比:塞信前先看看信箱里还是不是你记得的样子——这就是 force-with-lease 的全部意义。

13.4 参考资料

  • Pro Git 中文版 — 远程分支
  • Pro Git 中文版 — 与远程协作
  • 官方文档:git push / fetch / pull / remote
  • 命令输出样例验证环境:Git 2.43.0;演示作者信息:Ada Example <ada@example.com>

13.5 本章检查清单

  • 能说清「非快进」是什么,为什么推送会被拒
  • 能区分fetchpull
  • 会用git pull --rebase保持历史干净
  • 知道--force-with-lease--force安全在哪里
  • 能解释origin/main是什么
  • 会添加和删除远程仓库
  • 能说出三角工作流的三个步骤
  • 推送被拒时知道该怎么处理

按回车前先预判状态——这一章的保险绳,是你对远程仓库的清醒认识。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/14 13:55:52

1.3 Qt中的信号槽

1. 信号和槽概述信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽&#xff0c;实际就是观察者模式(发布-订阅模式)。当某个事件发生之后&#xff0c;比如&#xff0c;按钮检测到自己被点击了一下&#xff0c;它就会发出一个信号&#xff08;signal&#xff09;。这种发出是没有…

作者头像 李华