Git命令

本文最后更新于:3 年前

引言

本文将系统地介绍 Git 在实际开发中常用的命令及其用法,包括仓库初始化、配置管理、远程操作、分支和标签管理、子模块使用等。对于刚入门的读者,本文能帮助快速了解基础操作;对于已经熟悉 Git 的开发者,也可将其当作一份全面的参考手册或速查表。

创建及配置

git init

作用

git init 用于在当前目录下创建一个新的 Git 仓库。执行后,该目录会被 Git 识别为仓库,并创建 .git 目录来存储版本控制信息。

基本用法

1
2
3
4
5
# 在当前目录创建一个新的 Git 仓库。
git init

# 在指定目录 <directory> 下初始化 Git 仓库。
git init <directory>

参数说明

  • --bare:创建一个裸仓库(不含工作区的 Git 仓库,通常用于远程仓库)。
  • --template=<directory>:指定初始化时使用的模板目录。
  • --separate-git-dir=<git-dir>:指定 .git 目录的存放位置,而非默认的当前目录。
  • --shared[=<permissions>]:用于多人协作时设置共享权限(适用于团队开发的 Git 服务器)。

示例

1
2
3
4
5
# 创建一个裸仓库 myrepo.git,适用于远程仓库。
git init --bare myrepo.git

# 将 Git 版本控制信息存储在 /path/to/git-dir,而不影响当前目录结构。
git init --separate-git-dir=/path/to/git-dir

git config

作用

git config 用于设置 Git 的用户信息、编辑器、合并策略等全局或局部配置。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 设置 Git 的某个配置项。
git config [--global|--local|--system] <key> <value>

# 查看当前所有的 Git 配置项。
git config --list

# 获取某个配置项的值。
git config <key>

# 删除某个配置项。
git config --unset <key>

# 手动编辑配置文件。
git config --edit

参数说明

  • --local:只对当前 Git 仓库生效(默认),配置存储在 .git/config
  • --global:对当前用户所有 Git 仓库生效,配置存储在 ~/.gitconfig
  • --system:对系统所有用户生效,配置存储在 /etc/gitconfig
  • --unset:删除指定的配置项。
  • --edit:直接编辑 Git 配置文件。

常见配置项

  • user.name:设置 Git 用户名。
  • user.email:设置 Git 用户邮箱。
  • core.editor:设置默认编辑器。
  • core.ignorecase:设置是否忽略大小写(Windows 常用)。
  • core.autocrlf:处理换行符(trueWindowsinputLinux/macOS)。
  • alias.<shortcut>:创建 Git 命令别名。
  • diff.tool:设置默认的 diff 工具。
  • merge.tool:设置默认的合并工具。
  • push.default:设置 git push 默认行为(如 simplematching)。
  • credential.helper 设置 Git 认证方式,如 cachestore

示例

1
2
3
4
5
6
7
8
9
10
11
12
# 设置 Git 用户名和邮箱,适用于所有仓库。
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

# 创建 git st 作为 git status 的别名。
git config --global alias.st status

# 将默认编辑器设置为 Vim。
git config --global core.editor "vim"

# 记住 Git 认证信息,避免每次输入密码。
git config --global credential.helper store

远程

git remote

作用

git remote 用于管理本地 Git 仓库和远程仓库的连接信息,例如添加、删除、查看远程仓库。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看当前远程仓库的名称及对应的 URL。
git remote -v

# 添加远程仓库。
git remote add <name> <url>

# 删除远程仓库。
git remote remove <name>

# 重命名远程仓库。
git remote rename <old_name> <new_name>

# 修改远程仓库的 URL。
git remote set-url <name> <new_url>

# 查看远程仓库的详细信息,包括 URL、跟踪的分支等。
git remote show <name>

参数说明

  • -v:显示远程仓库的详细 URL。
  • add <name> <url>:添加远程仓库。
  • remove <name>:删除远程仓库。
  • rename <old> <new>:重命名远程仓库。
  • set-url <name> <url>:修改远程仓库 URL。

示例

1
2
3
4
5
6
7
8
# 添加名为 origin 的远程仓库。
git remote add origin https://github.com/user/repo.git

# 删除名为 origin 的远程仓库。
git remote remove origin

# 将 origin 重命名为 upstream。
git remote rename origin upstream

git clone

作用

git clone 用于克隆远程 Git 仓库到本地。

基本用法

1
2
3
4
5
# 克隆整个远程仓库到本地。
git clone <repository_url>

# 克隆远程仓库到指定目录 <directory>。
git clone <repository_url> <directory>

参数说明

  • <repository_url>:远程仓库 URLHTTP/HTTPS/SSH)。
  • <directory>:指定克隆后的目录名称。
  • --bare:克隆为裸仓库(无工作区)。
  • --mirror:完全镜像克隆,包括远程分支、标签等。
  • --branch <branch>:指定克隆的分支。
  • --depth <depth>:仅克隆指定深度的提交(加速克隆)。
  • --single-branch:仅克隆单个分支(默认 main/master)。

示例

1
2
3
4
5
# 克隆 GitHub 仓库到本地。
git clone https://github.com/user/repo.git

# 仅克隆 dev 分支,并限制提交历史为 1 层。
git clone -b dev --depth 1 https://github.com/user/repo.git

git fetch

作用

git fetch 从远程仓库拉取最新的变更,但不会合并到本地分支。

基本用法

1
2
3
4
5
# 拉取远程仓库 <remote> 的所有更新。
git fetch <remote>

# 仅拉取远程 <branch> 分支的更新。
git fetch <remote> <branch>

参数说明

  • <remote>:远程仓库名称(如 origin)。
  • <branch>:指定拉取的远程分支。
  • --all:拉取所有远程仓库的更新。
  • --prune:删除本地已不存在的远程分支。
  • --depth <depth>:仅拉取指定深度的提交。

示例

1
2
3
4
5
# 从 origin 远程仓库拉取所有更新。
git fetch origin

# 同步远程分支,并删除已被删除的远程分支。
git fetch origin --prune

git pull

作用

git pull 等价于 git fetch + git merge,即拉取远程分支的最新代码并合并到当前分支。

基本用法

1
2
# 从远程仓库 <remote> 拉取 <branch> 分支的更新并合并。
git pull <remote> <branch>

参数说明

  • <remote>:远程仓库名称。
  • <branch>:远程分支名称。
  • --rebase:使用 rebase 而非 merge 合并更新。
  • --depth <depth>:限制拉取的提交历史深度。
  • --no-commit:拉取更新但不自动提交。

示例

1
2
3
4
5
# 从 origin 远程仓库拉取 main 分支的最新代码并合并。
git pull origin main

# 以 rebase 方式拉取并应用远程更新。
git pull --rebase origin main

git push

作用

git push 用于将本地分支的提交推送到远程仓库。

基本用法

1
2
# 将本地 <branch> 推送到远程仓库 <remote>。
git push <remote> <branch>

参数说明

  • <remote>:远程仓库名称。
  • <branch>:要推送的本地分支。
  • --force (-f):强制推送,可能导致远程提交丢失。
  • --delete:删除远程分支。
  • --set-upstream (-u):关联本地分支与远程分支。
  • --all:推送所有分支。
  • --tags:推送所有标签。

示例

1
2
3
4
5
6
7
8
# 将 main 分支推送到远程 origin 仓库。
git push origin main

# 删除远程 feature-branch 分支。
git push origin --delete feature-branch

# 强制推送 main 分支,覆盖远程内容(需谨慎)。
git push -f origin main

状态

git status

作用

git status 用于查看当前 Git 仓库的状态,主要包括:

  • 工作目录中有哪些文件被修改或未跟踪。
  • 哪些文件已添加到暂存区但未提交。
  • 当前所在分支及是否有未提交的更改。

基本用法

1
2
# 显示工作区和暂存区的文件状态。
git status

状态说明

执行 git status 后,可能看到以下几种状态:

  • Untracked files:未跟踪的文件,即 Git 还未管理的文件(新文件)。
  • Changes not staged for commit:已被修改但未添加到暂存区的文件。
  • Changes to be committed:已添加到暂存区但未提交的文件。
  • Your branch is ahead of 'origin/main' by X commits:当前分支比远程分支多 X 个提交,需要 git push
  • nothing to commit, working tree clean:没有任何变更,工作目录是干净的。

参数说明

  • -s--short:显示简短格式的状态信息。
  • -b--branch:显示当前分支信息。
  • --ignored:也显示被 .gitignore 忽略的文件。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 使用简短格式显示状态。
git status -s

# 输出示例:
M file1.txt # 修改但未暂存
A file2.txt # 新增文件已暂存
?? file3.txt # 未跟踪文件



# 显示当前分支信息。
git status -b

# 输出示例:
## main

git diff

作用

git diff 用于比较不同版本的文件,常用于:

  • 比较工作区和暂存区的文件差异。
  • 比较暂存区和最新提交之间的差异。
  • 比较两个分支之间的差异。
  • 比较某次提交与当前分支的差异。

基本用法

1
2
3
4
5
6
7
8
9
10
11
# 显示工作区和暂存区之间的差异。
git diff

# 显示暂存区和上次提交之间的差异。
git diff --cached

# 显示工作区和最新提交之间的差异。
git diff HEAD

# 比较两个分支的差异。
git diff <branch1> <branch2>

参数说明

  • --staged--cached:比较暂存区和上次提交的差异。
  • --name-only:只显示有差异的文件名。
  • --name-status:显示文件的变更类型(新增、删除、修改)。
  • --color:强制启用颜色高亮。
  • --word-diff:逐词显示变更内容,而非逐行。
  • --stat:显示统计信息,如修改行数。
  • -p:显示补丁格式的详细修改内容。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 显示有变更的文件。
git diff --name-only

# 输出示例:
file1.txt
file2.txt



# 显示统计信息。
git diff --stat

# 输出示例:
file1.txt | 10 +++++-----
file2.txt | 2 +-
2 files changed, 7 insertions(+), 5 deletions(-)



# 比较当前版本和上一个版本的差异。
git diff HEAD~1 HEAD

# 比较 main 和 feature-branch 分支的差异。
git diff main feature-branch

日志

git log

作用

git log:用于查看 Git 提交历史,包括提交信息、提交人、时间、哈希值等。

基本用法

1
2
# 显示完整的提交历史。
git log

参数说明

  • -p:显示每次提交的详细代码变更(patch)。
  • --oneline:每条提交仅显示一行(简洁格式)。
  • --graph:以 ASCII 图形方式展示分支结构。
  • --decorate:显示分支、标签等附加信息。
  • --author=<name>:仅显示特定作者的提交。
  • --since=<date> / --until=<date>:显示特定时间范围内的提交。
  • --grep=<pattern>:按提交信息搜索。
  • --stat:显示每次提交修改的文件及变更统计。
  • --abbrev-commit:仅显示短哈希值。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 以图形方式显示所有分支的提交历史。
git log --oneline --graph --decorate --all

# 输出示例:
f1e2c1b (HEAD -> main, origin/main) 修复bug
* d3b4a6d 添加新功能
* a1c2b3d 初始化项目



# 查看 Alice 提交的记录。
git log --author="Alice"

# 查看 2024 年 1 月份的提交记录。
git log --since="2024-01-01" --until="2024-02-01"

git reflog

作用

git reflog 记录所有对分支 HEAD 进行的操作(切换分支、提交、合并、reset 等)。

基本用法

1
2
# 显示所有 HEAD 变更历史。
git reflog

参数说明

  • expire=<time>:设定日志保留时间(如 90 days)。
  • --all:显示所有引用的变更(包括分支、标签等)。
  • --grep=<pattern>:按提交信息搜索。

示例

1
2
3
4
5
6
7
8
9
10
11
git reflog

# 输出示例:
f1e2c1b (HEAD -> main) HEAD@{0}: commit: 修复bug
d3b4a6d HEAD@{1}: checkout: moving from dev to main
a1c2b3d HEAD@{2}: commit: 初始化项目



# 清除超过 30 天的引用日志。
git reflog expire --expire=30.days

git blame

作用

git blame 用于追踪文件每一行的变更历史,显示是谁在什么时候修改了该行。

基本用法

1
2
# 显示文件 <file> 的行级提交信息。
git blame <file>

参数说明

  • -L <start>,<end>:仅显示指定行范围的提交信息。
  • -C:追踪代码块在文件内的移动。
  • --date:显示日期格式(short, relative, iso 等)。
  • -w:忽略空白字符的变更。

示例

1
2
3
4
5
6
7
8
9
10
11
# 显示 file.txt 第 10 行到 20 行的修改记录。
git blame -L 10,20 file.txt

# 输出示例:
f1e2c1b (Alice 2024-08-10) 10 修复错误
d3b4a6d (Bob 2024-08-05) 11 优化代码



# 以 ISO 日期格式显示提交时间。
git blame --date=iso file.txt

git shortlog

作用

git shortlog 按作者分类并统计提交次数。

基本用法

1
2
# 显示简要的提交历史。
git shortlog

参数说明

  • -s:仅显示每个作者的提交数量。
  • -n:按提交数量排序。
  • -e:显示作者的电子邮件。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 按提交数量排序。
git shortlog -s -n

# 输出示例:
120 Alice
85 Bob
45 Charlie



# 显示提交数量和邮箱。
git shortlog -s -e

# 输出示例:
120 Alice <alice@example.com>
85 Bob <bob@example.com>

git show

作用

git show 显示特定提交、分支或对象(标签、文件)的详细信息,包括提交信息、变更的代码等。

基本用法

1
2
3
4
5
# 显示指定提交的详细信息。
git show <commit>

# 显示指定分支的最新提交详情。
git show <branch>

参数说明

  • <commit>:指定提交哈希值。
  • <branch>:指定分支名,查看最近提交详情。
  • --stat:仅显示文件变更统计信息。
  • -p:显示补丁格式(默认)。
  • --name-only:仅显示修改的文件名。
  • --name-status:显示文件变更类型(新增、删除、修改)。

示例

1
2
3
4
5
6
7
8
9
# 显示 f1e2c1b 提交的详细信息,包括提交信息、修改的文件和代码变更。
git show f1e2c1b

# 显示 HEAD 提交的文件变更统计。
git show --stat HEAD

# 输出示例:
file1.txt | 10 +++++-----
file2.txt | 2 +-

分支及操作

git branch

作用

git branch 用于创建、删除、重命名和查看分支。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 列出所有本地分支。
git branch

# 创建新分支 <branch-name>。
git branch <branch-name>

# 删除本地分支 <branch-name>(已合并的分支)。
git branch -d <branch-name>

# 强制删除本地分支(即使未合并)。
git branch -D <branch-name>

# 重命名分支。
git branch -m <old-name> <new-name>

# 列出远程分支。
git branch -r

# 列出所有分支(本地 + 远程)。
git branch -a

参数说明

  • -d:删除本地已合并的分支。
  • -D:强制删除分支(即使未合并)。
  • -m:重命名分支。
  • -r:查看远程分支。
  • -a:查看所有分支(本地+远程)。

示例

1
2
3
4
5
6
7
8
# 创建 feature-xyz 分支。
git branch feature-xyz

# 删除 feature-xyz 分支(仅限已合并)。
git branch -d feature-xyz

# 重命名 old-branch 为 new-branch。
git branch -m old-branch new-branch

git checkout

逐步被 git switch 取代,但仍然适用于恢复文件。

作用

git checkout 主要用于:

  • 切换分支(已被 git switch 替代)。
  • 恢复工作区的文件到某个版本。

基本用法

1
2
3
4
5
6
7
8
9
10
11
# 切换到 <branch> 分支。
git checkout <branch>

# 从 <old_branch> 分支拉取出 <new_branch> 分支。
git checkout <new_branch> <old_branch>

# 创建并切换到 <new-branch>。
git checkout -b <new-branch>

# 丢弃工作区 <file> 的修改,恢复为上次提交的状态。
git checkout -- <file>

参数说明

  • -b:创建并切换到新分支。
  • --:避免歧义,明确指定文件名。

示例

1
2
3
4
5
# 创建并切换到 feature-xyz 分支。
git checkout -b feature-xyz

# 丢弃 file.txt 的修改。
git checkout -- file.txt

git switch

作为 git checkout 的替代,更简洁安全。

基本用法

1
2
3
4
5
6
7
8
9
10
11
# 切换到 <branch> 分支。
git switch <branch>

# 创建并切换到 <new-branch>。
git switch -c <new-branch>

# 切换到上一个分支(类似 cd -)。
git switch -

# 进入分离 HEAD 模式(不绑定任何分支)。
git switch --detach <branch/commit>

参数说明

  • -c:创建新分支并切换。
  • --detach:进入分离 HEAD 状态(不会绑定到分支)。
  • -:上一个分支。

示例

1
2
3
4
5
6
7
8
9
10
11
# 切换到 feature-xyz 分支。
git switch feature-xyz

# 创建并切换到 new-feature 分支。
git switch -c new-feature

# 切换回上一个分支
git switch -

# 进入分离 HEAD 模式,当前处于 HEAD~2(即两次提交前)
git switch --detach HEAD~2

git merge

作用

git merge 用于合并指定分支到当前分支。

基本用法

1
2
# 将 <branch> 合并到当前分支。
git merge <branch>

参数说明

  • --no-ff:禁用 fast-forward 合并,保留 merge commit
  • --squash:压缩合并,不自动提交。
  • --abort:取消正在进行的合并。

示例

1
2
3
4
5
# 合并 feature-xyz 并保留 merge commit。
git merge feature-xyz --no-ff

# 取消正在进行的合并。
git merge --abort

git rebase

作用

git rebase 让当前分支的提交叠加到目标分支,使历史更线性。

基本用法

1
2
# 将当前分支变基到 <base-branch>。
git rebase <base-branch>

参数说明

  • --interactive (-i):交互式变基,可编辑提交。
  • --onto <new-base>:将当前分支基于 <new-base> 重新应用。
  • --abort:取消变基。
  • --continue:继续变基(解决冲突后)。

示例

1
2
3
4
5
# 交互式变基最近 3 次提交。
git rebase -i HEAD~3

# 取消变基。
git rebase --abort

git cherry-pick

作用

git cherry-pick 将某个提交复制到当前分支。

基本用法

1
2
# 将指定提交 commit-hash 应用到当前分支。
git cherry-pick <commit-hash>

参数说明

  • -n:仅应用变更,不提交。
  • -x:在提交信息中添加原始提交哈希。
  • --abort:取消 cherry-pick

示例

1
2
# 将 a1b2c3d 提交应用到当前分支。
git cherry-pick a1b2c3d

git revert

作用

git revert 用于撤销某次提交,同时保留历史记录,不影响之前的提交。

基本用法

1
2
# 创建一个新的补丁提交,以撤销 commit-hash。
git revert <commit-hash>

参数说明

  • -n:仅应用撤销变更,不提交。
  • --no-edit:使用默认提交信息。
  • --abort:取消撤销。

示例

1
2
# 撤销 a1b2c3d,并创建新的提交。
git revert a1b2c3d

暂存与提交

git add

作用

git add 将工作区的修改添加到暂存区(Staging Area),等待提交。

基本用法

1
2
3
4
5
6
7
8
9
10
11
# 将 <file> 添加到暂存区。
git add <file>

# 将所有修改的文件添加到暂存区。
git add .

# 将所有文件(包括新增、修改、删除)添加到暂存区。
git add -A

# 仅添加已修改和已删除的文件,不包括新文件。
git add -u

参数说明

  • .:添加当前目录及子目录所有变更的文件。
  • -A:添加所有文件(包括新增、修改、删除)。
  • -u:仅添加已修改和已删除的文件(不包括新文件)。
  • -p:交互式选择部分变更进行暂存。

示例

1
2
3
4
5
# 添加 file1.txt 和 file2.txt 到暂存区。
git add file1.txt file2.txt

# 逐块选择哪些修改要添加到暂存区。
git add -p

git commit

作用

git commit 将暂存区的变更提交到本地版本库。

基本用法

1
2
3
4
5
6
7
8
# 提交暂存区的变更,并附带提交信息。
git commit -m "提交信息"

# 跳过 git add,直接提交已跟踪的文件(不包括新文件)。
git commit -a -m "提交信息"

# 修改上一次提交(追加或修改提交信息)。
git commit --amend

参数说明

  • -m "<message>":直接在命令行输入提交信息。
  • -a:自动暂存所有已跟踪的文件(省略 git add)。
  • --amend:修改上一次提交(包括提交信息或文件)。
  • --no-edit--amend 时不修改提交信息。

示例

1
2
3
4
5
# 提交修改,并添加提交信息。
git commit -m "修复了一个 bug"

# 修改上次提交的提交信息。
git commit --amend -m "修复了 bug 并优化代码"

git reset

作用

git reset 用于撤销提交、取消暂存或恢复文件到特定状态。

基本用法

1
2
3
4
5
6
7
8
9
10
11
# 取消 <file> 的暂存状态,恢复到未暂存状态。
git reset HEAD <file>

# 撤销最近的一次提交,但保留变更(不会修改暂存区和工作区)。
git reset --soft HEAD~1

# 撤销提交,并取消暂存(不会修改工作区)。
git reset --mixed HEAD~1

# 彻底撤销最近一次提交,恢复到该提交前的状态(数据丢失,慎用)。
git reset --hard HEAD~1

参数说明

  • --soft:撤销提交,但保留文件在暂存区。
  • --mixed(默认):撤销提交,同时取消暂存,但不修改工作区文件。
  • --hard:彻底撤销提交、暂存和工作区文件(数据不可恢复)。

示例

1
2
3
4
5
# 撤销最近两次提交,变更仍然保留在暂存区。
git reset HEAD~2

# 回退到上一个提交,并删除所有未提交的修改。
git reset --hard HEAD~1

git rm

作用

git rm 用于从 Git 版本控制中删除文件(可选是否删除本地文件)。

基本用法

1
2
3
4
5
6
7
8
# 删除文件 <file>,并在下一次提交时生效。
git rm <file>

# 递归删除目录 <directory>。
git rm -r <directory>

# 仅从 Git 仓库中删除 <file>,保留本地文件。
git rm --cached <file>

参数说明

  • -r:递归删除目录。
  • --cached:仅从 Git 版本库中删除文件,保留本地文件。
  • -f:强制删除文件(即使已修改)。

示例

1
2
3
4
5
# 删除 logs/ 目录及其中的所有文件。
git rm -r logs/

# 将 file.txt 从 Git 版本库中删除,但不删除本地文件。
git rm --cached file.txt

git stash

作用

git stash 用于临时存储未提交的修改,以便切换分支或执行其他任务,稍后再恢复。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 将所有未提交的修改暂存起来,并清空工作区。
git stash

# 查看所有暂存的变更。
git stash list

# 恢复最近的暂存,并从 stash 列表中删除。
git stash pop

# 恢复最近的暂存,但不删除 stash 记录。
git stash apply

# 删除最近的 stash 记录。
git stash drop

# 清空所有暂存的变更。
git stash clear

参数说明

  • list:显示所有 stash 记录。
  • pop:恢复最近的 stash 并删除记录。
  • apply:恢复 stash 但不删除记录。
  • drop:删除最近的 stash 记录。
  • clear:清空所有 stash 记录。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 暂存所有未提交的修改。
git stash

# 恢复最近的暂存,并从 stash 列表中删除。
git stash pop

# 查看暂存列表:
git stash list

# 输出示例:
stash@{0}: WIP on main: 123abc 修复 bug
stash@{1}: WIP on feature: 456def 添加新功能



# 删除 `stash@{0}` 记录。
git stash drop stash@{0}

git restore

作用

git restore 用于恢复工作区中的文件,可以:

  • 撤销未提交的修改(恢复为上次提交的版本)。
  • 从暂存区恢复文件(相当于 git reset HEAD <file>)。
  • 恢复已删除的文件(只要还未提交删除)。

基本用法

1
2
3
4
5
6
7
8
9
10
11
# 恢复 <file> 为上次提交的版本(撤销本地修改)。
git restore <file>

# 取消暂存(等效于 git reset HEAD <file>)。
git restore --staged <file>

# 将 <file> 恢复到指定的 <commit> 版本。
git restore --source=<commit> <file>

# 恢复所有文件到上次提交的版本。
git restore .

参数说明

  • <file>:需要恢复的文件名。
  • --staged:从暂存区恢复文件到工作区(撤销 git add)。
  • --source=<commit>:恢复到指定的提交版本(如 HEAD~1commit-hash)。
  • .:恢复所有文件。

示例

1
2
3
4
5
6
7
8
9
10
11
# 恢复 file.txt,撤销本地修改(但不会影响暂存区),不会撤销 git add 操作。
git restore file.txt

# 取消 git add file.txt,但文件内容不会丢失,仍然在工作区(未暂存状态)。
git restore --staged file.txt

# 撤销所有未提交的修改。
git restore .

# 恢复 file.txt 到 上一次提交(HEAD~1) 的状态。
git restore --source=HEAD~1 file.txt

标签

git tag

作用

git tag 用于创建、删除、查看标签。Git 提供两种类型的标签:

  1. 轻量标签(Lightweight Tag):仅作为提交的引用,不包含额外信息。
  2. 附注标签(Annotated Tag):包含作者、日期、标签信息,存储在 Git 历史中。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 列出所有标签。
git tag

# 创建轻量标签 <tag-name>。
git tag <tag-name>

# 创建附注标签 <tag-name>,并附带描述信息。
git tag -a <tag-name> -m "Tag message"

# 删除本地标签 <tag-name>。
git tag -d <tag-name>

# 推送本地标签 <tag-name> 到远程仓库。
git push origin <tag-name>

# 推送所有本地标签到远程仓库。
git push origin --tags

# 列出符合 v1.* 规则的标签。
git tag -l "v1.*"

# 查看附注标签详情。
git show <tag-name>

参数说明

  • -a:创建附注标签,需添加描述信息。
  • -m "<message>":指定标签的描述信息(用于附注标签)。
  • -d:删除本地标签。
  • -l <pattern>:按模式搜索标签(如 v1.*)。
  • -f:强制覆盖已有标签(需谨慎)。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建轻量标签 v1.0。
git tag v1.0

# 创建附注标签 v1.0,并附加描述信息。
git tag -a v1.0 -m "First stable release"

# 删除 v1.0 标签。
git tag -d v1.0

# 推送 v1.0 到远程仓库。
git push origin v1.0

# 推送所有本地标签到远程仓库。
git push origin --tags

# 查看 v1.0 的详细信息。
git show v1.0

git describe

作用

git describe 用于显示最近的标签信息,通常用于版本管理,格式如下:

1
<tag-name>-<number-of-commits>-g<commit-hash>

例如:

1
v1.0-5-gf3b1c2d

表示 v1.0 之后有 5 次提交,最新提交的哈希是 f3b1c2d

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 显示最近的标签信息。
git describe

# 显示最新的任意标签(默认只考虑 annotated tags)。
git describe --tags

# 如果没有标签,返回最近的提交哈希。
git describe --always

# 显示完整格式,包括标签、提交数和哈希。
git describe --long

# 如果工作区有修改,返回 dirty 状态。
git describe --dirty

参数说明

  • --tags:允许使用轻量标签。
  • --always:如果没有标签,则返回提交哈希。
  • --long:显示完整格式。
  • --dirty:如果工作区有修改,则标记为 dirty

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
git describe

# 输出示例:表示距离 v1.0 有 5 次提交,最新提交哈希 f3b1c2d。
v1.0-5-gf3b1c2d



git describe --tags

# 输出示例:表示 v1.0.1 之后 3 次提交,最近提交哈希 5d6e8f9。
v1.0.1-3-g5d6e8f9



# 即使没有标签,也返回提交哈希。
git describe --always

# 输出示例:
g9a8b7c6
sh



# 查看未提交的修改。
git describe --dirty

# 输出示例:
v1.0-5-gf3b1c2d-dirty

子模块

git submodule 提供了一系列命令来管理子模块,这在管理第三方库、依赖项目或大规模分布式开发时非常有用。

git submodule add

作用

将另一个 Git 仓库作为子模块添加到当前仓库。

基本用法

1
2
# 将另一个 Git 仓库作为子模块添加到当前仓库。
git submodule add <repository_url> <path>

参数说明

  • <repository_url>:远程子模块仓库的地址。
  • <path>:子模块存放的目录(可选,默认仓库名)。

示例

1
2
# 在 libs/lib 目录下添加 lib.git 作为子模块。
git submodule add https://github.com/example/lib.git libs/lib

git submodule init

作用

git submodule init 不会拉取子模块的代码,只是让 Git 知道有子模块的存在(注册子模块)。

基本用法

1
2
3
4
5
# 初始化所有子模块。
git submodule init

# 仅初始化 <path> 目录下的子模块。
git submodule init

示例

1
2
# 初始化 .gitmodules 文件中定义的子模块。
git submodule init

git submodule update

作用

git submodule update 用于拉取子模块的代码,并将其同步到父仓库指定的提交。

基本用法

1
2
3
4
5
6
7
8
# 拉取子模块代码,并将其切换到父仓库记录的提交。
git submodule update

# 递归更新所有嵌套子模块(即子模块中的子模块)。
git submodule update --recursive

# 更新子模块到远程最新版本,而非父仓库记录的提交。
git submodule update --remote

参数说明

  • --recursive:递归更新所有子模块(包括嵌套子模块)。
  • --remote:更新子模块到远程最新提交,而不是父仓库记录的提交。

示例

1
2
# 递归更新所有子模块,并拉取最新的远程提交。
git submodule update --recursive --remote

git submodule status

作用

git submodule status 显示当前子模块的状态,包括:

  • 哈希值:子模块当前指向的提交。
  • 是否已修改:如果子模块的 HEAD 与父仓库的记录不同,则会有 + 标记。
  • 路径:子模块存放的目录。

基本用法

1
2
# 列出所有子模块的状态。
git submodule status

示例

1
2
3
4
5
6
7
git submodule status

# 示例输出:
+f1e2c3b4c5 libs/lib (v1.2-5-gf1e2c3b)
- `+` 表示子模块已修改,与父仓库记录的提交不同。
- `f1e2c3b4c5` 是子模块当前的提交哈希值。
- `libs/lib` 是子模块所在目录。

git submodule foreach

作用

git submodule foreach 允许对所有子模块执行批量操作。

基本用法

1
2
# 在每个子模块的目录中执行 <command>。
git submodule foreach <command>

示例

1
2
3
4
5
# 在所有子模块中执行 git pull,拉取最新代码。
git submodule foreach 'git pull origin main'

# 在所有子模块中切换到 main 分支并拉取最新代码。
git submodule foreach 'git checkout main && `Git` pull'

git submodule sync

作用

如果父仓库修改了 .gitmodules 文件中的子模块 URL,需要执行 git submodule sync 来同步 URL。

基本用法

1
2
3
4
5
# 同步所有子模块的 URL。
git submodule sync

# 仅同步指定子模块 <path>。
git submodule sync <path>

示例

1
2
# 同步 .gitmodules 文件中的所有子模块 URL。
git submodule sync

git submodule deinit

作用

git submodule deinit 取消初始化子模块,使其变成未克隆的状态。

基本用法

1
2
3
4
5
# 取消 <path> 目录下的子模块初始化。
git submodule deinit <path>

# 取消所有子模块的初始化。
git submodule deinit --all

示例

1
2
# 取消 libs/lib 目录下的子模块初始化。
git submodule deinit libs/lib

git submodule remove

作用

Git 没有 git submodule remove,但可以手动删除子模块。

基本用法

基本步骤如下:

1
2
3
4
5
6
7
8
# 1. 取消初始化
git submodule deinit -f <path>

# 2. 删除子模块目录
rm -rf <path> .git/modules/<path>

# 3. 从 Git 中移除子模块
git rm -f <path>

git clone –recursive

作用

如果一个 Git 仓库包含子模块,直接 git clone 不会自动克隆子模块。需要使用 --recursive 参数。

基本用法

1
2
3
4
5
6
# 克隆仓库并初始化所有子模块。
git clone --recursive <repository_url>

# 先克隆仓库,再初始化子模块(等效于 --recursive)。
git clone <repository_url>
git submodule update --init --recursive

示例

1
2
# 克隆 repo.git 并自动拉取子模块。
git clone --recursive https://github.com/example/repo.git

清理

git clean

作用

删除未跟踪文件,但不会影响已提交或暂存的文件,它只删除:

  • 未被 Git 跟踪的文件(未 git add 的文件)。
  • 忽略的文件(如 .gitignore 里的文件,可选择删除)。
  • 未跟踪的目录(可选择删除)。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 演示模式:显示将要删除的文件,但不会实际删除(安全检查)。
git clean -n

# 强制删除未跟踪的文件(不删除目录)。
git clean -f

# 强制删除未跟踪的文件和目录。
git clean -fd

# 删除所有未跟踪的文件,包括 .gitignore 里忽略的文件。
git clean -fx

# 删除所有未跟踪的文件和目录,包括 .gitignore 里忽略的文件。
git clean -fxd

参数说明

  • -n:仅模拟执行,不删除任何文件,只显示将被删除的文件列表。
  • -f:强制删除未跟踪的文件(Git 为了安全,不允许 clean 默认执行,需要 -f)。
  • -d:删除未跟踪的目录(默认只删除文件)。
  • -x:删除所有未跟踪的文件,包括 .gitignore 里忽略的文件。
  • -X:仅删除 .gitignore 里忽略的文件(不删除未跟踪但未被忽略的文件)。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 演示模式(安全检查)。
git clean -n

# 输出示例:
Would remove temp.txt
Would remove build/
# Would remove 只是模拟执行,未实际删除。



# 删除未跟踪的文件。
git clean -f

# 输出示例:
Removing temp.txt
# 删除 temp.txt(未跟踪的文件),不会删除目录。



# 删除未跟踪的文件和目录。
git clean -fd

# 输出示例:
Removing temp.txt
Removing build/
# 删除 `temp.txt(文件),删除 build/(目录)。



# 删除所有未跟踪的文件(包括 `.gitignore` 里的文件)。
git clean -fx

# 输出示例:
Removing temp.txt
Removing .env
Removing node_modules/
# 删除 .env(被 .gitignore 忽略的文件),删除 .gitignore 里忽略的所有文件。



# 仅删除 .gitignore 里忽略的文件。
git clean -fX

# 输出示例:
Removing .env
Removing node_modules/
# 不会删除 temp.txt(未跟踪但未被 .gitignore 忽略),仅删除 .gitignore 中列出的文件。

总结

Git 提供了丰富且灵活的命令,从简单的 initaddcommit,到高级的 rebasecherry-picksubmodule 等,覆盖了开发者在项目协作过程中可能遇到的几乎所有场景。掌握这些命令及其常见参数,能大幅提升我们对版本历史的可控性与开发效率。
然而,最重要的并不是死记硬背所有命令,而是在实际项目中灵活运用。遇到问题时,及时查看官方文档或 “git <command> --help” 也能快速解惑。希望本篇整理能帮助你在日常开发中更加游刃有余地管理代码。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!