惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 【当耐特】
云风的 BLOG
云风的 BLOG
罗磊的独立博客
C
Check Point Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Blog — PlanetScale
Blog — PlanetScale
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
J
Java Code Geeks
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
I
InfoQ
Hugging Face - Blog
Hugging Face - Blog
T
Tailwind CSS Blog
B
Blog RSS Feed

木灵鱼儿

VS Code BYOK 配置生成器 - 木灵鱼儿 2026 最新禁止浏览器密码管理器弹出教程 - 木灵鱼儿 16 NestJS 企业级 RBAC 权限控制体系 - 木灵鱼儿 15 NestJS 统一响应体设计(信封模式) - 木灵鱼儿 14 NestJS 生产级错误过滤方案 - 木灵鱼儿 13 NestJS 集成 TypeORM 完全指南 - 木灵鱼儿 12 NestJS 集成 Prisma ORM 完全指南(Prisma v7) - 木灵鱼儿 11 NestJS 注册与登录接口的密码安全设计 - 木灵鱼儿 10 NestJS JWT 身份验证完全指南 - 木灵鱼儿 09 NestJS 使用 @nestjs-swagger 生成 API 文档 - 木灵鱼儿 08 NestJS DTO 校验、Entity 脱敏与 Mapped Types 实战(TypeORM & Prisma) - 木灵鱼儿 07 NestJS 使用Caching缓存(cache-manager) - 木灵鱼儿 06 NestJS 使用Redis - 木灵鱼儿 05 Nestjs 高性能构建之SWC与Typescript7选型 - 木灵鱼儿 04 Nestjs API版本控制策略 - 木灵鱼儿 NestJS 正确处理日志 - 木灵鱼儿 NestJS config模块扩展用法.md - 木灵鱼儿 宝塔如何给网站一次性绑定两个域名 - 木灵鱼儿 NestJS 环境变量与配置管理(Config 模块) - 木灵鱼儿 如何使用 FNM 自动切换不同项目的 Node.js 版本 - 木灵鱼儿 如何使用 Node.js Corepack 自动锁定和切换项目包管理器版本 - 木灵鱼儿 日常开发中的 void:从忽略 Promise 到理解 JavaScript 历史写法 - 木灵鱼儿 git 进阶指南:如何用 Git Worktree 完美应对紧急 Bug 与多分支联调 - 木灵鱼儿 了解并解决 Git 大小写“无感”的幽灵 Bug - 木灵鱼儿 从零开始:手把手教你封装一个企业级 Axios 请求模块 - 木灵鱼儿 03-Vue Query 高级进阶:应对复杂业务场景的硬核套路 - 木灵鱼儿 02-Vue Query 快速入门:从零构建你的第一个声明式查询 - 木灵鱼儿 01-异步状态管理新范式:为什么在 Vue 3 中使用 vue-query? - 木灵鱼儿 Windows 下如何快速复制目录的同时排除指定的目录和文件 - 木灵鱼儿 x86多网口软路由+pve+爱快ikuai+iStoreOS实现组网和翻墙 - 木灵鱼儿
git 如何将所有历史提交合并为一条 - 木灵鱼儿
木灵鱼儿 · 2026-06-09 · via 木灵鱼儿

前言

最近在管理git仓库提交的时候,发现自己开始变得洁癖了,原来的开发流程是从主分支分支创建一个feature分支,然后feature分支开发完成后,压缩合并到主分支,这样不管 feature 分支有多少次提交,合并到主分支后,都会变成一条提交。

习惯了这种方式后,最近在新仓库做项目基础搭建的时候,因为是直接在main分支上提交的,加上nuxt4这个框架没什么可参考的模板,大部分时间都是自己在摸索,导致产生了很多提交记录,等基建完成后,就想着能不能把这些提交记录合并成一条提交,这样就不会显得太乱了。

于是就有了这篇文章,记录一下如何将所有历史提交合并成一条提交。

警告:安全第一

修改 Git 历史属于高风险操作。在开始之前,请务必确认:

  1. 这是你个人独立开发的项目,或者:
  2. 你的团队成员已经知晓此操作。因为历史重写后,所有协作者的本地仓库都需要手动同步,否则会导致严重的冲突。

将所有历史提交合并为一条

要把一个项目自创建以来的所有提交合并为一条,最彻底、最干净的方法是使用 “孤儿分支(Orphan Branch)” 法。

步骤 1:创建并切换到一个全新的“孤儿”分支

这个分支的特点是:没有任何历史提交记录,但保留你当前所有的代码文件。

git checkout --orphan temp_main

步骤 2:将所有文件添加到暂存区

git add -A

步骤 3:提交代码,作为全新的第一次提交

git commit -m "init"

此时,你的代码库在 temp_main 分支上只有一条名为 "init" 的提交记录了。

步骤 4:删除旧的本地 main 分支

我们需要把旧的、带有杂乱历史的分支删掉:

git branch -D main

步骤 5:将当前分支重命名为 main

git branch -m main

至此,你本地的 main 分支已经重塑成功,历史记录只剩下一条 "init"。

步骤 6:强推到远程仓库

因为你改变了历史,直接推送会被拒绝,必须使用强制推送(Force Push)

git push -f origin main

解决“推送完无法拉取”的问题

在强推成功后,你或者你的同事如果直接运行 git pull,大概率会遇到类似下面的报错:

fatal: refusing to merge unrelated histories
# 或者提示:Your branch and 'origin/main' have diverged...

为什么会这样?

因为 Git 是基于 Commit Hash(提交哈希值) 来比对历史的。
虽然远程仓库和本地仓库的代码内容一模一样,但由于你重写了历史,远程的 "init" 提交是一个全新的哈希值,而你(或同事)本地还保留着旧的提交链。Git 认为这是两个完全不同的项目,因此出于安全保护,拒绝了自动合并。

正确的解决方案

既然远程的 main 已经是你想要的最终状态(只有一个 init 提交),你只需要强行让本地与远程保持一致,抛弃本地旧的历史。

在本地终端依次运行以下两条命令:

# 1. 获取远程最新的提交数据(不进行合并)
git fetch origin

# 2. 将本地分支强制重置为远程分支的状态
git reset --hard origin/main

命令解析:

  • git fetch origin:告诉本地 Git 去看一眼远程仓库现在长什么样。
  • git reset --hard origin/main:这是灵魂一步。--hard 会丢弃本地所有未提交的修改和旧的历史,强行将本地指针对齐远程的 main

执行完毕后,本地和远程彻底同步,后续的 git pullgit push 即可恢复正常工作!

版权申明

本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。