Git 命令行完全教程
目标:从零开始,用纯命令行完成 VS Code 可视化 Git 的所有常用操作。
目录
1. 初始化仓库
1.1 全新项目
# 创建项目目录并进入
mkdir my-project
cd my-project
# 初始化 git 仓库
git init
# 查看仓库状态
git status
执行后会在当前目录生成 .git 隐藏目录,这就是 git 的”数据库”。
1.2 配置用户信息(首次使用必做)
git config --global user.name "你的名字"
git config --global user.email "your@email.com"
# 查看配置
git config --list
1.3 忽略不需要跟踪的文件
创建 .gitignore 文件:
cat > .gitignore << 'EOF'
# 编译产物
*.o
*.class
*.pyc
__pycache__/
# 依赖
node_modules/
vendor/
# 系统文件
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
# 敏感文件
.env
*.key
*.pem
EOF
1.4 克隆已有仓库
# 通过 SSH(推荐)
git clone git@github.com:user/repo.git
# 通过 HTTPS
git clone https://github.com/user/repo.git
# 克隆到指定目录
git clone git@github.com:user/repo.git my-folder
2. 提交代码
2.1 基本工作流
# 第一步:查看当前状态(看看改了哪些文件)
git status
# 第二步:添加文件到暂存区
git add 文件名 # 添加单个文件
git add file1.txt file2.py # 添加多个文件
git add src/ # 添加整个目录
git add . # 添加当前目录所有改动
# 第三步:提交到本地仓库
git commit -m "feat: 添加登录功能"
# 一步到位:添加所有已跟踪文件的改动并提交
git commit -am "fix: 修复分页bug"
# 注意:-a 只对已跟踪的文件生效,新文件仍需先 git add
2.2 提交信息规范
# 推荐格式:类型: 简短描述
git commit -m "feat: 新增用户管理模块"
git commit -m "fix: 修复登录超时问题"
git commit -m "docs: 更新API文档"
git commit -m "refactor: 重构数据库连接层"
git commit -m "perf: 优化列表查询性能"
2.3 修改最近一次提交
# 漏了文件,想追加到上一次提交
git add 漏掉的文件
git commit --amend --no-edit
# 想改上次的提交信息
git commit --amend -m "新的提交信息"
2.4 实操演示
# 模拟一次完整提交
echo "print('hello')" > main.py
git status # 看到 main.py 是未跟踪的(红色)
git add main.py # 加入暂存区
git status # 看到 main.py 变绿色
git commit -m "feat: 添加main.py入口" # 提交!
echo "print('world')" >> main.py
git status # 看到 main.py 被修改
git diff # 看看具体改了什么
git commit -am "feat: main.py增加输出" # 一步到位提交
git log --oneline # 查看提交历史
3. 查看提交记录
这是 VS Code 可视化最核心的替代功能。
3.1 基本查看
# 完整日志(按j/k上下翻页,按q退出)
git log
# 简洁模式(一行一条)
git log --oneline
# 最近 N 条
git log -5
git log --oneline -10
3.2 图形化分支图(最接近 VS Code 的视图)
# 最推荐:带分支图的简洁日志
git log --oneline --graph --all
# 更详细的分支图
git log --graph --all --decorate --format='%C(auto)%h %C(blue)%an %C(green)%ad %C(reset)%s' --date=short
# 建议设置别名,方便反复使用
git config --global alias.tree "log --oneline --graph --all"
git tree # 以后直接打这个就行
3.3 查看每次提交的具体改动
# 查看某次提交改了哪些内容
git show <commit-hash>
# 只看某个文件在两次提交间的变化
git log -p 文件名
# 查看每一行的最后修改者和修改时间
git blame 文件名
git blame -L 10,20 文件名 # 只看第10到20行
3.4 搜索提交记录
# 按提交信息关键词搜索
git log --oneline --grep="登录"
# 按代码改动的关键词搜索
git log --oneline -S "functionName"
# 按作者搜索
git log --oneline --author="张三"
# 按时间范围
git log --oneline --since="2025-01-01" --until="2025-12-31"
# 查看某个文件的所有提交历史
git log --oneline -- 文件名
3.5 查看改了什么(类似 VS Code 的对比视图)
# 工作区 vs 暂存区(还没 git add 的改动)
git diff
# 暂存区 vs 最新提交(已经 git add 了但没 commit)
git diff --cached
# 或
git diff --staged
# 工作区 vs 最新提交(所有未提交的改动)
git diff HEAD
# 比较两个提交
git diff commit1 commit2
git diff abc123..def456
# 比较两个分支
git diff main..feature-login
# 只看某个文件的差异
git diff -- 文件名
4. Tag 标签管理
Tag 就是给某个 commit 打上版本号标记,比如 v1.0.0,方便以后快速定位。
4.1 创建 Tag
# 轻量标签(不推荐,信息太少)
git tag v1.0.0
# 附注标签(推荐,带说明信息)
git tag -a v1.0.0 -m "正式发布 1.0.0 版本"
# 给之前的某个提交打标签
git tag -a v0.9.0 -m "测试版" <commit-hash>
# 查看某个标签的详情
git show v1.0.0
4.2 查看 Tag
# 列出所有标签
git tag
# 按模式过滤
git tag -l "v1.*"
# 按时间排序查看
git tag --sort=-creatordate | head -10
git tag --sort=-v:refname # 按版本号排序
4.3 推送 Tag 到远程
# 推送单个标签
git push origin v1.0.0
# 推送所有标签
git push origin --tags
# 默认 git push 不会推送标签,需要显式指定
4.4 删除 Tag
# 删除本地标签
git tag -d v1.0.0
# 删除远程标签
git push origin --delete v1.0.0
# 或
git push origin :refs/tags/v1.0.0
4.5 切换到某个 Tag 的代码
# 只读查看
git checkout v1.0.0
# 基于 Tag 创建新分支(推荐方式,可以在上面改代码)
git checkout -b hotfix-from-v1 v1.0.0
5. Worktree 多分支并行开发
Worktree 让你在同一个仓库里同时检出多个分支到不同目录,互不干扰。
典型场景:
- 正在
feature-A分支开发,突然要修main分支的紧急 bug - 不用 stash 当前工作,直接开个新 worktree 修 bug
5.1 创建 Worktree
# 语法
git worktree add <目录路径> <分支名>
# 示例:在隔壁目录检出 main 分支修 bug
git worktree add ../my-project-hotfix main
# 基于某个提交创建新分支并检出
git worktree add -b feature-payment ../my-project-payment main
5.2 查看所有 Worktree
git worktree list
# 输出示例:
# /home/user/my-project abc1234 [main]
# /home/user/my-project-hotfix def5678 [main]
5.3 删除 Worktree
# 到那个 worktree 目录下正常删除文件后
git worktree remove ../my-project-hotfix
# 或先清理,再删除
git worktree prune
rm -rf ../my-project-hotfix
5.4 完整实战:用 Worktree 修紧急 Bug
cd /home/user/my-project # 当前在 main 分支开发功能
git worktree list # 看看有哪些 worktree
# 开新 worktree 修 bug
git worktree add ../my-project-hotfix main
# 进新目录修 bug
cd ../my-project-hotfix
# ... 修改代码 ...
git commit -am "hotfix: 修复支付回调空指针"
git push
# 回到原目录继续开发
cd /home/user/my-project
# 新目录和原目录完全独立,各干各的
# 修完后清理 worktree
git worktree remove ../my-project-hotfix
5.5 Worktree 中的合并操作
Worktree 本质上是共享同一个 .git 仓库的不同工作目录,所以合并命令和普通方式完全一样。关键在于搞清楚”你在哪个目录、要合并谁”。
场景A:在 Worktree 里开发完,合并回主分支
# 假设目录结构:
# /home/user/my-project → main 分支
# /home/user/my-project-feature → feature-login 分支(worktree)
# 在 feature worktree 里开发并提交
cd /home/user/my-project-feature
# ... 开发 ...
git add .
git commit -m "feat: 登录功能完成"
# 然后回到主目录,把 feature 分支合并进来
cd /home/user/my-project
git merge feature-login
# 或者
git merge --no-ff feature-login -m "merge: 合并登录功能"
场景B:主分支有新提交,同步到 Worktree
# main 分支有人提交了新代码(不管是在哪个 worktree 提交的)
# 在 feature worktree 里把最新 main 合并进来
cd /home/user/my-project-feature # 进入 feature worktree
git merge main # 把 main 的最新代码合并到当前分支
# 如果有冲突,在当前目录正常解决即可
# ... 解决冲突 ...
git add .
git commit -m "merge: 同步 main 最新代码"
场景C:一个 Worktree 一个任务,互不阻塞
# Terminal 1:在 feature 目录开发新功能
cd /home/user/my-project-feature
git checkout feature-login
# ... 正常开发、提交 ...
# Terminal 2:在 hotfix 目录修紧急 bug
cd /home/user/my-project-hotfix
git checkout hotfix-urgent
# ... 修 bug、提交 ...
# Terminal 3:在 main 目录做发布
cd /home/user/my-project
git merge feature-login # 合并功能
git merge hotfix-urgent # 合并热修复
git tag -a v2.0.0 -m "发布" # 打版本
场景D:Worktree 间交叉合并(不推荐,但可行)
# 直接在 feature worktree 目录执行 merge
cd /home/user/my-project-feature
git merge hotfix-urgent # 此时会报错!
# 错误原因:hotfix-urgent 分支被另一个 worktree 检出了
# Git 不允许同一个分支同时被两个 worktree 检出
# 解决方案:先让 hotfix worktree 切换到别的分支
cd /home/user/my-project-hotfix
git checkout main # 或直接 git switch main
# 现在 hotfix-urgent 没人占用了
cd /home/user/my-project-feature
git merge hotfix-urgent # 可以了
5.6 Worktree + Merge 完整实战:并行开发两个功能,最后一起合并
# 初始状态:只有 main 分支
cd /home/user/my-project
git branch
# * main
# 创建两个 worktree,分别开发两个独立功能
git worktree add -b feature-payment ../my-project-payment main
git worktree add -b feature-report ../my-project-report main
# 开发 payment 功能
cd ../my-project-payment
echo "payment module" > payment.py
git add payment.py
git commit -m "feat: 支付模块"
# 开发 report 功能(payment 还在开发中,互不干扰!)
cd ../my-project-report
echo "report module" > report.py
git add report.py
git commit -m "feat: 报表模块"
# payment 继续开发
cd ../my-project-payment
echo "alipay support" >> payment.py
git commit -am "feat: 支持支付宝"
# 回到主目录,逐个合并
cd /home/user/my-project
# 先合并 payment
git merge --no-ff feature-payment -m "merge: 合并支付模块"
# 再合并 report(可能需要解决冲突)
git merge --no-ff feature-report -m "merge: 合并报表模块"
# 发布
git tag -a v1.0.0 -m "第一个正式版"
git archive -o ../myproject-v1.0.0.zip v1.0.0
# 清理 worktree
git worktree remove ../my-project-payment
git worktree remove ../my-project-report
# 查看最终的分支图
git log --oneline --graph --all
5.7 Worktree 注意事项
# 1. 同一个分支不能被两个 worktree 同时检出
git worktree list
# 确保没有分支名重复出现在不同目录
# 2. worktree 里删除分支前,先切换到其他分支
git switch main
git branch -d feature-old
# 3. 主仓库删了分支,worktree 引用会失效,记得 prune
git worktree prune
# 4. Worktree 共享 .git,所以 git log / git stash 等操作数据互通
# 在一个 worktree 里 git stash,在另一个 worktree 里 git stash list 能看到
6. 打包特定版本为 zip
git archive可以直接导出任意版本为 zip/tar.gz,不包含.git目录,适合交付。
6.1 打包当前版本
# 当前 HEAD 版本打包为 zip
git archive -o ../output.zip HEAD
# 打包为 tar.gz
git archive -o ../output.tar.gz HEAD
6.2 打包指定版本
# 按 Tag 打包
git archive -o ../v1.0.0.zip v1.0.0
# 按分支打包
git archive -o ../develop.zip develop
# 按 commit hash 打包
git archive -o ../snapshot.zip abc1234
# 只打包某个子目录
git archive -o ../src.zip HEAD src/
# 排除某些文件
git archive -o ../no-test.zip HEAD -- ':!test'
6.3 实用脚本:一键打包发布
#!/bin/bash
# 保存为 release.sh
VERSION=${1:-"v1.0.0"}
git archive -o "../myproject-${VERSION}.zip" "$VERSION"
echo "已生成: myproject-${VERSION}.zip"
ls -lh "../myproject-${VERSION}.zip"
用法:
chmod +x release.sh
./release.sh v2.0.0
6.4 打包带 .git 的完整仓库(迁移到另一台机器继续开发)
git archive不含.git,如果你要把整个仓库(含提交历史、分支、标签)搬到内网服务器继续开发,用下面三种方式。
方式一:直接打包整个目录(最简单)
# 打包为 zip(含 .git)
zip -r ../myproject-full.zip .
# 打包为 tar.gz(推荐,压缩比更高且保留权限)
tar -czf ../myproject-full.tar.gz .
# 到目标机器解压
unzip myproject-full.zip -d /path/to/new-project/
# 或
tar -xzf myproject-full.tar.gz -C /path/to/new-project/
方式二:git bundle 打包(最 Git 原生,推荐)
git bundle 把整个仓库(所有分支、标签、历史)打包成一个文件,无需解压,直接当远程仓库用。
# 打包:导出所有分支和标签
git bundle create ../myproject.bundle --all
# 查看 bundle 里有什么
git bundle list-heads ../myproject.bundle
# 输出示例:
# abc1234 refs/heads/main
# def5678 refs/heads/develop
# 1112222 refs/tags/v1.0.0
# 也可以只打包某个分支及其历史
git bundle create ../myproject.bundle main develop
# 也可以打包某个范围(比如只导出 v1.0.0 之后的内容)
git bundle create ../myproject.bundle v1.0.0..main
到目标机器恢复:
# 在目标机器上,像克隆远程仓库一样从 bundle 文件恢复
git clone /path/to/myproject.bundle /path/to/new-project/
# 克隆完就是一个完整的 git 仓库,历史、分支、标签全在
cd /path/to/new-project/
git log --oneline --graph --all # 一切都在
git branch -a # 所有分支都在
git tag # 所有标签都在
方式三:U 盘 / SCP 拷贝(物理隔离环境)
# 源机器:直接复制整个项目目录(.git 自然在里面)
scp -r /home/user/my-project user@目标IP:/home/user/
# 或者先 tar 再传
tar -czf myproject.tar.gz my-project/
scp myproject.tar.gz user@目标IP:/home/user/
# 到目标机器解压即用
ssh user@目标IP
cd /home/user
tar -xzf myproject.tar.gz
cd my-project
git log --oneline # 历史完整保留
三种方式对比
| 方式 | 包含 .git | 尊重 .gitignore | 文件大小 | 适用场景 |
|---|---|---|---|---|
git archive |
不含 | 是(只导出已跟踪文件) | 最小 | 交付给客户/生产部署 |
git bundle |
完整历史 | 是(只打包 Git 对象) | 比 archive 大 | 跨机器迁移开发(推荐) |
zip -r / tar |
完整历史 | 否(无差别打包整个目录) | 最大,含 node_modules 等 | 快速完整备份 |
7. 版本回退
7.1 先理解三个区域
工作区 暂存区 本地仓库 远程仓库
(Working) → (Stage) → (Local) → (Remote)
| | | |
git add git commit git push
| | | |
← git restore ← git restore ← git reset ← git revert
--staged ← git revert
7.2 回退方法对比
| 命令 | 效果 | 适合场景 |
|---|---|---|
git restore 文件 |
撤销工作区改动 | 还没 add |
git restore --staged 文件 |
移出暂存区 | 已经 add 但没 commit |
git reset --soft HEAD~1 |
撤销 commit,改动保留在暂存区 | commit 错了,想重写 |
git reset --mixed HEAD~1 |
撤销 commit 和 add,改动保留在工作区 | commit 错了,从头来 |
git reset --hard HEAD~1 |
彻底丢弃最近一次提交的所有改动 | 确定不要了 |
git revert HEAD |
创建一次新提交来”反向”抵消 | 已推送到远程 |
7.3 实战:各种回退场景
# 场景1:改乱了工作区,想恢复到上次 commit 的状态
git restore 文件名
git restore . # 恢复所有文件
# 场景2:git add 错了,想取消暂存
git restore --staged 文件名
# 场景3:刚 commit 了,但发现漏改东西
git reset --soft HEAD~1 # 回到 commit 前,改动还在暂存区
# ... 补改 ...
git commit -m "修正后的提交"
# 场景4:这次 commit 完全不想要了,回到干净状态
git reset --hard HEAD~1
# 场景5:回退到指定版本(回退 N 个 commit)
git reset --hard HEAD~3 # 回退 3 次提交
# 场景6:回退到指定 commit hash
git log --oneline # 先找到目标 commit
git reset --hard abc1234 # 回退到该 commit
# 警告:abc1234 之后的提交会全部丢失!
# 场景7:已经 push 到远程了,用 revert(安全)
git revert HEAD # 创建新 commit 撤销最近一次
git revert abc1234 # 撤销指定 commit
git push origin main
# 场景8:回退后又后悔了
git reflog # 查看所有 HEAD 的移动记录
git reset --hard HEAD@{1} # 回到回退前的状态
7.4 reset vs revert 关键区别
# reset:真删了,不留痕(像时光倒流)
git reset --hard HEAD~1
# revert:创建反向 commit,历史可追溯(像打补丁)
git revert HEAD
简单规则:已 push 到远程,用 revert;还在本地,用 reset。
8. 查看特定记录的代码
8.1 查看某次提交的完整改动(等效 GitHub 的 commit 详情页)
git show输出内容就是 GitHub 上点开某个 commit 看到的信息:作者、时间、提交信息、文件 diff,完全对应。
基础用法
git show abc1234 # 看完整 diff(等效 GitHub commit 详情)
git show abc1234 --stat # 只看改了哪些文件(等效 GitHub "Files changed" 概览)
git show abc1234 --stat -p # 文件统计 + diff 一次看完
git show abc1234 -- 文件名 # 只看某个文件的改动
git show HEAD~3 # 看 3 次提交之前的改动
注意:
git show <hash>展示的是这一次提交的改动。而git diff <hash>/git difftool <hash>展示的是该提交到当前状态之间所有的累积差异,完全不一样。要用 difftool 只看一次提交,必须加^!:
git show abc1234 # ✅ 只看这一次提交
git difftool --tool=icdiff abc1234 # ❌ 从那次提交到现在的所有差异
git difftool --tool=icdiff abc1234^! # ✅ 只看这一次提交
git difftool --tool=icdiff abc1234~..abc1234 # 等价写法
彩色单词级对比(更像 GitHub 的高亮效果)
# GitHub 默认是单词级高亮,命令行加 --color-words 达到同样效果
git show abc1234 --color-words
# 设置别名,以后直接用
git config --global alias.showw 'show --color-words'
git showw abc1234
连续查看最近 N 次提交各自的 diff
# 最近 5 次提交,每次都有完整 diff(等效 GitHub Commits 列表逐个点开看)
git log -p -5
# 最近 5 次,只显示文件概览不展开 diff
git log --stat -5
# 最近 5 次 + 单词级高亮
git log -p -5 --color-words
左右分屏对比(等效 GitHub 的 Split 视图)
GitHub 默认是左旧右新的分屏 diff。终端下有几种方式实现同样效果。
方案一:vimdiff(零依赖,内置)
vimdiff 是 Vim 自带的分屏对比工具,所有 Linux 都内置:
# 查看某次提交的左右分屏对比
git difftool --tool=vimdiff abc1234
# 对比两个提交
git difftool --tool=vimdiff abc1234..def5678
# 对比某个文件的两版本
git difftool --tool=vimdiff abc1234 -- src/main.py
# 设为默认 difftool,以后直接 git difftool
git config --global diff.tool vimdiff
git config --global difftool.prompt false # 不弹出确认提示
git difftool abc1234
vimdiff 打开后:
- 左边是旧版本,右边是新版本
Ctrl+W+ 左右箭头 切换窗口:qa退出所有窗口,进入下一个文件- 红色高亮 = 差异行
方案二:delta(最像 GitHub,强烈推荐)
delta 是一个 Rust 写的 diff 美化工具,支持左右分屏,效果跟 GitHub 几乎一样:
# 安装(CentOS 可能需要先装 cargo 或下载二进制)
# 方式A:用 cargo
cargo install git-delta
# 方式B:直接从 GitHub Release 下载二进制
# wget https://github.com/dandavison/delta/releases/latest/download/delta-*.tar.gz
# 配置 git 使用 delta
git config --global core.pager delta
git config --global interactive.diffFilter 'delta --color-only'
git config --global delta.side-by-side true # 开启左右分屏!
git config --global delta.line-numbers true # 显示行号
git config --global delta.navigate true # 用 n/N 跳转到下一个/上一个差异块
# 配置完后,git diff / git show 自动变成左右分屏
git show abc1234
git diff
git log -p
效果演示:
src/main.py
──────────────────────────────────────────────────────────────────
34 def login(user, pwd): │ 34 def login(user, pwd, method='password'):
35 return api.login() │ 35 return api.authenticate(user, pwd, method)
│ 36
│ 37 def logout():
│ 38 session.clear()
方案三:icdiff(轻量 Python 方案)
如果装不了 Rust,用 Python 的 icdiff。注意 icdiff 不是 Git 内置工具,需要先安装再注册:
# 1. 安装 icdiff
pip install icdiff
# 2. 注册为 Git 自定义 difftool(关键一步!否则报 Unknown merge tool)
git config --global difftool.icdiff.cmd 'icdiff --line-numbers --no-bold "$LOCAL" "$REMOTE"'
git config --global difftool.prompt false
# 3. 使用
git difftool --tool=icdiff abc1234
# 设为默认
git config --global diff.tool icdiff
git difftool abc1234
三种方案对比
| 方案 | 安装 | 效果 | 适用场景 |
|---|---|---|---|
| vimdiff | 零依赖,系统自带 | 功能全但颜值一般 | 临时用、不想装东西 |
| delta | 需下载二进制 | 最像 GitHub,真分屏 | 日常使用(推荐) |
| icdiff | pip install | 轻量分屏 | Python 环境已有 |
### 8.2 查看某个文件在某个版本时的内容
```bash
# 查看文件在特定 commit 时的内容(不修改工作区)
git show abc1234:路径/文件名
# 示例
git show abc1234:src/main.py
git show v1.0.0:README.md
git show HEAD~5:config/db.conf
8.3 比较文件在不同版本间的差异
# 同一个文件在两个版本间的差异
git diff abc1234..def5678 -- 文件名
# 文件在两次提交间的变化
git diff HEAD~3..HEAD -- src/main.py
# 文件名在两处不一样怎么办,看下一节
8.4 临时切换到某个版本(仅查看,不改代码)
# 切换到某个 commit(detached HEAD 状态)
git checkout abc1234
# ... 看完代码 ...
git switch main # 或 git checkout main 回到正常分支
# 切换到某个 tag
git checkout v1.0.0
8.5 实用对比脚本
# 查看一个文件从一开始到现在的所有版本
git log --oneline --follow -- 文件名
# --follow 会追踪文件重命名
# 查看某次提交前后10行上下文
git show abc1234 -U10
9. Merge 合并
9.1 基本合并流程
# 场景:把 feature-login 分支的代码合并到 main
# Step 1: 切换到目标分支
git checkout main
# 或
git switch main
# Step 2: 确保目标分支是最新的
git pull origin main
# Step 3: 合并
git merge feature-login
# Step 4: (如果没问题)推送到远程
git push origin main
9.2 合并策略
# 默认合并(可能产生 merge commit)
git merge feature-login
# Fast-Forward 合并:如果 main 没有新 commit,直接把 main 指针移过去
# 等同于 --ff,这是默认行为
git merge --ff feature-login
# 禁止 Fast-Forward:强制生成一个 merge commit
# 好处:分支历史清晰可见
git merge --no-ff feature-login -m "merge: 合并登录功能"
# Squash 合并:把 feature 分支的所有 commit 压成一个 commit
# 好处:main 分支历史干净
git merge --squash feature-login
git commit -m "feat: 登录功能(含10次提交)"
9.3 三种合并方式对比
--ff (Fast-Forward)
main: A---B
feature: \---C---D
结果: A---B---C---D (线性,看不出分支的存在)
--no-ff
main: A---B
feature: \---C---D
结果: A---B-------M (M 是 merge commit,保留分支结构)
\---C---D
--squash
main: A---B
feature: \---C---D
结果: A---B---S (S 包含了 C+D 的全部改动,只有一次 commit)
9.4 合并前先预演
# 合并前看看有没有冲突,不真正执行
git merge --no-commit --no-ff feature-login
# 检查完没问题的话:
git commit -m "merge: 合并 feature-login"
# 如果不想合并了:
git merge --abort
9.5 中断合并
# 合并到一半发现有冲突不想解决了
git merge --abort
# 回到合并前状态,干干净净
10. 解决合并冲突
当两个分支改了同一个文件的同一行,git 无法自动判断用哪个版本,就会产生冲突。
10.1 冲突的样子
<<<<<<< HEAD # 这是当前分支(main)的内容
def login(user, pwd):
return api.login(user, pwd)
======= # 这是要合并进来的分支(feature)的内容
def login(user, pwd, method='password'):
return api.authenticate(user, pwd, method)
>>>>>>> feature-login
10.2 解决冲突三步法
# Step 1: 找到冲突
git merge feature-login
# 输出:CONFLICT (content): Merge conflict in src/auth.py
git status # 看到 both modified: src/auth.py
# Step 2: 手动编辑文件,删除冲突标记
# 打开 src/auth.py,看到 <<<<<<< ======= >>>>>>> 标记
# 决定保留哪个版本(或两个版本融合),删掉标记
# Step 3: 标记已解决并提交
git add src/auth.py
git commit -m "merge: 合并 feature-login(已解决冲突)"
10.3 冲突解决示例
# 原始文件有冲突:
# <<<<<<< HEAD
# def login(user, pwd):
# =======
# def login(user, pwd, method='password'):
# >>>>>>> feature-login
# 手动编辑,保留你的选择,比如:
def login(user, pwd, method='password'):
return api.authenticate(user, pwd, method)
# 保存后:
git add src/auth.py
# 所有冲突都解决后:
git commit
# 默认会打开编辑器让你确认 merge 信息,保存退出即可
10.4 冲突时的常用操作
# 查看哪些文件有冲突
git diff --name-only --diff-filter=U
# 全部接受当前分支(ours)的版本
git checkout --ours 文件名
git add 文件名
# 全部接受合并分支(theirs)的版本
git checkout --theirs 文件名
git add 文件名
# 使用可视化 diff 工具(如果服务器装了)
git mergetool
# 放弃合并
git merge --abort
# 查看冲突的具体差异
git diff 文件名
10.5 查看合并历史
# 查看哪些分支已合并、未合并
git branch --merged
git branch --no-merged
# 查看合并日志
git log --merges --oneline
# 查看某次合并引入了哪些改动
git log --first-parent main
附:常用命令速查表
最常用(每天都会用)
git status # 查看状态
git log --oneline --graph --all # 查看历史图
git diff # 看工作区改动
git add . && git commit -m "..." # 提交
git push origin main # 推送到远程
git pull # 拉取远程更新
实用别名配置(建议加到 ~/.bashrc 或 ~/.gitconfig)
# 简洁状态
git config --global alias.st status
# 上次提交的改动
git config --global alias.last 'log -1 --stat'
# 漂亮的分支图
git config --global alias.tree 'log --oneline --graph --all --decorate'
# 漂亮日志
git config --global alias.lg "log --graph --format='%C(auto)%h %C(blue)%an %C(green)%ad %C(reset)%s' --date=short"
# 搜索提交信息
git config --global alias.find 'log --oneline --grep'
# 配置完成后:
git st # git status
git last # 查看最近一次提交
git tree # 查看分支图
git lg # 漂亮的提交日志
git find "关键词" # 搜索提交
紧急情况速查
# 改坏了,回到上次 commit
git restore .
# 刚 commit 了想反悔
git reset --soft HEAD~1
# 刚 push 了想反悔
git revert HEAD && git push
# 合并乱了想重来
git merge --abort
# 误删了 commit 想找回
git reflog && git reset --hard HEAD@{n}
# 查看某次提交的文件内容
git show abc1234:path/to/file
结语:命令行 vs VS Code 操作对照
| 操作 | VS Code 方式 | 命令行方式 |
|---|---|---|
| 看改了什么 | 左侧文件颜色 | git status + git diff |
| 看提交历史 | GitLens / 时间线 | git log --oneline --graph --all |
| 看单次提交 | 点击 commit 条目 | git show <hash> |
| 提交代码 | Ctrl+Enter | git add + git commit -m "..." |
| 看文件历史 | GitLens blame | git blame 文件名 |
| 分支合并 | 右键菜单 | git merge 分支名 |
| 解决冲突 | 内嵌编辑器 | 手动编辑 → git add → git commit |
| 版本回退 | 右键 revert | git reset / git revert |
| 打标签 | 右键创建 tag | git tag -a v1.0 -m "..." |
| 打包发布 | 手动压缩 | git archive -o v1.0.zip v1.0 |
命令行一开始可能不习惯,但一旦熟练,效率远高于鼠标点击。多练习,两周就能肌肉记忆。
结语
第三百八十五篇博文写完,开心!!!!
今天,也是充满希望的一天。