Git 使用详尽教程 — 从安装到工作流、真实场景与常见坑
目录
- 核心概念速览
- 安装与首次配置(简要)
- 日常工作流(示例命令 + 场景演示)
- 分支策略与团队协作(GitHub/GitLab 风格)
- 合并、变基与冲突处理(详细步骤)
- 回退、修复与历史重写(危险操作要谨慎)
- 常见工作场景与实战示例(hotfix、同步 fork、cherry-pick)
- 常见坑 + 逐条解决方案(可复制命令)
- 进阶话题速览(submodule、LFS、hooks、gitattributes)
- 精简常用命令速查表(便于复制)
1. 核心概念
- commit(提交):记录代码快照,每次提交有唯一 SHA-id。
- HEAD:当前检出的提交或分支的指针(“我现在在时间线的哪儿”)。
- Index / Staging area(暂存区):
git add后的下一站,git commit从这里生成提交。 - branch(分支):轻量指针,指向某个提交,方便并行开发。
- remote(远程):常见如
origin(你 fork/clone 来的那个仓库),upstream(上游仓库)。 - merge / rebase:两种把分支合并回主线的思路,产生历史差异(见后文)。
2. 安装与首次配置
(你已经有之前的安装文档,这里只列核心配置)
# 全局用户名与邮箱(必须)
git config --global user.name "你的名字"
git config --global user.email "你的邮箱@example.com"
# 设置默认编辑器(例如 VSCode)
git config --global core.editor "code --wait"
# 开启彩色输出
git config --global color.ui auto
# 全局 .gitignore
git config --global core.excludesfile ~/.gitignore_global
把 ~/.gitignore_global 填上 OS / 编辑器常见垃圾文件(.DS_Store, Thumbs.db, *.log 等)。
3. 日常工作流(Feature-branch,最常见)
目标:主分支(main/master)保持可发布状态;开发在短生命周期分支上,完成后通过 PR/MR 合并。
示例:创建 feature 分支 → 本地开发 → 推送 → 发 PR。
# 从最新的 main 开始
git checkout main
git pull origin main # 或 git fetch && git merge origin/main
# 新建分支并切换
git switch -c feature/xxx
# 开发过程中(分阶段提交)
git add file1 file2
git commit -m "feat: 增加 xxx 功能 - explain briefly"
# 多次提交...
# 推送到远程并建立上游关联
git push -u origin feature/xxx
# 在 GitHub/GitLab 上创建 PR,等待 Code Review
工作中常见建议
- 提交小而原子(单一变更目的),方便回退与 review。
- PR 描述完整(改动目的、如何测试、截图/日志/性能影响)。
- 尽量让 PR 不超过一天未合并(避免长期分支冲突)。
4. 分支策略与团队协作
- GitHub Flow(推荐轻量):主分支始终可部署,短小 feature 分支 + PR。
- GitLab Flow / GitFlow(正式/较重):有
develop,release,hotfix等分支,适合版本管理更复杂的团队。 - Trunk-based:非常短-lived 分支,鼓励频繁合并到 trunk,CI 强制测试。
企业里通常:保护 main(require PR、CI 通过、review),禁止强推(force push)。
5. 合并、变基与冲突处理
merge vs rebase(核心对比)
merge:把两个历史合并,保留分支点,常见命令git merge feature。
优点:历史真实,保留并行信息;缺点:历史较“分叉”。rebase:把分支上的提交“搬到”目标分支后面,得到线性历史,命令git rebase main。
优点:清爽线性历史;缺点:改变提交 SHA —— 不要对公共分支做 rebase(会给他人制造痛苦)。
处理冲突(示例:rebase 中发生冲突)
- 在 feature 分支上:
git rebase main - 若冲突发生,Git 会停下,
git status会显示冲突文件。 - 手动编辑文件,解决冲突(删除
<<<<<<<标记) git add <file>标记解决git rebase --continue继续- 如要放弃变基:
git rebase --abort
合并冲突常见技巧:
- 先 pull 最新
main并 rebase 本地分支,避免大型 PR 冲突积累。 - 使用
git mergetool或 IDE 的 merge 工具(VS Code、IntelliJ)来可视化解决。 - 如果冲突内容很复杂,可创建临时分支保存当前状态,然后回滚重做。
合并完成后:若使用 rebase 并已推送到远程,需要 git push --force-with-lease(首选 --force-with-lease 而非 --force,更安全)。
6. 回退、修复与历史重写(细节与安全)
常见场景与对应操作
-
改动还没提交(工作区修改)
放弃修改:git restore <file> # 等价于旧的 git checkout -- file -
已暂存但未提交(staged)
取消暂存:git reset <file> -
想修改最后一次提交的内容或信息(还未 push)
git commit --amend -m "新的提交信息"若已经 push,修改历史需谨慎并通知团队(见下)。
-
回退已经推送到公共分支的坏提交(推荐)
使用git revert生成一个新提交来撤销之前的提交(安全,不改变历史)。git revert <commit-sha> git push -
彻底删除本地历史(危险)
git reset --hard <sha>会丢弃工作区和暂存的修改。谨慎使用。 -
误 push 后想重写历史
-
先确保所有协作者知晓;
-
推荐使用
git push --force-with-lease(比--force更安全); -
使用
reflog恢复丢失的提交(若误操作):git reflog git checkout -b recover <sha>
-
7. 常见工作场景与实战示例
场景 A:主分支紧急 bug(hotfix)
-
在本地从
main建 hotfix 分支:git checkout main git pull origin main git switch -c hotfix/critical-fix # 修复,提交 git commit -am "fix: 修复生产紧急 bug" git push -u origin hotfix/critical-fix -
在 remote 上创建 PR → 通过后合并到
main(通常使用 merge commit 或 squash,按团队规则)。 -
合并后把 hotfix 合并回
develop(若你使用 GitFlow)。
场景 B:你 fork 了上游仓库,需要与上游同步
# 添加上游
git remote add upstream git@github.com:OriginalOwner/Repo.git
# 同步 main
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
或更常用的保持线性:
git fetch upstream
git checkout feature/xxx
git rebase upstream/main
# 处理冲突后
git push --force-with-lease
场景 C:在多人协作中把别人的单个提交拣到你的分支(cherry-pick)
git checkout feature/xxx
git fetch origin
git cherry-pick <commit-sha>
# 解决冲突 → git add ... → git cherry-pick --continue
8. 常见坑 + 逐条解决方案(工作中最容易踩的雷)
这些是团队与个人在实际项目里最常遇到的问题,并附上可复制命令与建议。
坑 1:误把密码/密钥提交到仓库(机密泄露)
步骤(紧急):
-
立刻撤销/吊销该秘钥(最重要)。
-
在本地移除该文件并从历史中删除:
-
推荐工具:
git filter-repo(现代、安全、快速)或bfg-repo-cleaner。示例(filter-repo 要另行安装):git filter-repo --path path/to/secret.txt --invert-paths -
或用 bfg:
bfg --delete-files secret.txt。
-
-
强制推送到远程(并通知团队):
git push --force --all git push --force --tags -
更新 README 或通知安全负责人。
注意:即便从 Git 历史删除,第三方镜像/缓存可能仍留存,必须换密钥并审计。
坑 2:在公共分支上做 rebase 并强推,导致他人历史被破坏
修复:
- 用
git reflog找到被覆盖的提交,用git checkout -b restore <sha>恢复;协调团队合并回去。
预防:设置分支保护(禁止强推),仅允许 PR 合并。
坑 3:换行符(CRLF/LF)导致大量文件变动
解决:
-
在 repo 根放
.gitattributes:* text=auto *.sh eol=lf -
Windows 用户:
git config --global core.autocrlf true,Linux/macOS 用户:git config --global core.autocrlf input。 -
如果仓库已经混乱,参考
.gitattributes后执行一次干净重检出:git rm --cached -r . git reset --hard
坑 4:子模块(submodule)更新后别忘了提交指针
要点:子模块是记录某个提交 SHA,不会自动更新父仓库。步骤:
git submodule update --init --recursive # 初始化
# 进入子模块更新
cd path/to/submodule
git fetch && git checkout some-commit
# 返回父 repo,提交子模块指针变更
cd ../..
git add path/to/submodule
git commit -m "update submodule pointer"
git push
坑 5:仓库体积飙升(大文件、历史垃圾)
临时清理:
git gc --aggressive --prune=now
git repack -ad
如果要从历史彻底移除大文件,请使用 git filter-repo 或 bfg,并强推。
坑 6:stash 消失或忘了 stash 内容在何处
-
查看 stash 列表:
git stash list -
恢复某个 stash 到新分支(安全):
git stash branch recover-stash stash@{2}
坑 7:detached HEAD(检出 tag 导致)
表现:提示你处在 detached HEAD,提交不会更新任何分支。
做法:
git switch -c my-fix-branch # 在当前点创建分支并切换
坑 8:误删分支后需要恢复
使用 reflog 找提交 SHA,然后:
git checkout -b restore-branch <sha>
9. 进阶话题:实用建议与示例
Git LFS(大文件)
-
用于管理二进制大文件(模型、媒体),需要安装
git-lfs:git lfs install git lfs track "*.psd" git add .gitattributes git add file.psd git commit -m "add large file" -
注意:LFS 仍会占用 server 存储配额(如 GitHub)。
钩子(hooks)
-
本地
.git/hooks/pre-commit可做 lint、测试:
示例(简单):#!/bin/sh # 检查 Python 文件是否包含 TODO if git diff --cached --name-only | grep '\.py$' >/dev/null; then if git diff --cached | grep 'TODO' >/dev/null; then echo "Found TODO in staged Python files. Please remove." exit 1 fi fi -
推荐使用
pre-commit框架统一团队 hooks(跨平台,易配置)。
.gitattributes(控制合并/换行/二进制)
- 强制某些文件使用特定 EOL、合并策略,或标记为二进制防止自动合并。
针对 CI 与保护分支的团队做法
- 启用
branch protection:要求 PR、CI 通过、至少一人 review、禁止 force push。 - 在合并策略上规定
squash merge/merge commit/rebase and merge,并写入 CONTRIBUTING.md。
10. 精简常用命令速查(挑最常用的 40 条)
git --version
git init
git clone <url>
git status
git add <file>
git add .
git commit -m "msg"
git commit --amend
git log --oneline --graph
git diff
git diff --staged
git restore <file>
git reset <file>
git branch
git branch -d <branch>
git switch <branch>
git switch -c <branch>
git checkout <branch> # 旧命令等价于 switch
git merge <branch>
git rebase <branch>
git rebase -i HEAD~N
git cherry-pick <sha>
git revert <sha>
git fetch
git pull
git pull --rebase
git push
git push -u origin <branch>
git push --force-with-lease
git remote -v
git remote add upstream <url>
git stash
git stash pop
git stash branch <name>
git tag -a v1.0 -m "msg"
git show <sha>
git reflog
git gc
附:提交信息模板
采用简洁且有含义的提交风格,便于生成 changelog:
<type>(<scope>): <简短描述>
可选正文(为什么这么改,影响哪些地方)
BREAKING CHANGE: <说明破坏性改动>
常用 type: feat, fix, docs, style, refactor, perf, test, chore。
示例:
feat(auth): add OAuth2 login
支持 Google / GitHub 登录,增加 token 刷新逻辑。
结语
Git 是把你工作中“时间”和“版本”组织起来的超级工具,但它不是魔法:良好的分支策略 + 小而频繁的提交 + 清晰的 PR 描述 + 保护主分支,能把绝大多数麻烦扼杀在摇篮里。遇到历史修复或强推类操作,先冷静、通知团队并先备份(git reflog 能救你很多次)。
作者:FeiLink
本文部分内容由 AI 辅助生成,并经人工整理与验证,仅供参考学习,欢迎指出错误与不足之处。
1395

被折叠的 条评论
为什么被折叠?



