Skip to content

基本操作

本章要点

  • git init 创建仓库、git clone 克隆仓库
  • 日常三连:git statusgit addgit commit
  • 查看历史:git log 的各种姿势
  • 查看差异:git diff
  • 移动与删除文件:git mvgit rm
  • 写好提交信息的方法论

获取仓库的两种方式

方式一:初始化新仓库

bash
$ mkdir my-project && cd my-project
$ git init
# Initialized empty Git repository in /path/to/my-project/.git/
  • 会在当前目录创建隐藏的 .git/ 目录,这就是版本库本体。
  • ⚠️ 不要在已有的 Git 仓库内部再执行 git init(会创建嵌套仓库)。

方式二:克隆已有仓库

bash
$ git clone https://github.com/user/repo.git
$ git clone https://github.com/user/repo.git my-folder   # 自定义目录名
  • 克隆 = 完整复制远程仓库的全部历史到本地。
  • 会自动配置好名为 origin 的远程仓库别名。

查看状态:git status

bash
$ git status            # 详细状态
$ git status -s         # 简短状态(short),一行一个文件

-s 输出格式(两列分别表示暂存区工作区的状态):

text
??  untracked.md        # ?? = 未跟踪(Untracked)
 A  added.md            #  A = 已暂存(Staged/Added)
 M  modified.md         #  M = 已修改未暂存(Modified)
MM  both.md             # 左 M 已暂存的修改,右 M 工作区又有新修改
 D  deleted.md          #  D = 已删除但未暂存
R   renamed.md          # R = 重命名

💡 状态字母速记:?? 从未见过,A 待提交,M 有改动,D 删除了。

暂存与提交

git add:把改动放入暂存区

bash
$ git add file.txt          # 暂存单个文件
$ git add src/              # 暂存整个目录
$ git add .                 # 暂存当前目录下所有改动(⚠️ 注意别把密钥文件加进去)
$ git add -A                # 暂存所有改动(含删除),等价于 git add .(部分旧版本差异)
$ git add -p                # 交互式分块暂存(强大!后面详述)
$ git add --update          # 只暂存已跟踪文件的修改(不包含新增未跟踪文件)

git commit:固化快照

bash
$ git commit -m "提交说明"              # 最常用
$ git commit                            # 打开编辑器写详细说明(适合长提交信息)
$ git commit -am "说明"                 # add + commit 一步完成(⚠️ 只对已跟踪文件生效,新增文件仍需 git add)
$ git commit --amend -m "新说明"        # 修改上一次提交(见 6.6 节)

提交信息规范(Commit Message)

好的提交信息让人一眼看懂历史,团队必须统一规范

text
<type>(<scope>): <subject>        # 第一行:标题,≤ 50 字符

<body>                            # 空一行后写正文:为什么改、怎么改

常见 type(约定式提交 Conventional Commits):

type含义
feat新功能
fix修复 bug
docs文档改动
style格式(空格、分号等,不影响逻辑)
refactor重构(不改功能)
test测试相关
chore构建/工具/依赖等杂项
perf性能优化
revert回滚某次提交

示例:

text
feat(login): 增加短信验证码登录

- 新增验证码发送接口 /api/sms/code
- 登录页支持手机号 + 验证码方式
- 验证码有效期 5 分钟,60 秒内不可重复发送

💡 为什么需要规范?git log 和 Code Review 都依赖提交信息传达意图;自动生成 changelog 也需要(如 semantic-release)。

查看历史:git log

bash
$ git log                     # 完整历史
$ git log --oneline           # 每行一条:缩写哈希 + 标题(最常用)
$ git log --oneline -10       # 只看最近 10 条
$ git log --graph             # 带 ASCII 分支图(配合 --oneline --all --decorate 效果最佳)
$ git log -p                  # 同时显示每次提交的完整 diff
$ git log --stat              # 显示每次提交改了哪些文件、增减行数
$ git log --author="张三"     # 按作者过滤
$ git log --since="2 weeks ago"   # 按时间过滤
$ git log --grep="fix"        # 按提交信息关键字过滤
$ git log -- <>           # 只查看某个文件的历史(注意 -- 后的空格)
$ git log -S "关键字"         # 找出"新增或删除该字符串"的提交(pickaxe 搜索)
$ git log --oneline --follow -- <>   # 跟踪文件重命名历史

输出示例:

text
$ git log --oneline --graph
* 8f4a2c9 (HEAD -> main, origin/main) fix(login): 修复验证码 60 秒倒计时不刷新
* 3b1e7d0 feat(login): 增加短信验证码登录
* c9a21f4 docs: 更新 README
* 5d0e1a3 feat: 项目初始化

💡 HEAD 表示"当前所在的位置"(当前分支的最新提交)。HEAD -> main 表示当前在 main 分支上。

查看某次提交的详细信息

bash
$ git show 8f4a2c9           # 查看该提交的改动
$ git show 8f4a2c9 --stat    # 只看统计信息
$ git show HEAD              # 查看最近一次提交

查看差异:git diff

bash
$ git diff                          # 工作区 vs 暂存区(我改了什么还没 add)
$ git diff --staged                 # 暂存区 vs 版本库(我将要提交什么)
$ git diff HEAD                     # 工作区 vs 版本库(全部未提交的改动)
$ git diff <提交1> <提交2>          # 两个提交之间的差异
$ git diff <分支A> <分支B>          # 两个分支之间的差异
$ git diff --stat                   # 只显示统计
$ git diff -- <>                # 只看某个文件

⚠️ 新手最容易搞混:git diff(不带参数)只看工作区里"还没 add"的改动,看不到已经 add 的内容;想看已暂存的内容要用 git diff --staged

彩色 diff 示例

diff
$ git diff
diff --git a/README.md b/README.md
index 3b18e51..d8f3a20 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # 项目说明
-这是旧内容
+这是新内容
+新增了一行
  • - 开头:被删除的行(红色)
  • + 开头:新增的行(绿色)
  • @@ -1,3 +1,4 @@:变更位置(旧文件第 1 行起 3 行,新文件第 1 行起 4 行)

查看待提交内容的便捷命令

bash
$ git diff --cached        # 等价于 git diff --staged

移动与删除文件

重命名/移动

bash
$ git mv old.txt new.txt   # 重命名(同时暂存这个改动)
$ git mv src/a.js lib/a.js # 移动目录

删除

bash
$ git rm file.txt          # 删除文件并暂存删除操作(工作区和版本库同步删除)
$ git rm --cached file.txt # 只从版本库移除跟踪,保留本地文件(常用语把误提交的密钥移出跟踪)
$ git rm -r dir/           # 递归删除目录

💡 不记得 git mv/git rm 也没关系:直接 mv/rm 后执行 git add -A,Git 会自动识别为重命名/删除。Git 本质上是靠内容相似度识别重命名的。

一次完整的工作循环演示

bash
$ cd my-project
$ git status -s                # ??  hello.md
$ echo "Hello Git" > hello.md
$ git status -s                # ??  hello.md(新文件默认未跟踪)
$ git add hello.md
$ git status -s                # A   hello.md(已暂存)
$ git commit -m "docs: 新增 hello.md"
# [main 4d2f1a3] docs: 新增 hello.md
#  1 file changed, 1 insertion(+)

$ echo "Hello Git World" > hello.md   # 修改内容
$ git status -s                #  M  hello.md(已修改未暂存)
$ git diff                     # 查看修改内容
$ git add hello.md && git commit -m "docs: 更新 hello.md"
$ git log --oneline            # 查看历史

交互式暂存:git add -p

git add -p 让你**分块(hunk)**决定哪些改动进暂存区,适合"一个文件里混着两个功能"的场景:

text
$ git add -p file.txt
@@ -1,7 +1,10 @@ ...          # 第一个改动块
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?   # 按键选择

常用按键:

按键含义
y暂存这一块
n不暂存这一块
s把这一块再拆小
e手动编辑这一块(精细控制)
q退出

💡 用 git add -p 可以做到"一个提交只包含一个逻辑改动",让历史像书一样整洁。