1. 项目概述
作为一名在软件开发一线摸爬滚打了十多年的老码农,我几乎每天都要和 Git 打交道。从最初接触时的手忙脚乱,到如今闭着眼睛都能敲出常用命令,这个过程里我踩过的坑、总结的经验,足够写一本小册子。网上关于 Git 命令的清单、速查表多如牛毛,但很多要么是简单的命令罗列,缺乏上下文;要么过于深入,让初学者望而却步。今天,我想从一个资深开发者的视角,为你整理一份真正“接地气”的 Git 常用命令集合。这份集合不仅仅是命令的堆砌,更是我多年实战经验的结晶,我会告诉你每个命令在什么场景下用、为什么用、以及用了之后可能会遇到什么“坑”。无论你是刚入门的新手,还是想梳理知识体系的老手,这篇文章都能让你对 Git 的日常使用有一个清晰、透彻的理解,告别“用时现查”的尴尬。
2. Git 核心概念与工作流精讲
在开始罗列命令之前,我们必须先理解 Git 的核心思想。很多新手觉得 Git 复杂,往往是因为一开始就陷入了命令的海洋,却不知道这些命令在 Git 的“世界观”里扮演什么角色。
2.1 Git 的“三棵树”模型
你可以把 Git 想象成一个拥有三个关键区域的版本控制系统:
- 工作区 (Workspace) :就是你电脑上直接看到、编辑文件的目录。你在这里新增、修改、删除文件。
-
暂存区 (Stage/Index)
:这是一个非常精妙的设计,可以理解为一个“预提交区”。通过
git add命令,你可以将工作区的改动“挑选”出来,放到这个区域。这让你可以分批次、有选择地提交代码,而不是一次性提交所有改动。 -
本地仓库 (Repository)
:通过
git commit命令,暂存区的内容就被永久保存到了本地仓库中,形成一个“快照”(即一次提交)。本地仓库里保存了你项目完整的历史记录。
此外,还有一个 远程仓库 (Remote) ,比如 GitHub、Gitee 或公司内建的 GitLab,它用于团队协作和备份。
为什么理解这个模型很重要?
因为几乎所有的 Git 命令,都是在操作这三个区域之间的关系。例如,
git status
就是查看工作区和暂存区差异的命令。混淆了这些区域,就很容易用错命令。
2.2 基本工作流:从修改到同步
一个标准的、无冲突的 Git 工作流通常遵循以下步骤,这也是你 80% 时间在重复的操作:
- 在工作区修改文件 :写你的代码。
-
git add:将修改“暂存”到暂存区。这步是准备提交。 -
git commit:将暂存区的改动正式提交到本地仓库,并附上说明信息。 -
git push:将本地仓库的提交推送到远程仓库,与团队共享。 -
git pull:从远程仓库拉取最新的改动到本地,保持同步。
这个流程构成了 Git 使用的基石。接下来,我们就按照这个逻辑,并结合实际开发中更复杂的场景,来逐一拆解那些你必须掌握的命令。
3. 仓库初始化与基础配置
万事开头难,但 Git 的初始化却异常简单。
3.1 创建与克隆仓库
场景一:从头开始一个新项目。
你新建了一个文件夹
my-project
,想用 Git 来管理它。
cd my-project
git init
执行
git init
后,当前目录下会生成一个隐藏的
.git
文件夹,这就是 Git 仓库的所有元数据所在。此时,你的项目就和 Git 绑定起来了。
场景二:参与一个已存在的项目。 更常见的情况是,你需要把同事或开源项目已有的代码拿到本地。
git clone <repository-url>
例如
git clone https://github.com/username/project.git
。这个命令做了两件事:1. 将远程仓库的所有代码和历史下载到本地;2. 自动为你创建好与远程仓库(通常命名为
origin
)的关联。这是你参与任何现有 Git 项目的起点。
实操心得 :
git clone默认会拉取整个项目历史,对于大型仓库可能较慢。如果你只关心最新代码,可以加上--depth 1参数进行浅克隆,但这会丢失历史记录,通常只用于 CI/CD 等一次性构建场景。
3.2 用户身份配置:你的“代码身份证”
提交代码时,Git 需要知道是谁提交的。这必须在第一次提交前配置好。
# 设置全局用户名和邮箱(对所有项目生效)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# 如果只想为当前项目设置(会覆盖全局配置)
git config user.name "Your Name"
git config user.email "your.email@example.com"
为什么这很重要? 因为每一次提交都会记录作者信息。在团队协作中,清晰的作者信息是责任追溯和沟通的基础。错误或乱填的邮箱会导致你的贡献无法正确关联到你的账户(如在 GitHub 上不显示贡献图)。
你可以通过
git config --list
查看所有当前生效的配置。如果想修改某个配置,可以直接再次运行
git config
命令,或者编辑配置文件(全局配置通常在
~/.gitconfig
)。
4. 日常开发循环:增、删、改、查、提交
这是开发者的日常,也是 Git 命令最密集使用的环节。
4.1 状态查看与差异比较
在做出任何提交决定前,先看看“现场”情况。
# 查看当前仓库状态:哪些文件被修改、新增或删除,哪些已暂存
git status
git status
是你的“仪表盘”。它用简洁的语言告诉你工作区和暂存区发生了什么。红色文件表示未暂存的修改,绿色文件表示已暂存等待提交。
更细致的改动查看:
git status
只告诉你哪些文件变了,而
git diff
则展示具体改了哪些内容。
# 比较工作区和暂存区的差异(即,你修改了但还没 add 的内容)
git diff
# 比较暂存区和上一次提交的差异(即,你已经 add 了,准备提交的内容)
git diff --cached
# 或者使用 git diff --staged (两者等价,--staged 更语义化)
# 比较工作区和上一次提交的差异(包含所有未暂存和已暂存的改动)
git diff HEAD
git diff
的输出是标准的 Unix diff 格式,
-
开头表示删除的行,
+
开头表示新增的行。熟练阅读 diff 是程序员的基本功。
4.2 文件操作:精准控制版本
添加文件到暂存区:
# 添加指定文件或目录
git add README.md
git add src/
# 添加当前目录所有变化(包括新增、修改、删除的文件)
git add .
# 或者
git add -A
# 交互式添加:Git会展示每一处改动,让你决定是否暂存。非常适合提交前做最后审查。
git add -p
注意事项 :
git add .和git add -A在 Git 2.x 版本中在项目根目录下行为基本一致,都会添加所有改动。但在子目录下执行时,git add .只添加当前目录及其子目录的改动,而git add -A仍然添加整个工作树的改动。为了一致性,我通常使用git add -A。
移除文件:
# 从工作区和暂存区同时删除文件(物理删除文件,并记录这次删除操作)
git rm obsolete_file.txt
# 只从暂存区删除,但保留工作区的物理文件。常用于误 add 了不该跟踪的文件(如编译产物、本地配置文件)。
git rm --cached local_config.ini
重命名或移动文件:
虽然你可以直接用操作系统命令
mv
,但用 Git 命令能更好地被 Git 识别为“重命名”操作,有利于历史追溯。
git mv old_name.txt new_name.txt
4.3 提交的艺术
暂存好了改动,就该创建提交了。
# 最基本的提交,附带一条提交信息
git commit -m "Fix: 修复用户登录失败的问题"
# 提交时,在编辑器中详细描述本次修改(推荐)
git commit
执行
git commit
不加
-m
参数,会打开默认的文本编辑器(如 Vim、Nano),让你编写更详细的提交说明。第一行是简短摘要,空一行后是详细描述。好的提交信息是项目历史的宝贵财富。
修改上一次提交: 人非圣贤,孰能无过。刚提交完发现漏了文件,或者提交信息写错了?
# 将当前的暂存区改动,追加到上一次提交中,并可以修改提交信息
git add forgotten_file.js
git commit --amend
重要警告 :
git commit --amend会 重写历史 。如果这个提交已经推送到远程仓库,强制推送 (git push --force) 可能会给协作者带来麻烦。因此, 只 amend 尚未推送的本地提交 。
跳过暂存区直接提交:
对于一些小修改,你可以跳过
git add
步骤。
git commit -a -m "Quick fix for typo"
-a
参数会自动把所有
已跟踪文件
的修改和删除操作暂存起来,然后提交。但
不会自动暂存新增的未跟踪文件
。
5. 分支管理:高效并行开发的基石
分支是 Git 的“杀手锏”,它让你可以低成本地创建代码的独立副本,用于尝试新功能、修复 Bug,而不会影响主线。
5.1 分支的创建、切换与查看
# 查看所有本地分支,当前分支前会标有 * 号
git branch
# 查看所有分支(包括远程分支)
git branch -a
# 创建新分支
git branch feature-awesome
# 创建并切换到新分支(最常用)
git checkout -b feature-awesome
# 或者使用更语义化的 switch 命令(Git 2.23+)
git switch -c feature-awesome
# 切换到已有分支
git checkout main
git switch main
# 删除已合并的分支
git branch -d feature-merged
# 强制删除未合并的分支(慎用!)
git branch -D feature-abandoned
5.2 合并与变基:整合代码的两种方式
当你完成一个功能分支的开发,需要将其合并回主分支。
合并 (Merge):
# 首先,切换到要合并到的目标分支(如 main)
git switch main
# 然后,合并来源分支
git merge feature-awesome
合并会创建一个新的“合并提交”,保留了两个分支的历史脉络。这是最安全、最常用的方式。
变基 (Rebase):
# 在功能分支上执行
git switch feature-awesome
git rebase main
变基会把你功能分支上的所有提交,“重新播放”在目标分支(main)的最新提交之后。结果是得到一条线性的、更整洁的历史。 但变基会重写提交历史 ,同样只适用于尚未共享的本地分支。
黄金法则 : 只对你本地、尚未推送的分支执行变基。对公共分支(如 main, develop)永远使用合并。
5.3 远程分支协作
本地分支需要与远程仓库互动。
# 查看远程仓库信息
git remote -v
# 从远程获取所有分支和提交信息(不会自动合并)
git fetch origin
# 获取远程分支并在本地创建跟踪分支
git fetch origin feature-remote
git checkout -b feature-local origin/feature-remote # 旧方式
git switch -c feature-local --track origin/feature-remote # 新方式
# 将本地分支推送到远程并建立关联(首次推送时)
git push -u origin feature-awesome
# 之后推送可以简写为
git push
# 删除远程分支
git push origin --delete old-branch
6. 版本穿梭与后悔药:重置与恢复
这是 Git 最强大的部分之一——时间旅行。但操作不当也会导致“悲剧”,请务必理解后再操作。
6.1 恢复文件:让单个文件回到过去
# 丢弃工作区中对某个文件的修改,恢复到暂存区(或上一次提交)的状态
git checkout -- README.md
# 新版本 Git 推荐使用 `restore`
git restore README.md
# 将暂存区中的文件撤销到工作区(即取消 add)
git reset HEAD README.md
git restore --staged README.md
6.2 重置提交:调整本地历史
git reset
主要用于在本地“回退”提交。它有三个主要模式,区别在于对
工作区
和
暂存区
的处理:
| 模式 | 移动 HEAD 指针 | 重置暂存区 | 重置工作区 | 适用场景 |
|---|---|---|---|---|
--soft
| 是 | 否 | 否 | 提交信息写错了,想重新提交。所有改动都保留在暂存区。 |
--mixed
(默认)
| 是 | 是 | 否 | 想取消最近几次提交,但保留修改内容在工作区重新整理。这是最常用的模式。 |
--hard
| 是 | 是 | 是 | 危险! 彻底丢弃最近的提交和所有修改,完全回到某个历史状态。 |
# 假设当前在提交 C,想回到提交 B
# A <- B <- C (HEAD)
# 软重置:HEAD指向B,C的改动还在暂存区
git reset --soft B
# 混合重置(默认):HEAD指向B,C的改动还在工作区(未暂存)
git reset B
# 等价于 git reset --mixed B
# 硬重置:HEAD指向B,C的改动完全丢弃!慎用!
git reset --hard B
6.3 储藏改动:临时切换上下文
你正在功能A上开发到一半,突然需要紧急修复生产环境的 Bug。这时你还没法提交。
# 将当前工作区和暂存区的改动“打包”储藏起来
git stash
# 或者添加说明信息
git stash push -m "WIP: half-done feature A"
# 查看所有储藏
git stash list
# 恢复最近一次的储藏,并从储藏列表中删除它
git stash pop
# 恢复指定储藏(如 stash@{1}),但不删除
git stash apply stash@{1}
# 删除一个储藏
git stash drop stash@{0}
git stash
是你的“工作现场保存器”,让你可以干净地切换分支,处理完急事后再回来继续。
7. 查看历史与定位问题
一个健康的项目历史,就是一部可追溯的纪录片。
7.1 查看提交日志
# 基础日志,按时间倒序显示
git log
# 单行简洁显示
git log --oneline
# 图形化显示分支和合并历史(非常直观)
git log --graph --oneline --all
# 显示最近5次提交
git log -5
# 显示包含特定关键词的提交
git log --grep="bugfix"
# 显示某个文件的历史修改记录
git log --follow -p README.md
7.2 追溯代码责任人
当发现一段有问题的代码时,你需要知道是谁、在什么时候引入的。
git blame README.md
git blame
会逐行显示文件,并标注每一行最后修改的提交哈希、作者和日期。这是团队协作中定位问题的利器。
7.3 二分查找:定位引入 Bug 的提交
当 Bug 不知道是哪个提交引入的时候,
git bisect
堪称神器。它使用二分查找算法,自动帮你定位第一个引入问题的提交。
# 开始二分查找
git bisect start
# 标记当前版本为“有问题”
git bisect bad
# 标记一个已知没问题的旧版本(如一个月前的提交)
git bisect good v1.0.0
# 之后 Git 会自动检出中间的一个提交,你进行测试
# 如果这个提交没问题,就标记 good
git bisect good
# 如果这个提交有问题,就标记 bad
git bisect bad
# 重复此过程,直到 Git 定位到第一个 bad 提交
# 查找结束,重置到最初状态
git bisect reset
8. 远程协作与同步
个人开发是基础,团队协作才是 Git 价值的体现。
8.1 拉取与推送
# 从远程仓库获取更新并合并到当前分支(常用,但可能产生合并提交)
git pull origin main
# 等价于 git fetch origin + git merge origin/main
# 使用变基方式拉取,保持历史线性(更推荐)
git pull --rebase origin main
# 等价于 git fetch origin + git rebase origin/main
# 推送本地分支到远程
git push origin feature-branch
# 如果远程分支有更新导致推送失败,先拉取再推送
git pull --rebase origin feature-branch
git push origin feature-branch
# 强制推送(危险!会覆盖远程历史,仅用于修正未共享的本地历史后)
git push --force-with-lease origin feature-branch
重要提示 :
git push --force是危险的,因为它无条件覆盖远程分支。--force-with-lease是更安全的选项,它会在强制推送前检查远程分支是否已被他人更新,如果被更新了则推送失败,防止覆盖同事的工作。
8.2 处理冲突
当你和同事修改了同一文件的同一区域,合并或拉取时就会产生冲突。Git 会在文件中用
<<<<<<<
,
=======
,
>>>>>>>
标记出冲突部分。
解决冲突的步骤:
-
执行
git pull或git merge后提示冲突。 - 打开冲突文件,手动编辑,保留你想要的内容,删除冲突标记。
-
将解决后的文件添加到暂存区:
git add conflicted_file.py。 -
完成合并:
git commit。
使用图形化工具 :对于复杂的冲突,使用 VS Code、IntelliJ IDEA 或专门的合并工具(如 Meld, Beyond Compare)会高效得多,它们可以并排显示更改,让你三向合并。
9. 高级技巧与最佳实践
掌握了基础,再来点提升效率的“骚操作”。
9.1 使用别名:为长命令设置快捷键
Git 支持为命令设置别名,可以极大提升效率。
# 设置全局别名
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\-commit"
设置后,你就可以用
git st
代替
git status
,用\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
git co main
代替
git checkout main
。那个超长的
git lg
别名能输出非常漂亮、带分支图的提交历史。
9.2 .gitignore 文件:忽略不需要跟踪的文件
项目里总有些文件不该纳入版本控制,比如编译产物、本地配置、IDE 设置、依赖包等。在项目根目录创建
.gitignore
文件,并写入匹配规则。
# 忽略所有 .log 文件
*.log
# 忽略 node_modules 目录
node_modules/
# 忽略所有 .env 环境变量文件,但保留 .env.example
.env
!.env.example
# 忽略某个特定文件
secret_key.txt
GitHub 提供了各种语言和项目的
.gitignore
模板,创建新项目时可以直接选用。
9.3 提交信息规范
好的提交信息能让历史清晰可读。我推荐使用类似 Angular 的规范:
- feat : 新功能
- fix : 修复 Bug
- docs : 文档更新
- style : 代码格式调整(不影响逻辑)
- refactor : 代码重构
- test : 测试相关
- chore : 构建过程或辅助工具的变动
示例:
git commit -m "feat(user): 新增用户头像上传功能"
。这样的历史,用
git log --oneline
一看就懂。
10. 常见问题与排查实录
理论说再多,不如看看实战中常遇到的“坑”。
10.1 提交了错误的内容或信息
- 问题 :刚提交完,发现漏了文件,或者提交信息有错别字。
-
解决
:使用
git commit --amend。先git add漏掉的文件,然后运行git commit --amend。这会用一个新的提交替换掉上一次提交。 切记,仅用于未推送的提交。
10.2 想撤销最近几次提交,但保留修改
- 问题 :连续做了几次临时提交,想合并成一个清晰的提交。
-
解决
:使用
git reset --soft。例如,想撤销最近3次提交但保留所有改动在暂存区:git reset --soft HEAD~3。然后重新git add和git commit。
10.3 误执行了
git add .
,添加了不该跟踪的文件
-
问题
:不小心把
node_modules或.env加入了暂存区。 -
解决
:使用
git rm --cached将其从暂存区移除,并添加到.gitignore。git rm --cached -r node_modules/ # -r 用于目录 echo "node_modules/" >> .gitignore git add .gitignore git commit -m "chore: 忽略 node_modules 目录"
10.4 从远程拉取代码时遇到冲突
-
问题
:执行
git pull失败,提示冲突。 -
解决
:
- 不要慌。Git 只是暂停了合并过程。
-
运行
git status查看哪些文件冲突。 -
手动编辑这些文件解决冲突(删除
<<<<<<<,=======,>>>>>>>标记)。 -
解决后,
git add这些文件。 -
运行
git commit来完成合并。如果你在解决冲突中途想放弃,可以运行git merge --abort回到合并前的状态。
10.5 分支名打错了,或者想重命名分支
-
问题
:创建了分支
featrue-xxx,想改成feature-xxx。 -
解决
:
# 重命名当前分支 git branch -m new-branch-name # 重命名指定分支 git branch -m old-name new-name # 如果分支已推送到远程,需要删除远程旧分支,推送新分支 git push origin --delete old-name git push -u origin new-name
10.6 如何完全删除一个提交记录?
- 问题 :不小心提交了包含敏感信息(如密码)的文件,需要从历史中彻底抹去。
-
解决
:这需要使用
git filter-branch或更高效的git filter-repo工具。 这是一个破坏性极强的操作,会重写所有历史,影响所有协作者。 仅适用于尚未广泛共享的仓库,或在万不得已时使用。操作前务必全员备份并沟通。对于已推送的敏感信息泄露,应立即视为安全事件处理,优先修改密码和密钥,而非仅仅删除 Git 历史。
最后,我的个人体会是,Git 的强大源于其设计的灵活性,但这也带来了复杂性。不要试图一次性记住所有命令。掌握最核心的
status
,
add
,
commit
,
pull
,
push
,
checkout/switch
,
branch
,
merge
,再辅以
diff
,
log
,
stash
,就足以应对 95% 的日常开发场景。剩下的 5%,善用
git --help
和搜索引擎。把这份清单加入书签,遇到陌生场景时回来查一查,结合理解去实践,很快你就能像呼吸一样自然地使用 Git 了。记住,版本控制的核心目的是协作与安全,清晰的提交历史和良好的分支策略,比你记住多少冷门命令重要得多。
957

被折叠的 条评论
为什么被折叠?



