目录
第一章:时光机:撤销与恢复
1.1 场景一:撤销工作区的修改
问题:你在修改CSS样式时,改得一团糟,想恢复到上次提交的状态。
bash
# 查看修改
git status
# 输出:
# On branch main
# Changes not staged for commit:
# modified: css/style.css
# 查看具体修改
git diff css/style.css
# 撤销工作区的修改(恢复到上次提交的状态)
git restore css/style.css
# 或使用旧命令
git checkout -- css/style.css
# 验证
git status
# 输出:nothing to commit, working tree clean
撤销所有文件的修改:
bash
# 撤销所有修改
git restore .
# 或
git checkout -- .
1.2 场景二:撤销暂存区的文件
问题:你不小心把不该提交的文件添加到了暂存区。
bash
# 假设你创建了一个包含密码的配置文件
echo "database_password=secret123" > config.local
# 不小心添加到暂存区
git add .
# 查看状态
git status
# 输出:
# On branch main
# Changes to be committed:
# new file: config.local
# 从暂存区移除(但保留工作区的修改)
git restore --staged config.local
# 或使用旧命令
git reset HEAD config.local
# 查看状态
git status
# 输出:
# On branch main
# Untracked files:
# config.local
# 将文件添加到.gitignore
echo "config.local" >> .gitignore
git add .gitignore
git commit -m "Add config.local to gitignore"
1.3 场景三:修改最后一次提交
问题:你刚提交完,发现提交信息写错了,或者忘记添加某个文件。
修改提交信息:
bash
# 修改最后一次提交的信息
git commit --amend -m "Fix: correct commit message"
# 或打开编辑器修改
git commit --amend
添加遗漏的文件:
bash
# 假设你忘记添加一个文件
echo "/* New styles */" >> css/style.css
# 添加到暂存区
git add css/style.css
# 修改最后一次提交(不改变提交信息)
git commit --amend --no-edit
# 或修改提交信息
git commit --amend -m "Add dark mode styles and fix header layout"
警告 :--amend
会改变提交的SHA-1哈希值,如果已经推送到远程仓库,不要使用!
1.4 场景四:撤销提交(保留修改)
问题:你提交了代码,但发现还需要继续修改。
bash
# 撤销最后一次提交,保留修改在暂存区
git reset --soft HEAD~1
# 查看状态
git status
# 输出:
# On branch main
# Changes to be committed:
# modified: css/style.css
# modified: js/main.js
# 继续修改文件
# ...
# 重新提交
git commit -m "Improved dark mode with better color scheme"
撤销多个提交:
bash
# 撤销最近3次提交,保留修改在工作区
git reset HEAD~3
# 撤销到特定提交
git reset abc123
1.5 场景五:完全撤销提交(危险!)
问题:你想完全放弃最近的提交和所有修改。
bash
# 完全撤销最后一次提交(删除修改)
git reset --hard HEAD~1
# ⚠️ 警告:这会永久删除工作区和暂存区的修改!
# 撤销到特定提交
git reset --hard abc123
安全建议 :在使用--hard
前,先确认没有重要的未提交修改,或者先创建备份分支:
bash
# 创建备份分支
git branch backup-before-reset
# 然后再执行reset
git reset --hard HEAD~1
# 如果后悔了,可以恢复
git reset --hard backup-before-reset
1.6 场景六:撤销已推送的提交(安全方式)
问题:你推送了错误的代码到GitHub,需要撤销。
使用revert(推荐):
bash
# 创建一个新的提交来撤销指定提交
git revert HEAD
# Git会打开编辑器让你编辑提交信息
# 默认信息是:Revert "原提交信息"
# 推送到远程
git push
# 撤销多个提交
git revert HEAD~2..HEAD
# 撤销特定提交
git revert abc123
revert vs. reset:
特性 | revert | reset |
---|---|---|
修改历史 | 否(创建新提交) | 是(移动分支指针) |
安全性 | 安全 | 危险(可能丢失数据) |
适用场景 | 已推送的提交 | 本地未推送的提交 |
团队协作 | 友好 | 不友好 |
1.7 场景七:找回丢失的提交(reflog)
问题 :你用reset --hard
删除了提交,现在后悔了。
bash
# 查看reflog(记录所有HEAD的移动)
git reflog
# 输出:
# 7g8h9i0 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
# 8h9i0j1 HEAD@{1}: commit: Add new feature
# 7g8h9i0 HEAD@{2}: commit: Fix bug
# 6f7g8h9 HEAD@{3}: commit: Update styles
# 找到丢失的提交(8h9i0j1)
# 恢复到该提交
git reset --hard 8h9i0j1
# 或使用reflog引用
git reset --hard HEAD@{1}
# 验证
git log --oneline
reflog的过期时间:
bash
# 查看reflog配置
git config --get gc.reflogExpire
# 默认:90 days
git config --get gc.reflogExpireUnreachable
# 默认:30 days
# 修改过期时间
git config gc.reflogExpire "180 days"
1.8 场景八:临时保存工作进度(stash)
问题:你正在开发功能,突然需要切换分支修复紧急bug,但当前修改还不想提交。
bash
# 保存当前工作进度
git stash
# 或添加说明
git stash save "WIP: implementing search feature"
# 查看stash列表
git stash list
# 输出:
# stash@{0}: WIP on main: 7g8h9i0 Add new feature
# stash@{1}: WIP on feature-branch: 6f7g8h9 Update styles
# 切换分支修复bug
git switch hotfix-branch
# ... 修复bug并提交 ...
# 切换回原分支
git switch main
# 恢复工作进度
git stash pop
# 或应用但不删除stash
git stash apply
# 应用特定的stash
git stash apply stash@{1}
# 删除stash
git stash drop stash@{0}
# 清空所有stash
git stash clear
stash包含未跟踪的文件:
bash
# 包含未跟踪的文件
git stash -u
# 或
git stash --include-untracked
# 包含被忽略的文件
git stash -a
# 或
git stash --all
从stash创建分支:
bash
# 从stash创建新分支
git stash branch new-feature-branch
# 这会:
# 1. 创建新分支
# 2. 检出到新分支
# 3. 应用stash
# 4. 删除stash
第二章:历史改写:Rebase与修改提交
2.1 场景九:整理提交历史
问题:你在开发过程中创建了很多小提交,想在合并到main前整理一下。
bash
# 查看提交历史
git log --oneline
# 输出:
# 9i0j1k2 (HEAD -> feature/search) Fix typo
# 8h9i0j1 Update search logic
# 7g8h9i0 Add search function
# 6f7g8h9 WIP: search feature
# 5e6f7g8 (main) Add dark mode
# 使用交互式rebase整理最近4次提交
git rebase -i HEAD~4
# 或指定基准提交
git rebase -i 5e6f7g8
交互式rebase编辑器:
sql
pick 6f7g8h9 WIP: search feature
pick 7g8h9i0 Add search function
pick 8h9i0j1 Update search logic
pick 9i0j1k2 Fix typo
# Rebase 5e6f7g8..9i0j1k2 onto 5e6f7g8 (4 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# d, drop <commit> = remove commit
整理策略:
sql
pick 6f7g8h9 WIP: search feature
squash 7g8h9i0 Add search function
squash 8h9i0j1 Update search logic
fixup 9i0j1k2 Fix typo
# squash:合并提交,保留提交信息
# fixup:合并提交,丢弃提交信息
保存并关闭编辑器,Git会打开新的编辑器让你编辑合并后的提交信息:
sql
# This is a combination of 4 commits.
# This is the 1st commit message:
Add search feature
Implemented full-text search functionality with the following features:
- Search input in header
- Real-time search as user types
- Highlight matching text in results
- Filter articles by search term
# This is the commit message #2:
# Add search function
# ...
编辑为简洁的提交信息:
sql
feat: add full-text search feature
Implemented real-time search functionality:
- Search input in header
- Highlight matching text
- Filter articles by search term
完成rebase:
bash
# 查看结果
git log --oneline
# 输出:
# 0j1k2l3 (HEAD -> feature/search) feat: add full-text search feature
# 5e6f7g8 (main) Add dark mode
2.2 场景十:修改历史提交信息
问题:你发现几次提交前的提交信息有错别字。
bash
# 交互式rebase
git rebase -i HEAD~5
# 将要修改的提交标记为reword
reword abc123 Add dark mdoe feature
pick def456 Fix bug
pick ghi789 Update README
# 保存后,Git会依次打开编辑器让你修改每个reword的提交信息
2.3 场景十一:拆分一个提交
问题:你在一个提交中做了太多事情,想拆分成多个提交。
bash
# 交互式rebase
git rebase -i HEAD~3
# 将要拆分的提交标记为edit
edit abc123 Add multiple features
pick def456 Fix bug
# Git会停在abc123提交
# 撤销该提交,但保留修改
git reset HEAD~1
# 查看修改
git status
# 分别提交不同的修改
git add css/style.css
git commit -m "feat: add dark mode styles"
git add js/search.js
git commit -m "feat: add search functionality"
git add README.md
git commit -m "docs: update README with new features"
# 继续rebase
git rebase --continue
2.4 场景十二:在错误的分支上开发了
问题:你在main分支上开发了新功能,但应该在feature分支上。
方法一:使用cherry-pick
bash
# 当前在main分支,有2个新提交
git log --oneline -3
# 输出:
# 2l3m4n5 (HEAD -> main) Add feature part 2
# 1k2l3m4 Add feature part 1
# 0j1k2l3 (origin/main) Previous commit
# 创建feature分支(指向当前提交)
git branch feature/new-feature
# 重置main分支到远程状态
git reset --hard origin/main
# 切换到feature分支
git switch feature/new-feature
# 提交已经在feature分支上了
方法二:如果已经推送了
bash
# 创建feature分支
git checkout -b feature/new-feature
# 推送feature分支
git push -u origin feature/new-feature
# 切换回main
git switch main
# 重置main(本地)
git reset --hard origin/main
# 如果main已经推送,需要revert
git revert HEAD~2..HEAD
git push
2.5 Rebase vs. Merge:深入对比
Merge的优缺点:
✅ 优点:
- 保留完整的历史记录
- 安全,不修改已有提交
- 清晰显示分支合并点
❌ 缺点:
- 提交历史复杂,有很多合并提交
- 难以追踪单一功能的开发历史
Rebase的优缺点:
✅ 优点:
- 线性的提交历史,易于理解
- 干净整洁的历史记录
- 易于追踪功能开发
❌ 缺点:
- 修改历史,可能导致冲突
- 不适合已推送的公共分支
- 需要更多Git知识
黄金法则:
永远不要rebase已经推送到公共仓库的提交!
推荐使用场景:
bash
# ✅ 好的使用:整理本地未推送的提交
git rebase -i HEAD~5
# ✅ 好的使用:更新feature分支
git switch feature-branch
git rebase main
# ❌ 坏的使用:rebase已推送的main分支
git switch main
git rebase other-branch
git push -f # 强制推送会影响其他人!
# ✅ 好的使用:在推送前整理提交
git rebase -i origin/feature-branch
git push
第三章:Git高级特性
3.1 Git Hooks:自动化工作流
Git Hooks是在特定Git事件发生时自动执行的脚本。
客户端Hooks:
bash
# 查看hooks目录
ls -la .git/hooks/
# 输出:
# pre-commit.sample
# pre-push.sample
# commit-msg.sample
# ...
实战:创建pre-commit钩子检查代码质量
bash
# 创建pre-commit钩子
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
echo "Running pre-commit checks..."
# 检查是否有console.log
if git diff --cached --name-only | grep -E '\.(js|jsx|ts|tsx)$' | xargs grep -n "console.log" 2>/dev/null; then
echo "❌ Error: Found console.log in staged files!"
echo "Please remove console.log before committing."
exit 1
fi
# 检查是否有TODO标记
if git diff --cached | grep -E "^\+.*TODO" 2>/dev/null; then
echo "⚠️ Warning: Found TODO comments in changes."
echo "Consider creating an issue for these TODOs."
fi
# 运行代码格式检查(如果有prettier)
if command -v prettier &> /dev/null; then
echo "Running Prettier..."
git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(js|jsx|css|md)$' | xargs prettier --check
if [ $? -ne 0 ]; then
echo "❌ Error: Code formatting issues found!"
echo "Run: prettier --write <file>"
exit 1
fi
fi
echo "✅ All pre-commit checks passed!"
exit 0
EOF
# 添加执行权限
chmod +x .git/hooks/pre-commit
测试钩子:
bash
# 添加一个console.log
echo "console.log('test');" >> js/main.js
# 尝试提交
git add js/main.js
git commit -m "Test commit"
# 输出:
# Running pre-commit checks...
# js/main.js:123:console.log('test');
# ❌ Error: Found console.log in staged files!
# Please remove console.log before committing.
绕过钩子(紧急情况):
bash
# 使用--no-verify跳过钩子
git commit --no-verify -m "Emergency fix"
共享钩子(团队使用):
bash
# 在项目中创建hooks目录
mkdir -p scripts/git-hooks
# 将钩子脚本放入该目录
cp .git/hooks/pre-commit scripts/git-hooks/
# 创建安装脚本
cat > scripts/install-hooks.sh << 'EOF'
#!/bin/bash
ln -sf ../../scripts/git-hooks/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
echo "Git hooks installed successfully!"
EOF
chmod +x scripts/install-hooks.sh
# 在README中说明
echo "
## 开发环境设置
安装Git hooks:
\`\`\`bash
./scripts/install-hooks.sh
\`\`\`
" >> README.md
# 或使用Git 2.9+的配置
git config core.hooksPath scripts/git-hooks
3.2 Git Worktree:多个工作目录
场景:你正在开发新功能,突然需要修复紧急bug,但不想stash或提交未完成的代码。
bash
# 查看当前worktree
git worktree list
# 输出:
# /path/to/my-blog 7g8h9i0 [main]
# 为hotfix创建新的工作目录
git worktree add ../my-blog-hotfix hotfix/critical-bug
# 输出:
# Preparing worktree (new branch 'hotfix/critical-bug')
# HEAD is now at 7g8h9i0 Add dark mode
# 切换到hotfix目录
cd ../my-blog-hotfix
# 修复bug
# ...
# 提交并推送
git add .
git commit -m "hotfix: fix critical security issue"
git push -u origin hotfix/critical-bug
# 回到原工作目录
cd ../my-blog
# 继续开发新功能
# ...
# 完成后删除hotfix工作目录
git worktree remove ../my-blog-hotfix
# 或手动删除目录后清理
rm -rf ../my-blog-hotfix
git worktree prune
Worktree的优势:
- 不需要stash或提交未完成的工作
- 可以同时在多个分支上工作
- 每个worktree有独立的工作区和暂存区
- 共享同一个.git目录(节省空间)
3.3 Git LFS:大文件管理
场景:你的博客需要存储高清图片、视频等大文件。
安装Git LFS:
bash
# Ubuntu/Debian
sudo apt install git-lfs
# macOS
brew install git-lfs
# 初始化
git lfs install
# 输出:
# Updated git hooks.
# Git LFS initialized.
跟踪大文件:
bash
# 跟踪所有图片文件
git lfs track "*.jpg"
git lfs track "*.png"
git lfs track "*.gif"
# 跟踪视频文件
git lfs track "*.mp4"
git lfs track "*.mov"
# 跟踪特定目录
git lfs track "images/**"
# 查看跟踪的文件
git lfs track
# 输出:
# Listing tracked patterns
# *.jpg (.gitattributes)
# *.png (.gitattributes)
# images/** (.gitattributes)
# .gitattributes会被自动创建
cat .gitattributes
# 输出:
# *.jpg filter=lfs diff=lfs merge=lfs -text
# *.png filter=lfs diff=lfs merge=lfs -text
使用LFS:
bash
# 添加大文件(与普通文件相同)
cp ~/large-image.jpg images/
git add images/large-image.jpg
git commit -m "Add hero image"
# 推送(LFS文件会上传到LFS服务器)
git push
# 查看LFS文件
git lfs ls-files
# 输出:
# 4d7a214b2f * images/large-image.jpg
克隆包含LFS的仓库:
bash
# 自动下载LFS文件
git clone git@github.com:your-username/my-blog.git
# 或只克隆指针,不下载LFS文件
GIT_LFS_SKIP_SMUDGE=1 git clone git@github.com:your-username/my-blog.git
# 之后按需下载
git lfs pull
3.4 子模块(Submodules):管理依赖项目
场景:你的博客使用了一个共享的UI组件库。
添加子模块:
bash
# 添加子模块
git submodule add git@github.com:your-username/ui-components.git lib/ui-components
# 查看.gitmodules文件
cat .gitmodules
# 输出:
# [submodule "lib/ui-components"]
# path = lib/ui-components
# url = git@github.com:your-username/ui-components.git
# 提交子模块
git add .gitmodules lib/ui-components
git commit -m "Add UI components submodule"
git push
克隆包含子模块的项目:
bash
# 方法一:克隆时初始化子模块
git clone --recurse-submodules git@github.com:your-username/my-blog.git
# 方法二:克隆后初始化
git clone git@github.com:your-username/my-blog.git
cd my-blog
git submodule init
git submodule update
# 或合并为一条命令
git submodule update --init --recursive
更新子模块:
bash
# 进入子模块目录
cd lib/ui-components
# 拉取最新代码
git pull origin main
# 回到主项目
cd ../..
# 提交子模块的更新
git add lib/ui-components
git commit -m "Update UI components to latest version"
git push
在主项目中更新所有子模块:
bash
# 更新所有子模块到远程最新版本
git submodule update --remote
# 更新并合并
git submodule update --remote --merge
# 更新并变基
git submodule update --remote --rebase
第四章:实战问题解决手册
4.1 问题:如何删除敏感信息?
场景:你不小心提交了包含密码的配置文件。
方法一:使用filter-branch(Git内置)
bash
# 从所有历史中删除文件
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch config/secrets.yml" \
--prune-empty --tag-name-filter cat -- --all
# 强制推送(会重写历史)
git push origin --force --all
git push origin --force --tags
方法二:使用git-filter-repo(推荐)
bash
# 安装git-filter-repo
pip3 install git-filter-repo
# 删除文件
git filter-repo --path config/secrets.yml --invert-paths
# 强制推送
git push origin --force --all
方法三:使用BFG Repo-Cleaner(最快)
bash
# 下载BFG
wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar
# 删除文件
java -jar bfg-1.14.0.jar --delete-files secrets.yml
# 清理
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# 强制推送
git push origin --force --all
预防措施:
bash
# 使用git-secrets检测敏感信息
git clone https://github.com/awslabs/git-secrets.git
cd git-secrets
make install
# 在项目中安装
cd /path/to/my-blog
git secrets --install
# 添加检测规则
git secrets --register-aws
git secrets --add 'password\s*=\s*.+'
git secrets --add 'api[_-]?key\s*=\s*.+'
# 扫描历史
git secrets --scan-history
4.2 问题:如何找回删除的分支?
场景:你不小心删除了一个重要的分支。
bash
# 查看reflog找到分支最后的提交
git reflog
# 输出:
# 7g8h9i0 HEAD@{0}: checkout: moving from feature-branch to main
# 8h9i0j1 HEAD@{1}: commit: Last commit on feature-branch
# ...
# 重新创建分支
git branch feature-branch 8h9i0j1
# 或
git checkout -b feature-branch 8h9i0j1
4.3 问题:如何合并不相关的历史?
场景:你想合并两个独立创建的仓库。
bash
# 添加另一个仓库为远程仓库
git remote add other-repo git@github.com:your-username/other-repo.git
# 拉取
git fetch other-repo
# 合并(允许不相关的历史)
git merge other-repo/main --allow-unrelated-histories
# 解决冲突(如果有)
# ...
# 提交合并
git commit
4.4 问题:如何查看文件的修改历史?
场景:你想知道某个文件是何时、被谁、为什么修改的。
bash
# 查看文件的提交历史
git log --follow -- css/style.css
# 查看每次提交的具体修改
git log -p -- css/style.css
# 查看文件的每一行是谁修改的
git blame css/style.css
# 查看特定行范围
git blame -L 10,20 css/style.css
# 忽略空白变化
git blame -w css/style.css
# 查看文件在特定提交时的内容
git show abc123:css/style.css
4.5 问题:如何搜索代码历史?
场景:你想找到某个函数是何时被删除的。
bash
# 在所有提交中搜索
git log -S "function searchArticles" --source --all
# 使用正则表达式搜索
git log -G "function.*search" --source --all
# 搜索提交信息
git log --grep="search feature"
# 组合搜索
git log --grep="search" --author="Your Name" --since="2 weeks ago"
4.6 问题:如何比较两个分支?
场景:你想知道feature分支相比main分支有哪些变化。
bash
# 查看不同的提交
git log main..feature-branch
# 查看文件差异
git diff main...feature-branch
# 查看具体文件的差异
git diff main...feature-branch -- css/style.css
# 查看统计信息
git diff --stat main...feature-branch
# 查看哪些文件被修改
git diff --name-only main...feature-branch
# 查看哪些文件被修改(包括状态)
git diff --name-status main...feature-branch
4.7 问题:如何处理大仓库?
场景:仓库太大,克隆很慢。
浅克隆:
bash
# 只克隆最近的历史
git clone --depth 1 git@github.com:your-username/my-blog.git
# 克隆最近10次提交
git clone --depth 10 git@github.com:your-username/my-blog.git
# 之后获取完整历史
git fetch --unshallow
单分支克隆:
bash
# 只克隆main分支
git clone -b main --single-branch git@github.com:your-username/my-blog.git
稀疏检出:
bash
# 克隆但不检出文件
git clone --no-checkout git@github.com:your-username/my-blog.git
cd my-blog
# 启用稀疏检出
git sparse-checkout init --cone
# 只检出特定目录
git sparse-checkout set css js
# 检出文件
git checkout main
4.8 问题:如何处理换行符问题?
场景:Windows和Linux/macOS的换行符不同,导致diff混乱。
bash
# 查看当前配置
git config core.autocrlf
# Windows用户(检出时转换为CRLF,提交时转换为LF)
git config --global core.autocrlf true
# macOS/Linux用户(检出时不转换,提交时转换为LF)
git config --global core.autocrlf input
# 不自动转换(不推荐)
git config --global core.autocrlf false
# 使用.gitattributes统一管理
cat > .gitattributes << 'EOF'
# 自动检测文本文件并规范化
* text=auto
# 明确指定文本文件使用LF
*.js text eol=lf
*.css text eol=lf
*.html text eol=lf
*.md text eol=lf
# 明确指定Windows脚本使用CRLF
*.bat text eol=crlf
*.ps1 text eol=crlf
# 明确指定二进制文件
*.png binary
*.jpg binary
EOF
git add .gitattributes
git commit -m "Add .gitattributes for line ending normalization"
4.9 问题:如何处理文件权限变化?
场景:在Windows和Linux之间切换导致文件权限变化。
bash
# 忽略文件权限变化
git config core.fileMode false
# 只在当前仓库生效
git config --local core.fileMode false
# 查看配置
git config core.fileMode
4.10 问题:如何加速Git操作?
bash
# 启用文件系统缓存(Windows)
git config --global core.fscache true
# 启用并行索引预加载
git config --global core.preloadindex true
# 增加压缩级别(0-9,默认1)
git config --global core.compression 9
# 启用多线程pack
git config --global pack.threads 0 # 0表示自动检测CPU核心数
# 定期维护仓库
git gc --aggressive --prune=now
# 查看仓库大小
git count-objects -vH
第五章:性能优化与最佳实践
5.1 提交规范(Conventional Commits)
格式:
xml
<type>(<scope>): <subject>
<body>
<footer>
类型(type):
feat
: 新功能fix
: 修复bugdocs
: 文档更新style
: 代码格式(不影响功能)refactor
: 重构perf
: 性能优化test
: 测试chore
: 构建过程或辅助工具的变动ci
: CI配置文件和脚本的变动
示例:
bash
git commit -m "feat(search): add full-text search functionality
Implemented real-time search with the following features:
- Search input in header
- Highlight matching text in results
- Filter articles by search term
Closes #123"
git commit -m "fix(comments): prevent XSS in comment submission
Added HTML escaping to prevent XSS attacks in user-submitted comments.
BREAKING CHANGE: Comments API now requires authentication"
git commit -m "docs: update README with installation instructions"
git commit -m "perf(images): optimize image loading with lazy loading"
5.2 .gitignore最佳实践
通用模板:
bash
cat > .gitignore << 'EOF'
# ===== 操作系统 =====
# macOS
.DS_Store
.AppleDouble
.LSOverride
._*
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
# Linux
*~
.directory
# ===== 编辑器 =====
# VS Code
.vscode/
*.code-workspace
# JetBrains IDEs
.idea/
*.iml
# Vim
*.swp
*.swo
*~
# Sublime Text
*.sublime-project
*.sublime-workspace
# ===== 依赖 =====
node_modules/
vendor/
bower_components/
# ===== 构建输出 =====
dist/
build/
out/
*.min.js
*.min.css
# ===== 日志 =====
*.log
logs/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# ===== 临时文件 =====
*.tmp
*.temp
*.cache
# ===== 环境配置 =====
.env
.env.local
.env.*.local
config.local.*
# ===== 数据库 =====
*.sqlite
*.db
# ===== 备份文件 =====
*.bak
*.backup
*.old
# ===== 压缩文件 =====
*.zip
*.tar.gz
*.rar
# ===== 项目特定 =====
# 根据项目需要添加
EOF
5.3 Git别名配置
常用别名:
bash
# 基本别名
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
# 高级别名
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual 'log --oneline --graph --decorate --all'
git config --global alias.amend 'commit --amend --no-edit'
git config --global alias.undo 'reset --soft HEAD~1'
# 美化的日志
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 查看所有别名
git config --get-regexp alias
使用别名:
bash
# 使用别名
git co main
git br -a
git ci -m "Update styles"
git st
git lg
5.4 团队协作最佳实践
1. 分支命名规范:
bash
feature/功能名称 # 新功能
bugfix/问题描述 # bug修复
hotfix/紧急修复 # 紧急修复
release/版本号 # 发布分支
experiment/实验名称 # 实验性功能
2. PR模板:
bash
# 创建PR模板
mkdir -p .github
cat > .github/pull_request_template.md << 'EOF'
## 变更说明
<!-- 简要描述这个PR做了什么 -->
## 变更类型
- [ ] 新功能
- [ ] Bug修复
- [ ] 文档更新
- [ ] 代码重构
- [ ] 性能优化
- [ ] 其他(请说明)
## 测试
- [ ] 已添加单元测试
- [ ] 已进行手动测试
- [ ] 已在多个浏览器测试
## 截图
<!-- 如果有UI变化,请添加截图 -->
## 相关Issue
<!-- 关闭的Issue:Closes #123 -->
## 检查清单
- [ ] 代码遵循项目规范
- [ ] 已更新相关文档
- [ ] 没有引入新的警告
- [ ] 已进行自我代码审查
EOF
git add .github/pull_request_template.md
git commit -m "Add PR template"
git push
3. Issue模板:
bash
# Bug报告模板
cat > .github/ISSUE_TEMPLATE/bug_report.md << 'EOF'
---
name: Bug报告
about: 报告一个bug帮助我们改进
title: '[BUG] '
labels: bug
assignees: ''
---
**Bug描述**
简要描述bug是什么。
**复现步骤**
1. 访问 '...'
2. 点击 '....'
3. 滚动到 '....'
4. 看到错误
**预期行为**
描述你期望发生什么。
**实际行为**
描述实际发生了什么。
**截图**
如果适用,添加截图帮助解释问题。
**环境信息:**
- OS: [e.g. macOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**附加信息**
添加任何其他相关信息。
EOF
# 功能请求模板
cat > .github/ISSUE_TEMPLATE/feature_request.md << 'EOF'
---
name: 功能请求
about: 建议一个新功能
title: '[FEATURE] '
labels: enhancement
assignees: ''
---
**功能描述**
简要描述你想要的功能。
**使用场景**
描述这个功能的使用场景。
**替代方案**
描述你考虑过的替代方案。
**附加信息**
添加任何其他相关信息或截图。
EOF
git add .github/ISSUE_TEMPLATE/
git commit -m "Add issue templates"
git push
5.5 CI/CD集成:GitHub Actions
自动部署到GitHub Pages:
bash
# 创建GitHub Actions工作流
mkdir -p .github/workflows
cat > .github/workflows/deploy.yml << 'EOF'
name: Deploy to GitHub Pages
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: |
if [ -f package.json ]; then
npm ci
fi
- name: Build
run: |
if [ -f package.json ]; then
npm run build
fi
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./
publish_branch: gh-pages
EOF
git add .github/workflows/deploy.yml
git commit -m "Add GitHub Actions workflow for deployment"
git push
代码质量检查:
bash
cat > .github/workflows/quality.yml << 'EOF'
name: Code Quality
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Run Prettier
run: npm run format:check
- name: Run Tests
run: npm test
EOF
git add .github/workflows/quality.yml
git commit -m "Add code quality workflow"
git push
系列总结
恭喜你完成了《Git完全指南》三部曲的学习!让我们回顾整个系列:
上篇:从零开始的GitHub之旅
- Git的历史和设计哲学
- 安装配置和环境准备
- 四大对象模型和存储机制
- 创建博客项目并推送到GitHub
中篇:GitHub团队协作实战
- 分支的本质和操作
- Pull Request工作流
- 冲突解决实战
- 团队协作模式
下篇:Git高级技巧与问题解决
- 撤销与恢复(reset、revert、reflog、stash)
- 历史改写(rebase、修改提交)
- 高级特性(Hooks、Worktree、LFS、Submodules)
- 实战问题解决手册
- 性能优化和最佳实践
核心收获:
- 理解Git的本质:内容寻址文件系统,快照而非差异
- 掌握核心工作流:工作区 → 暂存区 → 本地仓库 → 远程仓库
- 熟练使用分支:创建、合并、变基、解决冲突
- 团队协作能力:Pull Request、代码审查、工作流选择
- 问题解决技巧:历史修改、数据恢复、性能优化
- 自动化能力:Hooks、CI/CD、质量检查
继续学习:
- 深入Git内部:阅读Pro Git书籍的"Git Internals"章节
- 学习高级工作流:研究大型开源项目的Git使用方式
- 掌握Git服务器:搭建自己的Git服务器(GitLab、Gitea)
- 探索Git扩展:git-flow、git-extras、tig等工具
- 参与开源项目:实践Fork工作流,提交PR到开源项目
最后的建议:
- 多实践:Git是一个需要大量实践的工具
- 不要害怕犯错:Git有很多安全网(reflog、stash、分支)
- 养成好习惯:频繁提交、写清晰的提交信息、定期推送
- 持续学习:Git功能丰富,保持学习和探索的态度
- 帮助他人:分享你的Git知识,帮助团队成员
感谢你完成这段Git学习之旅!希望这份指南能帮助你成为Git专家,在版本控制的世界中游刃有余!