文档教程DevOps运维【免费下载链接】devops-exercisesLinux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions项目地址https://gitcode.com/GitHub_Trending/de/devops-exercises点击查看免费下载提交压缩squash commits是 Git 日常开发与代码评审中高频使用的历史整理技术它能把一段连续、琐碎的提交记录合并成一个逻辑完整的提交让仓库历史变得干净、可读、易于回溯。本文以 devops-exercises 仓库中 Git 主题的 Squashing Commits 练习及其标准答案为骨架完整还原从制造两个独立提交到交互式变基合并的每一步命令行操作并深入讲解交互式变基git rebase -i的编辑器语义、根提交root commit场景的报错与补救、以及一次合并多个提交的进阶用法。读完本文你将能够独立完成任意数量连续提交的压缩并理解这一操作在提交历史层面到底发生了什么。一、什么是提交压缩为什么要压缩提交Git 中的每次提交commit都是一个完整的快照对象它记录当前工作区全部被跟踪文件的树tree、指向父提交parent的引用、作者/提交者信息与提交信息。因此提交历史本质上是一条通过父指针串联起来的链历史越长、提交越碎这条链就越难读懂。压缩提交就是把链上相邻的多个提交合并为一个让它们共享同一个提交信息和同一个快照。仓库原练习在完成后给出了两个思考题答案本身就是压缩动机的官方注脚为什么要压缩提交历史会变得更干净cleaner并且更容易追踪变更——尤其是当历史里充斥着大量删掉了一个字符这类细碎提交时逐条追踪成本极高合并后逻辑更聚焦。是否可能一次压缩超过 2 个提交可以。压缩的数量只受交互式变基规则约束2 个只是最小示范场景。此外从工程实践看压缩通常在以下场景使用合并一个功能分支feature branch时把几十个中间提交整理成 12 个逻辑提交再合入主线修复评审意见后把修 bug 的提交与最初实现的提交合并以及保持提交粒度与代码逻辑单元一致方便git bisect定位问题。二、复现实验场景创建两个独立提交本仓库的 Squashing Commits 练习要求先在仓库中制造两个独立的提交再用git rebase -i将它们合并。官方标准答案给出的完整操作如下# 1. 创建一个内容为 Mario 的新文件并提交 echo Mario new_file git add new_file git commit -m New file # 2. 修改刚创建的文件内容为 Mario Luigi创建第二个提交 echo Mario Luigi new_file git commit -a -m Added Luigi # 3. 验证当前存在两个独立提交 git log这里有两处值得展开的命令细节git add new_file把新文件放入暂存区staging area / index随后git commit才把它固化进历史。这一步对应仓库里更基础的 Commit 01 练习——其标准答案展示了mkdir my_repo cd my_repo、git init、git add file、git commit的完整初始化流程本文场景默认你已在一个已初始化的仓库中操作。第二次提交使用了git commit -a简写-a--all会把已跟踪文件的修改自动加入暂存区再提交省去了再次git add new_file。注意它只对已跟踪文件生效这正是它在此处可行的原因——new_file已在第一次提交中被 Git 跟踪。执行完git log后你应当看到两条提交记录大致形如commit 4016808 (HEAD - main) Added Luigi commit 5412076 New file两条提交的哈希示例中的5412076、4016808因仓库而异但结构必然如此Added Luigi位于HEAD其父提交是New file。三、核心操作git rebase -i HEAD~2 交互式压缩3.1 命令含义压缩两个提交的标准命令是git rebase -i HEAD~2参数拆解如下git rebase变基命令本质是把一段提交重新应用到新的基点上同时允许在应用过程中改写提交-i--interactive进入交互模式在编辑器默认由core.editor决定通常是 vim/nano中列出待处理提交清单供你逐条指定动作HEAD~2变基起点表示HEAD向前追溯 2 个提交。交互式变基允许重写自该提交之后的所有提交因此HEAD~2意味着我们获得机会改写最新的 2 个提交。3.2 编辑器清单pick 与 squash运行命令后编辑器会打开一个类似如下的清单按时间从旧到新排列pick 5412076 New file pick 4016808 Added Luigi每行由动作关键字 提交哈希 提交信息三部分组成。此时只需要做一件事把第二个提交Added Luigi的动作由pick改为squashpick 5412076 New file squash 4016808 Added Luigi清单中其余以#开头的行是注释帮助信息其中明确列出了每个动作的含义包括pick保留该提交原样应用到新历史中也可简写为psquash将该提交合并到前一个提交中并合并两者的提交信息简写sfixup与squash类似但丢弃该提交的提交信息直接沿用前一条简写freword保留提交但允许修改其提交信息简写rdrop删除该提交简写d。保存并退出编辑器vim 中为:wq后Git 立即执行把Added Luigi的内容与New file合并、重放为一个新提交的流程。3.3 提供合并后的提交信息由于squash会合并两条提交信息Git 会再次打开编辑器让你为最终合并出的那一个提交撰写新信息。编辑器顶部通常是两行原始信息的拼接注释形式给出例如# This is a combination of 2 commits. # This is the 1st commit message: New file # This is the commit message #2: Added Luigi你可以删除注释与旧信息输入一句能概括两次变更的提交信息例如Add Mario Luigi to new_file保存退出后压缩即告完成。用git log验证你只会看到一条提交且它的快照内容等价于原来两个提交的最终状态new_file内容为Mario Luigi而不会再出现中间那条Added Luigi。四、常见报错invalid upstream HEAD~2 与根提交处理仓库官方答案特别标注了一个高频故障场景如果运行git rebase -i HEAD~2时报出类似fatal: invalid upstream HEAD~2的错误通常意味着第二个提交其实就是仓库的根提交root commit——即整个仓库历史只有 2 条提交而HEAD~2要追溯到第 0 个提交不存在这样的祖先。本仓库的示例恰好会触发该场景如果仓库是全新初始化的那么New file就是根提交HEAD~2将无效。官方答案给出了两种补救方式改用git rebase -i --root--root允许将变基起点延伸到整个历史的根从而把根提交本身也纳入可重写范围。运行后清单同样会列出全部提交此处即那 2 条后续操作改pick为squash、编辑提交信息与常规流程完全一致。先创建一个初始提交在这两个提交之前补一个初始提交例如空的 README 提交使HEAD~2能正确指向该初始提交随后即可用常规的git rebase -i HEAD~2。两种方案都可行--root更直接而补初始提交的思路更贴近历史上本应先有一个初始化提交的常规仓库形态。值得一提的是git rebase -i --root同样适用于压缩历史中最早的两个提交——这正是一次压缩超过 2 个提交能力的延伸。五、进阶一次压缩多个提交与其他压缩途径5.1 压缩 N 个提交把范围从 2 扩展到 N 同样简单git rebase -i HEAD~N在清单中保留最旧的一个提交为pick其后的 N-1 个提交全部改为squash或fixup。Git 会从旧到新逐层合并最终只产生一个提交。若使用fixup则不会弹出合并提交信息的编辑步骤直接沿用第一条提交信息适合只保留主体描述、丢弃修复性描述的场景。5.2 其他压缩手段除交互式变基外业界常用的压缩方式还有两种可依据场景选用git reset --soft 重新提交git reset --soft HEAD~N把分支指针回退 N 个提交但保留暂存区与工作区内容之后一次git commit即可把 N 个提交的内容打包为一个新提交。它比交互式变基更少交互适合不需要逐个挑选、明确要合并最近 N 个的场合。git merge --squash把分支合并为单条提交的合并方式适用于功能分支整体合入主干时只保留一个提交的场景与本文改写本分支历史的诉求略有不同但目的同源。无论哪种方式压缩的本质都是创建全新的提交对象、重写历史链——原提交并不会从对象库中立即消失而是成为孤儿对象最终由git gc回收。5.3 重要的边界绝不重写已推送的历史压缩提交会改变提交哈希因为提交信息、父指针与快照树都变了因此只应对尚未推送push到共享远端、或只有你一个人在用的分支执行。一旦历史已被其他人拉取重写历史会造成远端与本地的分叉给协作者带来巨大的合并痛苦。安全的做法是先在本地的功能分支上压缩完成再git push --force-with-lease而非危险的--force推送到远端。六、验证与知识点串联压缩完成后建议做如下验证git log --oneline # 确认只剩一条提交 git show HEAD # 确认最终快照包含 Mario Luigi若想对比压缩前后的差异也可在压缩前用git log --oneline或git log --format%h %s留档原历史。在 devops-exercises 仓库中本文场景与周边练习形成完整的 Git 知识链Commit 01 练习教你完成第一次提交并验证见标准答案Branch 01 练习教你基于已有提交开分支并验证提交归属见标准答案而本练习则在前两者基础上引入历史改写。此外Git 主题 README 的 Rebase 问答区还保留了如何压缩最后两个提交的开放问题本练习的标准答案正是它的直接实现两者可互为印证。七、小结本练习虽短却覆盖了 Git 历史改写中最核心的一组知识提交的链式结构、git rebase -i的交互语义、pick/squash/fixup的动作差异、根提交导致的invalid upstream报错及其两种解法以及一次压缩 N 个提交的扩展用法。牢记两条红线即可安全上手未推送的历史才值得重写压缩后务必验证最终快照与提交信息。通过本仓库 squashing_commits.md 练习与标准答案的反复实践你将能把这条命令链内化为日常提交整理的肌肉记忆。赞分享文档教程DevOps运维【免费下载链接】devops-exercisesLinux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions项目地址https://gitcode.com/GitHub_Trending/de/devops-exercises点击查看免费下载相关推荐Git Squash 提交压缩实战用交互式 Rebase 将多条提交合并为一条first-contributions 开源贡献指南Git Squash 提交压缩实战用交互式 Rebase 将多条提交合并为一条first contributions 开源贡献指南 本篇技术指南以 fir文档教程开源治理first-contributions 开源贡献实战用交互式 RebaseSquash Commits将多个 Commit 合并为一个first contributions 开源贡献实战用交互式 RebaseSquash Commits将多个 Commit 合并为一个 本文基于 firs文档教程开源治理一条命令免费激活 Windows 和 OfficeMAS 激活工具完整教程一条命令免费激活 Windows 和 OfficeMAS 激活工具完整教程 刚装完系统右下角挂着「激活 Windows」水印Office 打开也是受限模式操作系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考