Git常用命令指南
Git常用命令指南
⚓️ 基础回顾:标准同步流程
我们需要先明确 Git 的常规工作流,这是理解后续“破坏性操作”的基准。
-
下拉代码:git pull origin main vs git fetch
-
git pull origin main
作用:将远程 main 分支的最新代码拉取到本地,并自动尝试合并。
实质:它是git fetch(下载远程变更到跟踪分支) +git merge(合并到当前分支) 的组合。
适用场景:日常开发快速同步同事代码,但可能产生合并冲突或多余的 Merge 提交。
注:推荐git pull --rebase origin main保持线性历史,避免 Merge 节点。 -
git fetch origin(更安全的选择)
作用:仅下载远程仓库的最新提交和分支信息到本地远程跟踪分支(如origin/main),不修改当前工作分支。
后续步骤:手动查看差异(如git log --oneline --graph --all),再决定git merge origin/main或git rebase origin/main。
优势:预览变更,避免意外覆盖本地未提交工作;团队协作时先检查差异再合并。
核心区别:
命令 下载变更 自动合并 风险 git pull✅ ✅ 中等 git fetch✅ ❌ (手动) 低 -
-
上传代码:git push origin main
作用:将本地的 commit 推送到远程仓库。
硬性规则:Git 默认要求**“快进式”(Fast-forward)**推送。这意味着,远程仓库的最新提交必须是你本地历史的“祖先”。
失败原因:如果远程有了新提交(别人推了代码),而你没有先pull或fetch+merge,Git 会拒绝推送并提示fetch first。这也是后续需要--force的原因。
🧭 场景一:远程覆盖本地(放弃本地修改)
适用情况:
- 本地环境乱了(比如改错了文件、测试配置搞坏了)。
- 想完全丢弃本地未提交或已提交的修改。
- 希望本地代码状态与远程仓库(origin)完全一致。
🚀 操作命令:
# 1. 获取远程最新状态(不合并)
git fetch --all
# 2. 将本地分支重置为远程分支的状态
git reset --hard origin/main
**
🔍 发生了什么?
- 当前分支指针:直接移动到
origin/main指向的提交。 - 工作区与暂存区:所有未提交的修改、新增的文件(未追踪除外)都会被永久删除。
- 本地提交:所有本地比远程多出的
commit都会丢失。
⚠️ 警告:这是一个破坏性操作,执行前请确认本地没有需要保留的代码。
🧭 场景二:本地覆盖远程(强制更新历史)
适用情况:
- 远程仓库的历史“脏”了或不需要了。
- 你进行了
rebase或amend操作,导致本地历史与远程分叉。 - 你确定本地版本才是正确的唯一真理。
🚀 操作命令:
git push origin main --force
(注:如果分支名不是 main,请替换为对应的分支名)
🔍 发生了什么?
- 远程分支的历史会被你本地的历史完全替换。
- 远程上其他人推送的提交(如果存在)将被覆盖且不可恢复。
🛠️ 场景三:只修改最近一次提交(不产生新记录)
很多时候我们并不是要重置整个仓库,只是想:“哎呀,刚才提交时漏了一个文件” 或者 “提交信息写错了”。
此时不要用 git reset,也不要提交一个新的 commit(产生类似 "fix bug" 这种无意义提交),最干净的方式是 amend。
**✅ 使用 git commit --amend**
- 将漏掉的修改加入暂存区:
git add .
- 合并到上一次提交:
# 弹出编辑器修改提交信息
git commit --amend
# 或者:保持原提交信息,直接合并
git commit --amend --no-edit
结果:你当前的修改融入了上一次提交,没有产生新的 Commit ID(但旧的 ID 变了,因为内容变了)。
🔥 核心讨论:如何安全地“强推”?
当你使用了 commit --amend 或者 rebase 后,本地历史和远程历史就不一样了。此时直接 git push 会报错,必须使用强制推送。
但是,--force 是 Git 中最危险的命令之一。
❌ 危险做法:git push --force
它的潜台词是:“我不管远程有什么,直接用我的覆盖。”
- 风险:如果你的同事刚才推了一段代码到远程,你的操作会直接抹除他的提交,且通常没有警告。
✅ 推荐做法:git push --force-with-lease
它的潜台词是:“如果远程没人动过(和我本地缓存的远程状态一致),我就覆盖;否则报错提醒我。” **
📊 对比总结
| 特性 | git push --force | git push --force-with-lease |
|---|---|---|
| 行为逻辑 | 无条件覆盖 | 有条件覆盖(带租约检查) |
| 是否检查远程更新 | ❌ 不检查 | ✅ 检查 |
| 安全性 | 低(容易误删同事代码) | 高(类似于乐观锁) |
| 推荐场景 | 只有你一个人用的私有分支 | 任何多人协作的分支 |
🧠 举个栗子
假设远程仓库是 A -> B -> C。
- 你在本地把
C修改成了C'(amend 操作)。 - 同事在远程推入了新提交
D,现在远程是A -> B -> C -> D。
此时你尝试推送:
- 使用
--force:成功。远程变为A -> B -> C'。后果:同事的 D 提交丢失了! - 使用
--force-with-lease:失败。Git 提示远程有新内容。后果:你被拦下来了,你需要先 pull 下来解决冲突。
💡 总结与建议
- 想丢弃本地修改:用
git reset --hard origin/branch。 - 想修补上次提交:用
git commit --amend。 - 必须强制推送时:永远优先使用
--force-with-lease。 - 关于
git-filter-repo:那是用于清洗大文件或重写整个仓库历史的核武器,日常修改提交不用杀鸡用牛刀。