创建仓库
git init — 在当前目录初始化
在一个已有的项目目录中运行 git init,Git 会在其中创建一个 .git 子目录,这就是仓库的"大脑"。
# 在当前目录初始化 Git 仓库
git init
# 指定目录名初始化(会创建该目录)
git init my-project
# 初始化后的状态
git status
.git/ 目录包含 Git 仓库的所有数据,永远不要手动删除或修改它,除非你知道自己在做什么。主要结构:
.git/
├── HEAD # 指向当前分支
├── config # 仓库级配置
├── objects/ # 所有对象(blob/tree/commit/tag)
├── refs/
│ ├── heads/ # 本地分支引用
│ └── tags/ # 标签引用
└── index # 暂存区(二进制文件)
git clone — 克隆远程仓库
克隆会下载远程仓库的全部历史和文件,自动设置 origin 远程并建立追踪关系。
# 克隆到同名目录
git clone https://github.com/user/repo.git
# 克隆到指定目录名
git clone https://github.com/user/repo.git my-local-name
# 使用 SSH(需提前配置 SSH 密钥)
git clone git@github.com:user/repo.git
# 只克隆最近 1 次提交(浅克隆,加快速度)
git clone --depth 1 https://github.com/user/repo.git
查看仓库状态
git status 是你最常运行的命令之一,它显示工作区和暂存区的当前状态。
git status
典型输出及含义:
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed: # 暂存区中,等待提交的变更
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: src/app.js
Changes not staged for commit: # 工作区中,已修改但未 add 的文件
(use "git add <file>..." to update what will be committed)
modified: src/utils.js
Untracked files: # 从未被 Git 追踪过的新文件
(use "git add <file>..." to include in what will be committed)
notes.txt
-
Untracked
新文件,Git 从未追踪过它。需要
git add才会被 Git 管理。 -
Modified
已追踪的文件,内容发生了变化,但还没有
git add到暂存区。 -
Staged
已经
git add到暂存区,等待下次git commit时被包含进去。
# 简洁格式(适合日常使用)
git status -s
# M = 已修改(M在左=暂存区,M在右=工作区)
# ?? = Untracked(未追踪)
# A = 新文件已暂存
添加到暂存区
基本用法
# 添加指定文件
git add index.html
# 添加整个目录
git add src/
# 添加当前目录下所有变更(包括新文件、修改、删除)
git add .
# 添加所有 .js 文件
git add *.js
git add -p — 交互式选择部分变更
这是一个强大但少被初学者知道的功能。它允许你逐块(hunk by hunk)选择要暂存的变更,而不必把整个文件的所有变更一起提交。
git add -p src/app.js
交互时可用的选项:
| 按键 | 含义 |
|---|---|
y | 暂存这个 hunk(代码块) |
n | 跳过这个 hunk |
s | 将当前 hunk 再拆分为更小的块 |
e | 手动编辑这个 hunk |
q | 退出,不再处理剩余 hunk |
为什么要用 -p?假设你在修复一个 bug 的同时顺手重构了几行代码,-p 让你把 bug 修复和重构分成两个独立的提交,保持提交历史的清晰。
提交变更
基本提交
# 提交暂存区的内容,打开编辑器输入提交信息
git commit
# 直接在命令行指定提交信息(最常用)
git commit -m "feat: add user login page"
# 跳过 git add,直接提交所有已追踪文件的变更(不包含新文件)
git commit -am "fix: correct calculation logic"
# 修改最后一次提交(仅在未 push 前使用!)
git commit --amend -m "fix: correct calculation logic (amended)"
好的提交信息规范
一个好的提交信息应遵循50/72 规则:主题行不超过 50 字符,正文每行不超过 72 字符,主题行与正文之间用空行分隔。
feat: add OAuth2 login with Google
- Implement Google OAuth2 callback endpoint
- Store access token in encrypted session cookie
- Add redirect to original URL after successful login
Closes #142
更进一步,推荐遵循 Conventional Commits 规范,提交信息格式为 type(scope): description:
| 类型 | 含义 | 示例 |
|---|---|---|
feat | 新功能 | feat: add dark mode toggle |
fix | Bug 修复 | fix: resolve null pointer in parser |
docs | 文档更新 | docs: update API reference |
refactor | 重构(不改变功能) | refactor: extract auth middleware |
test | 添加或修改测试 | test: add unit tests for validator |
chore | 杂务(构建、依赖) | chore: upgrade webpack to v5 |
查看提交历史
# 基础日志,显示完整哈希、作者、日期、提交信息
git log
# 每行一条提交(最常用!)
git log --oneline
# 图形化显示所有分支(强烈推荐!)
git log --oneline --graph --all
# 显示每次提交的文件差异
git log -p
# 只看最近 3 次提交
git log -3
# 按作者过滤
git log --author="张三"
# 按时间过滤
git log --since="2024-01-01" --until="2024-06-30"
# 搜索提交信息中包含关键词的提交
git log --grep="login"
# 自定义格式输出
git log --pretty=format:"%h %an %ar %s"
--oneline --graph --all 的典型输出:
* a3f2c1d (HEAD -> main, origin/main) feat: add profile page
* 8e4b9a2 fix: correct email validation
| * c7d1e3f (feature/dark-mode) feat: implement dark mode
| * 5a2b8c1 style: add CSS variables for theme
|/
* 2f9d4e5 refactor: extract auth module
* 1b3c7a9 init: initial commit
查看文件差异
# 工作区 vs 暂存区(未 add 的变更)
git diff
# 暂存区 vs 最新提交(已 add、未 commit 的变更)
git diff --staged
# 工作区 vs 最新提交(所有未提交的变更)
git diff HEAD
# 两次提交之间的差异
git diff HEAD~1 HEAD
# 两个分支之间的差异
git diff main..feature-login
# 只显示变更了哪些文件,不显示具体内容
git diff --name-only
配置 .gitignore
.gitignore 文件告诉 Git 哪些文件不需要追踪。应放在仓库根目录并提交到版本控制。
语法规则
| 模式 | 含义 | 示例 |
|---|---|---|
* | 匹配任意字符(不含路径分隔符) | *.log 忽略所有 log 文件 |
** | 匹配任意层级的目录 | **/temp 忽略任意位置的 temp 目录 |
? | 匹配单个字符 | file?.txt |
/ 结尾 | 只匹配目录 | build/ 只忽略目录 |
! 开头 | 取消忽略(例外) | !important.log 不忽略此文件 |
# 开头 | 注释 | # 这是注释 |
典型 .gitignore 示例
# 依赖目录
node_modules/
vendor/
# 构建输出
dist/
build/
*.min.js
# 环境变量(绝对不要提交!)
.env
.env.local
.env.*.local
# 系统文件
.DS_Store
Thumbs.db
# 日志文件
*.log
npm-debug.log*
# IDE 配置
.idea/
.vscode/
*.swp
已追踪的文件不会被 .gitignore 影响!如果一个文件已经被提交过,之后再把它加入 .gitignore 并不会让 Git 停止追踪它。需要先运行 git rm --cached filename 将其从追踪列表中移除(不删除本地文件),再提交。
查看特定提交
# 查看某次提交的详细内容(变更了什么)
git show a3f2c1d
# 查看最新提交
git show HEAD
# 只显示某次提交修改的文件列表
git show a3f2c1d --name-only
# 查看某次提交中某个文件的内容
git show a3f2c1d:src/app.js