Git

Git 是目前最广泛使用的分布式版本控制系统。每个克隆都是完整仓库,离线可提交,推送时再同步。


核心概念

工作区(Working Tree)
    ↓ git add
暂存区(Index / Staging Area)
    ↓ git commit
本地仓库(Local Repository)
    ↓ git push
远程仓库(Remote Repository)
对象说明
Blob文件内容快照
Tree目录结构(引用 Blob 和子 Tree)
Commit一次提交(引用 Tree + 父 Commit + 元数据)
Tag指向特定 Commit 的持久引用
Branch指向某 Commit 的可移动指针
HEAD当前所在位置(通常指向当前分支)

安装与全局配置

# 设置用户信息(写入 ~/.gitconfig)
git config --global user.name  "Your Name"
git config --global user.email "you@example.com"
 
# 默认分支名
git config --global init.defaultBranch main
 
# 换行符处理(Windows 提交时转 LF,检出时转 CRLF)
git config --global core.autocrlf true   # Windows
git config --global core.autocrlf input  # macOS/Linux
 
# 默认编辑器
git config --global core.editor "code --wait"   # VS Code
git config --global core.editor "idea --wait"   # [[IDEA]]
 
# 查看所有配置
git config --list --show-origin

基础操作

初始化 / 克隆

# 新建仓库
git init
git init my-project
 
# 克隆远程仓库
git clone https://github.com/user/repo.git
git clone https://github.com/user/repo.git my-dir   # 指定目录名
git clone --depth 1 https://github.com/user/repo.git  # 浅克隆(仅最新快照)

查看状态与差异

git status              # 工作区与暂存区状态
git status -s           # 简短格式
 
git diff                # 工作区 vs 暂存区
git diff --staged       # 暂存区 vs 最新提交
git diff HEAD           # 工作区 vs 最新提交
git diff main..feature  # 两分支差异

暂存与提交

git add file.txt        # 暂存指定文件
git add src/            # 暂存目录
git add -p              # 交互式逐块暂存(patch 模式)
git add .               # 暂存所有改动
 
git commit -m "feat: add login feature"
git commit -am "fix: typo"              # 跳过 add,直接提交已跟踪文件的改动
 
# 修改最后一次提交(未推送才安全)
git commit --amend -m "fix: correct message"
git commit --amend --no-edit            # 追加暂存内容但不改消息

分支管理

# 查看分支
git branch              # 本地分支
git branch -r           # 远程分支
git branch -a           # 所有分支
git branch -v           # 显示最新 commit
 
# 创建与切换
git branch feature/login
git switch feature/login          # 推荐用 switch(Git 2.23+)
git switch -c feature/login       # 创建并切换
git checkout -b feature/login     # 旧语法,等价上面
 
# 删除分支
git branch -d feature/login       # 已合并才能删
git branch -D feature/login       # 强制删除
git push origin --delete feature/login  # 删除远程分支
 
# 重命名分支
git branch -m old-name new-name

合并

# Fast-forward 合并(可线性推进时)
git merge feature/login
 
# 关闭 FF,始终产生 Merge Commit(保留分支历史)
git merge --no-ff feature/login -m "merge: login feature"
 
# 冲突后手动解决,再完成合并
git add conflicted-file.txt
git merge --continue
 
# 放弃本次合并
git merge --abort

Rebase(整理提交历史)

# 将当前分支变基到 main
git rebase main
 
# 交互式整理最近 3 次提交(合并、改序、改消息)
git rebase -i HEAD~3
 
# Rebase 中出现冲突
git add resolved-file.txt
git rebase --continue
git rebase --abort    # 放弃
 
# 推荐:将特性分支变基后再合并入主干(保持线性历史)
git switch feature/login
git rebase main
git switch main
git merge --ff-only feature/login

已推送的提交不要 rebase,会导致他人历史错乱。


远程操作

# 查看远程
git remote -v
git remote add origin https://github.com/user/repo.git
git remote set-url origin git@github.com:user/repo.git  # 改为 SSH
 
# 抓取与拉取
git fetch origin           # 拉取远程元数据,不修改本地工作区
git fetch --prune          # 同时删除已不存在的远程跟踪分支
git pull                   # = fetch + merge
git pull --rebase          # = fetch + rebase(推荐,保持线性)
 
# 推送
git push origin feature/login
git push -u origin feature/login    # 设置上游,以后直接 git push
git push --force-with-lease         # 安全强推(检查远端无新提交)

撤销与回退

# 撤销工作区改动(未暂存)
git restore file.txt              # Git 2.23+
git checkout -- file.txt          # 旧语法
 
# 取消暂存
git restore --staged file.txt
git reset HEAD file.txt           # 旧语法
 
# 回退提交(保留工作区改动)
git reset --soft HEAD~1           # 撤销提交,改动回到暂存区
git reset HEAD~1                  # 撤销提交,改动回到工作区(默认 --mixed)
git reset --hard HEAD~1           # 撤销提交并丢弃改动(危险)
 
# 安全回退(产生新 Commit,不改写历史,适合已推送)
git revert HEAD
git revert abc1234
 
# 找回误删内容(reflog 记录所有 HEAD 变更)
git reflog
git reset --hard HEAD@{3}

Stash(暂时搁置)

git stash                          # 保存工作区和暂存区改动
git stash push -m "wip: login form"  # 附带描述
git stash -u                       # 同时保存未跟踪文件
 
git stash list                     # 查看 stash 列表
git stash pop                      # 弹出最近一条(恢复并删除)
git stash apply stash@{1}          # 应用但不删除
git stash drop stash@{1}           # 删除指定
git stash clear                    # 清空所有

Tag(标签)

# 轻量标签
git tag v1.0.0
 
# 附注标签(推荐,含元数据)
git tag -a v1.0.0 -m "Release 1.0.0"
git tag -a v1.0.0 abc1234 -m "tag specific commit"
 
git tag                    # 列出所有 tag
git show v1.0.0            # 查看 tag 详情
 
git push origin v1.0.0     # 推送指定 tag
git push origin --tags     # 推送所有 tag
git push origin --delete v1.0.0  # 删除远程 tag
git tag -d v1.0.0          # 删除本地 tag

查看历史

git log
git log --oneline --graph --all    # 图形化所有分支历史
git log --oneline -20              # 最近 20 条
git log -p                         # 附带 diff
git log --stat                     # 附带文件变更统计
git log --author="Zhang"           # 过滤作者
git log --since="2024-01-01"       # 时间范围
git log -- path/to/file            # 某文件的历史
 
# 查找提交
git log --grep="login"             # 按提交消息搜索
git log -S "functionName"          # 按代码内容搜索(pickaxe)
 
# 查看某行代码的来源
git blame -L 42,50 src/UserService.java

.gitignore

# 编译产物
target/
*.class
*.jar
 
# IDE 文件
.idea/
*.iml
.vscode/
 
# 环境配置(不提交密钥)
.env
.env.local
application-local.yml
 
# 日志
*.log
logs/
 
# 系统文件
.DS_Store
Thumbs.db

.gitignore 仅对未跟踪文件有效;已跟踪的文件需先 git rm --cached <file> 取消跟踪。


Cherry-pick

将其他分支的某个提交应用到当前分支:

git cherry-pick abc1234             # 应用单个提交
git cherry-pick abc1234..def5678    # 应用一个范围(不含 abc1234)
git cherry-pick -n abc1234          # 应用改动但不自动提交
git cherry-pick --abort

子模块(Submodule)

# 添加子模块
git submodule add https://github.com/user/lib.git libs/lib
 
# 克隆含子模块的仓库
git clone --recurse-submodules https://github.com/user/main.git
 
# 更新子模块
git submodule update --remote --merge

Git Flow 简介

main          生产分支,只接受来自 release/* 和 hotfix/* 的合并
develop       集成分支,特性合并目标
feature/*     特性分支,从 develop 切出,合回 develop
release/*     预发布分支,从 develop 切出,合回 main + develop
hotfix/*      紧急修复,从 main 切出,合回 main + develop

简化版(Trunk-based):所有开发在 main 分支,用功能开关控制上线,适合 CI/CD 高频发布场景。


常用别名配置

git config --global alias.st    status
git config --global alias.co    checkout
git config --global alias.br    branch
git config --global alias.ci    commit
git config --global alias.lg    "log --oneline --graph --all --decorate"
git config --global alias.unstage "restore --staged"
git config --global alias.last  "log -1 HEAD"

SSH 密钥配置

# 生成密钥
ssh-keygen -t ed25519 -C "you@example.com"
 
# 将公钥添加到 GitHub/GitLab
cat ~/.ssh/id_ed25519.pub
 
# 测试连接
ssh -T git@github.com

常见问题

场景命令
提交到了错误分支git cherry-pick 到正确分支,再 reset --hard 回滚
误删分支git reflog 找到 hash,git branch recover <hash>
大文件误提交git filter-repo --path bigfile.bin --invert-paths
合并后想撤销git revert -m 1 <merge-commit-hash>
提交信息写错未推送:git commit --amend;已推送:git revert

相关链接

  • IDEA — IDE 内置 Git 图形操作与冲突解决
  • GitHub Actions — 基于 Git 事件触发 CI/CD 流水线
  • CI集成 — Maven/Gradle 与 CI 的集成配置