告别死记硬背:Git 常用命令学习指南
Git命令核心思想
首先,我们需要理解 Git 是如何看待我们的代码的。它主要涉及四个关键区域:
- 工作区 (Workspace): 就是你在电脑上能看到的项目文件夹,包含了你当前正在编辑和修改的文件。
- 暂存区 (Staging Area / Index): 一个“待提交”的缓冲区。当你对文件做了修改,并希望在下一次“存档”(commit)时包含这些修改,你就需要先把它们放到暂存区。这是一个 Git 的核心特色,它让你能够精确控制每次提交包含哪些内容。
- 本地仓库 (Local Repository): 你的个人代码数据库,存放在项目根目录下的
.git文件夹里。它包含了项目所有的历史版本(commits)。你提交的代码都保存在这里。 - 远程仓库 (Remote Repository): 托管在网络服务器上的代码仓库(如 GitHub, GitLab)。这是你与团队成员协作、共享代码的地方。
我们的绝大部分 Git 操作,本质上就是在这四个区域之间移动和管理你的代码。
整体流程

工作区 -> 暂存区(git add):git add是将工作区的修改“打包”,准备进行下一次提交。暂存区 -> 本地仓库(git commit):git commit将暂存区的内容生成一个永久快照(版本),保存在本地仓库。本地仓库 -> 远程仓库(git push):git push将本地的提交分享到远程服务器。远程仓库 -> 本地仓库(git pull/fetch):fetch只下载更新,pull在fetch的基础上还会尝试合并。暂存区 -> 工作区(git restore):git retore用暂存区的版本覆盖工作区的修改。- 以上为部分核心流程,更多详情见git命令分类内容。
Git命令分类
初始化与配置 (Setup & Config)
- 目的:开始一个新项目或获取一个现有项目,并设置你的个人信息。
- 在 Git 中,几乎所有命令都有丰富的拓展和变形,通常通过添加不同的标志 (flags) 或 参数 (arguments) 来实现,下面我们分析拆解“初始化与配置”分类下这三个命令的基本用法和常用拓展。
git init创建新git仓库
基本用法: git init
在当前目录下创建一个新的 Git 仓库(即一个 .git 文件夹)。
常用变形与拓展:
git init [directory_name]- 作用: 在指定位置创建一个新文件夹,并将其初始化为 Git 仓库。
- 场景: 你想创建一个名为
my-new-project的项目并马上让它成为 Git 仓库,但你现在不在那个目录下。你可以直接运行git init my-new-project,而不需要mkdir my-new-project && cd my-new-project && git init这一连串操作。
git init --bare- 作用: 创建一个裸仓库 (Bare Repository)。
- 区别:
- 普通仓库(
git init)包含一个.git目录和一个工作区(你能直接看到和编辑的项目文件)。 - 裸仓库没有工作区,它只包含
.git目录里的版本历史、分支信息等核心内容。它的目录结构看起来就像.git文件夹本身。
- 普通仓库(
- 场景: 这是用来搭建中央服务器/远程仓库的。团队成员不会直接在裸仓库里修改文件,而是将各自的修改
push到这个裸仓库中,再从里面pull更新。你自己在 GitHub/GitLab 上创建的仓库,其本质就是一个裸仓库。
git init -b [branch_name]或git init --initial-branch=[branch_name]- 作用: 在初始化仓库时,指定初始分支的名称。
- 场景: 传统上,Git 的默认主分支是
master。但现在社区和很多平台(如 GitHub)推荐使用main作为默认主分支。通过git init -b main,你可以让新创建的仓库直接使用main作为主分支名,避免后续再重命名的麻烦。
git clone克隆仓库到本地
基本用法: git clone [repository_url]
从指定的 URL 克隆一个远程仓库到本地。
常用变形与拓展:
git clone [url] [new_directory_name]- 作用: 克隆仓库,并将其保存到一个自定义名称的文件夹中。
- 场景: 如果远程仓库名叫
project-backend-v2,但你想在本地把它命名为api-server,就可以使用git clone [url] api-server。 - 其他的:
git clone [url] .克隆项目到目录,但是不会创建子目录git clone [url]克隆项目到目录,默认使用原项目名称创建项目
git clone -b [branch_name] [url]或git clone --branch [branch_name] [url]- 作用: 只克隆指定的特定分支。
- 场景: 一个项目有很多分支,但你只关心
development分支的开发工作。使用这个命令,克隆完成后你的工作区会自动切换到development分支,而不是默认的主分支。
git clone --depth [number] [url]- 作用: 创建一个浅克隆 (Shallow Clone),只包含最近的
[number]次提交记录,而不是全部历史。 - 场景:
- 大型项目: 如果一个项目历史非常悠久、体积巨大,完整克隆可能要花费很长时间和大量磁盘空间。如果你只关心最新的代码,
git clone --depth 1 [url]会非常快。 - 持续集成 (CI/CD): 在自动化构建和部署流程中,通常只需要最新代码来运行测试和打包,不需要完整的 Git 历史。浅克隆可以极大提升流水线效率。
- 大型项目: 如果一个项目历史非常悠久、体积巨大,完整克隆可能要花费很长时间和大量磁盘空间。如果你只关心最新的代码,
- 作用: 创建一个浅克隆 (Shallow Clone),只包含最近的
git clone --mirror [url]- 作用: 创建一个远程仓库的镜像。这会克隆一个裸仓库 (
-bare),并保留所有远程跟踪分支、标签等所有引用信息。 - 场景: 你想完整地备份一个远程仓库,或者想把一个项目从一个平台(如 GitLab)迁移到另一个平台(如 GitHub)。你可以先创建一个镜像,然后再推送到新的远程地址。
- 作用: 创建一个远程仓库的镜像。这会克隆一个裸仓库 (
git config设置用户信息
基本用法: git config --global user.name "Your Name"
设置全局的用户信息。
git config 最重要的拓展在于它的作用域 (Scope)。
作用域的层级:
Git 的配置有三个主要级别,优先级从高到低:
-local(本地)- 作用: 配置只对当前仓库有效。配置信息保存在当前仓库的
.git/config文件中。 - 用法:
git config --local user.name "ProjectSpecific Name"(或者不加标志,默认为-local) - 场景: 你在公司的项目需要使用公司邮箱,但在自己的开源项目里想用个人邮箱。你可以在每个仓库内部进行本地配置。
- 作用: 配置只对当前仓库有效。配置信息保存在当前仓库的
-global(全局)- 作用: 配置对当前用户的所有仓库都有效。配置信息保存在用户主目录下的
.gitconfig文件中(例如~/.gitconfig)。 - 用法:
git config --global user.name "Your Default Name" - 场景: 设置你最常用的用户名和邮箱,这样就不用每个项目都设置一遍了。
git config --global user.name "Your Name"
git config --global user.email "Your email”
- 作用: 配置对当前用户的所有仓库都有效。配置信息保存在用户主目录下的
-system(系统)- 作用: 配置对系统上的所有用户都有效。配置信息保存在 Git 的安装目录下(例如
/etc/gitconfig)。 - 用法:
git config --system ...(通常需要管理员权限) - 场景: 系统管理员为服务器上的所有用户设置统一的配置,比如公司内部的代理服务器。
- 作用: 配置对系统上的所有用户都有效。配置信息保存在 Git 的安装目录下(例如
其他常用拓展:
git config --list: 查看当前生效的所有配置项(会显示 local, global, system 的合并结果)。git config --list --show-origin: 不仅显示配置项,还显示它们分别来自哪个配置文件(local, global, or system),非常适合用来排查配置问题。git config --unset [key]: 删除一个配置项。git config alias.[alias_name] "[command]": 设置命令别名,这是提升效率的神器!- 场景: 你觉得
git status太长,可以设置git config --global alias.st status。之后你只需要输入git st即可。 - 常用别名设置:
git config --global alias.co checkoutgit config --global alias.br branchgit config --global alias.ci commitgit config --global alias.lg "log --oneline --graph --decorate"(一个复杂的、带格式的日志输出)
- 场景: 你觉得
总结
git init的拓展主要关注在哪里和以什么形式创建仓库(普通 vs. 裸仓库)。git clone的拓展主要关注克隆什么(特定分支、部分历史)和克隆到哪里。git config的拓展核心是作用域(本地、全局、系统)和自定义功能(如别名)。
理解了这些变形,你就能从一个 Git 的“使用者”向一个“高效使用者”和“定制者”迈进了。
本地核心工作流 (Core Local Workflow) - 这是你最常用的部分
- 目的:在你的本地电脑上进行代码修改、保存和版本管理。
- 下面围绕工作区 -> 暂存区 -> 本地仓库这个核心流程,来拆解“本地核心工作流”分类下命令的基本用法和常用拓展。
git status显示状态
基本用法: git status
显示工作区和暂存区的状态,告诉你哪些文件被修改、哪些是新增的、哪些已经准备好提交。
常用变形与拓展:
git status -s或git status --short- 作用: 提供一个简短、紧凑的输出格式。这是很多经验丰富的开发者最常用的状态查看方式。
- 输出解读: 输出是两列字符,后面跟着文件名。
- 第一列表示暂存区的状态。
- 第二列表示工作区的状态。
M(左M): 文件被修改后已暂存 (git add)M(右M): 文件被修改但未暂存A: 新文件已暂存??: 未被Git跟踪的新文件D: 文件被删除后已暂存D(右D): 文件在工作区被删除但未暂存
- 场景: 当你只想快速扫一眼当前有哪些文件发生了变化时,
git status -s的输出一目了然,没有多余的文字干扰。
git status -b或git status --branch作用: 在状态输出的顶部,额外显示当前所在的分支,以及与上游(远程)分支的同步情况。
输出示例:
## main...origin/main [ahead 1]这表示你当前在
main分支,该分支跟踪的是origin/main,并且你有一个本地提交(ahead 1)尚未推送到远程。场景: 随时了解你的本地分支与远程分支的关系,是领先、落后还是同步,对于协作开发至关重要。
git status -sb- 作用:
short和branch两个选项的结合,提供了最紧凑但信息又足够丰富的状态概览。很多开发者会为它设置一个别名,如git sb。
- 作用:
git add添加到暂存区
基本用法: git add [file]
将指定文件的修改从工作区添加到暂存区。
常用变形与拓展:
git add .- 作用: 将当前目录下所有被修改(modified)和新增(untracked)的文件都添加到暂存区。这是最常用的
add命令之一。 - 场景: 你在项目中修改了多个文件,并新建了几个文件,想一次性全部提交,直接在项目根目录运行
git add .即可。
- 作用: 将当前目录下所有被修改(modified)和新增(untracked)的文件都添加到暂存区。这是最常用的
git add -u或git add --update- 作用: 只添加已被跟踪的文件的修改(包括修改和删除),不会添加新创建的文件(untracked files)。
- 场景: 你改了3个文件,同时又在项目里创建了一些临时的测试文件。你只想提交那3个文件的改动,而不希望把新文件加进去,这时
git add -u就非常方便。
git add -A或git add --all- 作用:
add命令的“终极版”,将所有变化(包括新文件、修改、删除)都添加到暂存区。可以看作是git add .和git add -u的合集。
- 作用:
git add -p或git add --patch- 作用: 交互式添加。Git 会逐一展示文件中每一块(hunk)的修改,然后询问你是否要将这一块修改添加到暂存区。
- 交互选项: 你会看到
Stage this hunk [y,n,q,a,d,s,e,?]?y: 暂存这个代码块n: 不暂存这个代码块s: 将这个代码块拆分成更小的块,进行更精细的选择e: 手动编辑这个代码块q: 退出交互模式
- 场景: 这是创建清晰、原子化提交的神器。比如你在一个文件里同时修复了一个 Bug 并做了一些代码格式化,你可以通过
git add -p只把修复 Bug 的那几行代码添加到暂存区并提交,然后再进行下一次提交。
git commit创建提交
基本用法: git commit -m "Your concise message"
将暂存区的内容创建一个新的提交,并附上一句简短的说明。
常用变形与拓展:
git commit(不带m)- 作用: Git 会自动打开你配置的默认文本编辑器(如 Vim, Nano, VS Code),让你输入一个完整格式的提交信息。
- 格式规范: 通常是第一行写一个不超过50个字符的简短摘要,然后空一行,再写详细的描述。
- 场景: 对于比较重要的修改,一句话说不清楚,需要详细解释“为什么这么改”以及“带来了什么影响”。这是编写高质量提交信息的标准做法。
git commit -a -m "Message"或git commit --all -m "Message"- 作用: 一个快捷方式,它会跳过
git add步骤,直接将所有已被跟踪的文件(不包括新文件)的修改进行提交。相当于git add -u和git commit -m的组合。 - 注意: 这个命令很方便,但也存在风险,因为它可能会将你不想提交的修改也一并提交了。建议在确认所有修改都无误的小型提交中使用。
- 作用: 一个快捷方式,它会跳过
git commit --amend- 作用: 修改你最后一次的提交。这是一个非常有用的“后悔药”。
- 场景:
- 修改提交信息: 刚提交完发现消息里有错别字,运行
git commit --amend会打开编辑器让你重新编辑上次的提交信息。 - 补充文件: 刚提交完发现漏掉了一个文件,可以先
git add [missed_file],然后运行git commit --amend --no-edit。-no-edit选项表示沿用上一次的提交信息,只把新暂存的文件添加进去。
- 修改提交信息: 刚提交完发现消息里有错别字,运行
- 黄金法则: 绝对不要对已经推送到共享远程仓库的提交使用
-amend,因为它会重写历史,给协作者带来麻烦。只在你的本地修改时使用。
git commit -v或git commit --verbose- 作用: 在打开的编辑器中,除了让你填写提交信息外,还会将本次提交的具体代码差异(diff)显示在下方(作为注释)。
- 场景: 当你准备编写详细的提交信息时,可以直接在编辑器里看到所有代码改动,帮助你写出更准确的描述,而无需切回命令行再用
git diff查看。
补充:本地文件管理命令:rm和mv
与核心工作流紧密相关的还有两个命令:删除文件、移动/重命名文件,它们是 Git 推荐的文件操作方式:
git rm [file]: 从工作区和暂存区同时删除一个文件。它相当于rm [file]+git add [file]。- 变形:
git rm --cached [file]是一个非常重要的命令,它只从暂存区删除文件,但保留工作区的文件。 - 场景: 你不小心把一个日志文件或者包含密码的配置文件
add甚至commit了。你想让 Git 不再跟踪它,但又不想删除这个文件本身。这时用git rm --cached [file],然后再把文件名加入.gitignore,就完美解决了问题。
- 变形:
git mv [old_name] [new_name]: 用 Git 的方式移动或重命名文件。它相当于mv [old] [new]+git rm [old]+git add [new]。
通过掌握这些变形,你可以将这一套核心工作流玩得非常熟练,极大地提升代码管理的质量和效率。
分支管理 (Branching)
- 目的:在不影响主线(通常是
master或main分支)的情况下,进行新功能开发或Bug修复。这是 Git 实现并行开发、保持主线稳定的核心功能。 - 分支管理是 Git 的精髓所在,它让并行开发、功能实验和 Bug 修复变得安全和高效。因此,这个模块下的命令有着极其重要和强大的拓展,理解它们是从 Git 新手迈向高手的关键一步。下面我们来拆解“分支管理”分类下命令的基本用法和常用拓展。
git branch列出/创建/跟踪/删除分支等
基本用法:
git branch: 列出所有本地分支。git branch [branch-name]: 基于当前 commit 创建一个新分支,但不切换过去。
常用变形与拓展:
git branch -v或vv:- 作用: 显示更详细的信息 (
-verbose)。 v: 显示每个分支的最后一个 commit 的哈希值和提交信息。vv: 非常有用! 在v的基础上,还会显示每个分支的上游跟踪分支信息(如果有的话),以及领先/落后情况。- 输出示例:
my-feature 2a4b6c1 [origin/my-feature: ahead 1] Add new button - 场景: 快速查看所有分支的最新进展以及它们与远程仓库的同步状态。
- 作用: 显示更详细的信息 (
git branch -r(-remotes):- 作用: 只列出所有远程跟踪分支(例如
origin/main,origin/feature-x)。 - 场景: 你想看看远程仓库上都有哪些分支,以便决定接下来要
pull或checkout哪个。
- 作用: 只列出所有远程跟踪分支(例如
git branch -a(-all):- 作用: 列出所有本地分支和远程跟踪分支。
- 场景: 获取项目所有分支的“全景图”。
git branch -d [branch-name](-delete):- 作用: 删除一个已经完全合并到当前分支的分支。这是一个安全操作,如果分支上有没有被合并的修改,Git 会阻止你删除。
- 场景: 功能开发完成并合并到主线后,清理掉无用的功能分支。
git branch -D [branch-name]:- 作用: 强制删除一个分支,无论它是否已被合并。
- 场景: 你在一个分支上的开发工作半途而废,确定这些代码完全没用了,需要彻底清除这个分支。请谨慎使用!
git branch -m [old-name] [new-name](-move):- 作用: 重命名一个分支。如果省略
[old-name],则重命名当前所在的分支。 - 场景: 分支名有拼写错误,或者想根据团队规范更新分支命名。
- 作用: 重命名一个分支。如果省略
git branch --merged/-no-merged:- 作用: 非常实用的筛选命令。
-merged: 显示所有已经合并到当前分支的分支列表。这些通常是可以安全删除的。-no-merged: 显示所有尚未合并到当前分支的分支列表。这些分支上包含独立的工作。
- 场景: 定期进行项目维护,使用
git branch --merged | xargs git branch -d命令可以批量清理所有已合并的本地分支。
- 作用: 非常实用的筛选命令。
git switch / git checkout(切换分支)
说明: git checkout 是一个功能非常庞杂的旧命令,既能切换分支,又能恢复文件。为了清晰,Git 在 2.23 版本中引入了 git switch (专用于切换分支) 和 git restore (专用于恢复文件)。推荐使用新命令,但 checkout 仍然通用。
基本用法:
git switch [branch-name]: 切换到已存在的指定分支。git checkout [branch-name]: 同样是切换分支。
常用变形与拓展:
git switch -c [new-branch-name](-create):- 作用: 创建一个新分支并立即切换过去。这是一个原子操作。
- 旧命令:
git checkout -b [new-branch-name] - 场景: 这是开始新功能开发最常用的命令。 例如:
git switch -c feature/user-login。
git switch -:- 作用: 一个超级方便的快捷键,用于在当前分支和上一个分支之间来回切换。
- 旧命令:
git checkout - - 场景: 你正在
feature分支写代码,需要频繁切回main分支查看或合并最新代码,这个命令能极大提升效率。
git switch --track origin/[branch-name]:- 作用: 在本地创建一个新分支,并设置它跟踪一个同名的远程分支。
- 场景: 你的同事创建了一个
feature/api-docs分支并推送到了远程。你想在本地基于这个分支工作,就可以运行git switch --track origin/feature-api-docs。通常,如果本地不存在同名分支,git switch feature/api-docs也能智能地完成这个操作。
git merge合并分支
基本用法: git merge [branch-to-merge-in]
将指定分支的更改合并到当前所在的分支。
常用变形与拓展:
- 理解两种合并方式: Git Merge 主要有两种模式,Git 会自动选择。
- Fast-Forward (快进合并): 如果你的当前分支没有任何新的提交,而目标分支在你的基础上前进了一步。Git 只会简单地将你的分支指针“快进”到目标分支的最新状态。历史记录是一条直线。
- Three-Way Merge (三方合并): 如果两个分支都各自有了新的提交(历史分叉了),Git 会找到它们的共同祖先,然后将两边的修改合并起来,并创建一个新的“合并提交” (Merge Commit)。历史记录上会看到一个分叉和汇合的“钻石”形状。
git merge --no-ff(-no-fast-forward):- 作用: 禁用 Fast-Forward 模式,强制 Git 总是创建一个新的“合并提交”,即使快进合并是可能的。
- 场景: 这是一个非常流行的策略。它能清晰地在提交历史中标记出“某个功能分支在此处被合并进来”,即使它技术上可以被快进。这样能保持功能开发的脉络清晰可追溯,让
git log --graph的输出更有意义。
git merge --squash:- 作用: 将目标分支上的所有提交“压扁”成一个变更集,然后放入当前分支的暂存区。它不会自动创建提交。
- 流程: 运行
git merge --squash feature-branch后,你需要接着运行git commit来手动创建一个提交。 - 场景: 你的功能分支上有10个零碎的提交(如 “修复拼写”、”WIP”、”再试一次”)。你不想让这些杂乱无章的历史污染主分支。使用
-squash可以将这个功能的所有代码改动,作为一个干净、完整的提交合入主分支。
git merge --abort:- 作用: 撤销/中止一次失败的合并。
- 场景: 你在合并时遇到了大量的冲突(Conflicts),你觉得很棘手,想先放弃合并,让工作区回到合并之前的状态。
git merge --abort就是你的“救生筏”。
git merge -X[strategy-option]:- 作用: 为合并策略提供额外的选项,用于处理冲突。
- 场景:
git merge -Xignore-all-space或git merge -Xignore-space-change可以在解决冲突时忽略所有空白字符(空格、换行)的差异,有时能自动解决一些因为格式化工具导致的“伪冲突”。
通过这些拓展,你可以像一位“代码时空管理员”一样,精确地控制项目的历史脉络,实现整洁、可追溯且高效的团队协作。
远程协作 (Collaboration & Remote)
- 目的:将你的本地代码与团队成员共享,或获取团队成员的最新代码。
- 毫无疑问!远程协作是 Git 作为分布式版本控制系统的核心价值所在,因此围绕这个主题的命令提供了大量强大且精细的拓展,以应对各种团队协作场景。下面我们来深入探索它们的基础用法和变形。
git remote列出/添加/修改/显示/删除分支
基本用法:
git remote: 列出你配置的远程仓库的简称(通常是origin)。git remote -v: 列出简称和对应的 URL。
常用变形与拓展:
git remote add [name] [url]:- 作用: 添加一个新的远程仓库连接。
- 场景: 最经典的场景是参与开源项目。你
fork了一个项目到自己的 GitHub,然后clone到本地,这时你的origin指向你自己的 fork。为了能同步原作者的更新,你需要添加原项目仓库作为另一个远程连接,通常命名为upstream。 - 示例:
git remote add upstream https://github.com/original-author/project.git
git remote set-url [name] [new_url]:- 作用: 修改一个已存在的远程仓库的 URL。
- 场景:
- 项目迁移,仓库地址换了。
- 从 HTTPS 切换到 SSH 协议以使用密钥认证,免去每次输入密码。
- 示例:
git remote set-url origin git@github.com:user/repo.git
- 示例:
- 从A仓库转到B仓库(https://github.com/mingnify/my-deepwiki-open)
- 示例:
git remote set-url origin https://github.com/mingnify/my-deepwiki-open.git
- 示例:
git remote show [name]:- 作用: 显示一个远程仓库的详细信息。
- 信息包括: Fetch 和 Push 的 URL、远程仓库的 HEAD 分支(默认分支)、远程跟踪分支的状况、以及本地分支与远程分支的跟踪关系。
- 场景: 一个非常有用的诊断工具。当你对一个远程连接的状态感到困惑时,用
git remote show origin可以获得非常全面的信息。
git remote remove [name]或git remote rm [name]- 作用: 删除一个远程仓库的连接。
- 场景:
upstream项目已经不再维护,或者你想清理掉一个无效的远程连接。
git fetch下载分支
基本用法: git fetch [remote_name] (e.g., git fetch origin)
从远程仓库下载最新的对象(commits, files, tags),并更新你的远程跟踪分支(如 origin/main)。
核心概念: fetch 是一个绝对安全的操作。它只更新你本地的“远程数据快照”,不会以任何方式修改你的本地工作分支(如 main),也不会碰你的工作区。它让你有机会在合并前先查看远程的变动 (git log origin/main)。
常用变形与拓展:
git fetch --prune或p:- 作用: 在抓取前,修剪/清理掉那些在本地存在、但远程仓库上已经被删除了的远程跟踪分支。
- 场景: 这是保持仓库整洁的必备命令。你的同事合并并删除了一个功能分支
feature/login,在你的本地git branch -r列表中可能还留着origin/feature/login。-prune会帮你清理掉这些“幽灵”分支。 - 专业提示: 很多人会设置
git config --global fetch.prune true,让每次fetch都自动执行修剪。
git fetch --all:- 作用: 从所有配置的远程仓库(如
origin,upstream等)抓取更新。 - 场景: 当你需要同时与自己的 fork 和上游的官方仓库保持同步时,这个命令可以一次性更新所有远程信息。
- 作用: 从所有配置的远程仓库(如
git fetch [remote_name] [branch_name]:- 作用: 只从指定的远程仓库抓取一个特定的分支。
- 场景: 你只关心某个特定功能分支的更新,不想下载其他所有分支的变动,这样可以节省时间和带宽。
git pull拉取分支
基本用法: git pull [remote_name] [branch_name] (e.g., git pull origin main)
抓取远程更新并立即尝试合并到你当前的本地分支。
核心概念: git pull 本质上是两个命令的快捷方式:git fetch + git merge。理解这一点是关键,因为它解释了为什么 pull 有时会产生合并冲突或创建一个合并提交。
常用变形与拓展:
git pull --rebase:- 作用: 使用
rebase(变基)代替merge来整合远程变更。 - 流程: 它执行
git fetch,然后不是用merge,而是用git rebase。它会把你本地尚未推送的提交“摘下来”,然后将远程的最新提交应用到你的分支,最后再把你本地的提交“重新播放”在最顶端。 - 结果对比:
pull(默认 merge): 会在历史记录中产生一个“Merge”提交,形成分叉再汇合的图形。pull --rebase: 不会产生合并提交,能保持提交历史是一条干净的直线。
- 场景: 很多团队强制使用
-rebase来维持一个清爽、线性的提交历史。这是目前非常流行的协作策略。你可以通过git config --global pull.rebase true把它设为默认行为。
- 作用: 使用
git pull --prune:- 作用: 和
fetch一样,在拉取前先修剪远程已删除的分支。
- 作用: 和
git push提交分支
基本用法: git push [remote_name] [branch_name] (e.g., git push origin main)
将你的本地分支的提交上传到远程仓库。
常用变形与拓展:
git push -u [remote_name] [branch_name](-set-upstream):- 作用: 在推送的同时,建立本地分支与远程分支的跟踪关系。
- 场景: 当你第一次推送一个在本地创建的新分支时,必须使用
u。设置好之后,未来在这个分支上工作时,你就可以简单地使用git push和git pull,Git 会自动知道该推送到哪里、从哪里拉取。
git push --force:- 作用: 强制推送。它会用你本地的分支状态粗暴地覆盖远程分支,忽略远程仓库上可能有的、你本地没有的任何新提交。
- 警告: 这是一个危险的操作,尤其是在共享分支(如
main)上,因为它会销毁其他人的提交。只在你非常确定自己在做什么时使用(例如,修复一次错误的私有分支推送)。
git push --force-with-lease:- 作用: 更安全的强制推送。这是
-force的绝佳替代品。 - 工作原理: 它在推送前会检查一下:远程分支的状态是否和你上次
fetch时一样。如果期间有其他人推送了新的提交,-force-with-lease会拒绝推送,从而避免覆盖他人的工作。如果远程没有变化,它才会执行强制推送。 - 场景: 当你因为
rebase本地分支而需要强制推送时,永远优先使用-force-with-lease。
- 作用: 更安全的强制推送。这是
git push [remote_name] --delete [branch_name]:- 作用: 删除一个远程分支。
- 旧语法:
git push [remote_name] :[branch_name](冒号前为空,表示推送一个“空”到远程分支,即删除它)。两个命令效果一样。
git push --tags:- 作用: 将你本地创建的所有标签(tags)推送到远程仓库。默认情况下,
git push并不会推送标签。 - 场景: 当你完成一个版本发布(如
v1.0.0),打好标签后,需要用这个命令将版本标记共享给团队。
- 作用: 将你本地创建的所有标签(tags)推送到远程仓库。默认情况下,
掌握这些远程命令的拓展,你就能自信地处理复杂的团队协作流程,无论是维护清晰的历史,还是安全地修复错误,都游刃有余。
历史记录与审查 (History & Inspection)
- 目的:查看项目的演变历史,对比不同版本之间的差异。
- 当然,历史记录与审查是 Git 的“侦探工具箱”,这个工具箱里的命令拥有海量的拓展选项,能让你像使用数据库查询语言一样,精准地挖掘和分析项目的全部历史。
- 下面我们来深入探索
git log和git diff这两个核心审查命令的强大变形。
git log显示提交历史
基本用法: git log
按时间倒序显示所有提交历史,信息比较完整。
git log 的拓展主要分为两大类:格式化输出(让信息更美观易读)和筛选过滤(只看你想看的信息)。
格式化输出 (Formatting)
git log --oneline:- 作用: 将每次提交压缩到一行显示,只包含 commit 哈希值和提交标题。
- 场景: 快速浏览最近的提交历史,对项目的演进有一个宏观的了解。
git log --graph:- 作用: 在输出的左侧用 ASCII 字符绘制出分支与合并的图形化历史。
- 场景: 这是理解项目分支结构和合并历史的最直观方式。
git log --decorate:- 作用: 在提交记录旁显示指向该提交的所有引用(如分支名、标签名
HEAD等)。 - 场景: 清楚地看到
main分支、feature分支、v1.0标签等分别指向哪个提交。
- 作用: 在提交记录旁显示指向该提交的所有引用(如分支名、标签名
- 组合使用:****
git log --oneline --graph --decorate:- 作用: 这是最常用、最强大的日志查看命令之一,它以紧凑、图形化、信息丰富的方式展示了提交历史。强烈建议为它设置一个别名,例如
git lg。
- 作用: 这是最常用、最强大的日志查看命令之一,它以紧凑、图形化、信息丰富的方式展示了提交历史。强烈建议为它设置一个别名,例如
git log -p或-patch:- 作用: 在显示每次提交信息的同时,附带上该次提交的具体代码变更差异 (diff)。
- 场景: 你想详细审查某几次提交到底修改了什么代码。
筛选过滤 (Filtering)
- 按数量:
git log -n <number>或git log -<number>(e.g.,git log -5): 只显示最近的n次提交。
- 按时间:
git log --since="2 weeks ago"(或-after="2025-06-20"): 显示指定时间点之后的提交。git log --until="yesterday"(或-before="2025-07-01"): 显示指定时间点之前的提交。- 场景: 查看本周或某个时间段内团队的所有工作。
- 按作者/提交者:
git log --author="John Doe": 只显示指定作者的提交。git log --committer="Jane Smith": 只显示指定提交者的提交(在rebase或cherry-pick时作者和提交者可能不同)。- 场景: 查看某个成员的所有提交记录,进行 Code Review 或绩效评估。
- 按提交信息:
git log --grep="fix: login bug": 筛选出提交信息中包含指定字符串的提交。- 场景: 查找所有与修复“登录bug”相关的提交。
- 按文件/路径:
git log -- <file_path>: 只显示修改过指定文件或路径的提交历史。双破折号-是为了将文件名和分支名等引用明确分开。- 场景: 查看某个特定文件的“前世今生”,了解它的所有变更历史。
- 按代码内容 (Pickaxe):
git log -S"functionName": 超级强大的功能! 筛选出那些新增或删除了包含指定字符串的代码的提交。它不关心提交信息,只关心代码内容本身。- 场景: 查找是哪个提交引入或删除了对某个特定函数
functionName的调用。
- 按范围:
git log <branch1>..<branch2>: 显示在branch2中存在,但在branch1中不存在的提交。git log main..feature/login: 查看feature/login分支相比main分支多出了哪些提交。- 场景: 在合并分支前,预览将要合并过来哪些新的提交。
git diff显示工作/暂存区差异
基本用法: git diff
显示工作区和暂存区之间的差异。
git diff 的强大之处在于它可以对比 Git 中任意两个点之间的代码差异。
常用变形与拓展:
git diff --staged或-cached:- 作用: 显示暂存区和上一次提交 (HEAD) 之间的差异。
- 场景: 在
git commit之前,最后检查一下你准备提交的内容(即已经git add的内容)是否准确无误。
git diff HEAD:- 作用: 显示工作区+暂存区和上一次提交之间的所有差异。
- 场景: 查看从上次提交到现在,你总共做了哪些修改,无论是否已暂存。
git diff [branch1]..[branch2]:- 作用: 比较两个分支最新提交 (tip) 之间的差异。
- 场景: 查看
develop分支和main分支的代码内容有哪些不同,为合并做准备。
git diff [commit1]..[commit2]:- 作用: 比较任意两次提交之间的差异。
- 场景: 你发现某个功能在版本
v1.1中出错了,但在v1.0中是好的。使用git diff v1.0..v1.1可以精确地看到这两个版本之间所有的代码改动,帮助你定位问题。
git diff --stat:- 作用: 不显示详细的代码差异,而是显示一个变更统计,列出哪些文件被修改了,以及每个文件增删的行数。
- 场景: 当变更文件很多时,先用
-stat宏观地看一下变更范围,再针对特定文件进行详细diff。
git diff --color-words:- 作用: 进行词级 (word-level) 而不是行级 (line-level) 的比较。它会高亮显示一行中具体是哪个单词发生了变化。
- 场景: 当你只是修改了一行中的一个变量名或修正了一个拼写错误时,这个模式能让你更清晰地看到微小变动。
通过组合使用这些命令和选项,你可以构建出非常强大的审查工作流,无论是调试 Bug、理解代码演进,还是进行代码审查 (Code Review),都将变得得心应手。Git 的历史不仅仅是备份,更是一个内容丰富、可供深入挖掘的知识库。
撤销与修复 (Undoing & Fixing)
- 目的:当你犯了错误,需要“反悔”或修改历史时使用。
- “撤销与修复”模块是 Git 中最能体现其“时空穿梭机”能力的部分,也是新手最容易感到困惑的地方。这个模块下的命令不仅有丰富的拓展,理解它们之间的核心区别至关重要。
- 最大的区别在于:有些命令会重写历史(对本地私有工作很方便,但对共享历史有风险),而另一些命令则通过创建新的历史来“撤销”过去(对共享历史是安全的)。
- 下面我们来深入拆解这个“后悔药”工具箱。
git restore撤销工作/暂存区修改
核心思想: 这是 Git 2.23 版本后推出的新命令,专门用于撤销工作区和暂存区的修改,它不触及提交历史,因此非常安全。它是对 git checkout 和 git reset 部分旧功能的清晰替代。
基本用法:
git restore [file]: 丢弃工作区中某个文件的修改,将其恢复成和暂存区一致的状态。如果该文件未被暂存,则恢复成和上一次提交 (HEAD) 一致的状态。
常用变形与拓展:
git restore --staged [file]:- 作用: “取消暂存”。将一个已经
git add到暂存区的文件移出暂存区,但保留工作区的修改。 - 旧命令:
git reset HEAD [file](这个老命令因为reset这个词有歧义,所以不推荐了)。 - 场景: 你
git add .的时候不小心把一个不想提交的文件加进去了,用这个命令可以把它“捞”出来。
- 作用: “取消暂存”。将一个已经
git restore --source=[commit|branch] [file]:- 作用: 从指定的某个历史提交或分支中拉取文件,并用它覆盖工作区和暂存区中的版本。
- 场景: 你知道
feature分支上的config.js文件是好的,想用它来覆盖当前分支上被改坏的版本,就可以运行git restore --source=feature config.js。这就像一个定向的文件“时空穿梭”。
git revert新提交覆盖旧提交
核心思想: 这是最安全的“撤销提交”方式,尤其适用于共享分支。它不会删除或修改旧的提交,而是创建一个全新的提交,其内容与要撤销的提交完全相反。
基本用法: git revert [commit-hash]
创建一个新提交,用来抵消指定 commit 所做的所有更改。
常用变形与拓展:
git revert HEAD: 撤销最近的一次提交。git revert [commit1]..[commit2]:- 作用: 撤销一个连续的提交范围(不包括
commit1,但包括commit2)。Git 会为这个范围内的每一次提交都尝试创建一个对应的撤销提交。 - 场景: 一个功能分支合并进来后发现有严重问题,需要撤销整个分支的所有提交。
- 作用: 撤销一个连续的提交范围(不包括
git revert -n或-no-commit:- 作用: 只执行撤销的动作(即在工作区和暂存区应用相反的更改),但不自动创建那个新的“撤销提交”。
- 场景:
- 你想一次性撤销多个不连续的提交,然后将这些撤销的更改合并成一个“撤销提交”。你可以对每个目标提交都运行
git revert -n,最后再手动git commit。 - 在提交前,你想先审查或修改一下撤销操作所带来的代码变动。
- 你想一次性撤销多个不连续的提交,然后将这些撤销的更改合并成一个“撤销提交”。你可以对每个目标提交都运行
git reset重置
核心思想: 这是一个非常强大但有潜在危险的命令。它的本质是移动 HEAD 指针,让它指向某个历史提交,从而达到“重置”或“撤销”的目的。它会重写历史,因此绝对不要在已经推送到共享分支的提交上使用它。
reset 最重要的拓展是它的三个模式 (--soft, --mixed, --hard),它们决定了在移动 HEAD 指针后,对暂存区和工作区做什么。
基本用法: git reset [commit-hash]
三大模式:
git reset --soft [commit]:- 作用: 最温柔的重置。只移动
HEAD指针到指定的提交。暂存区和工作区的内容完全不变。 - 效果: 所有在
[commit]之后提交的更改,现在都变成了“已暂存”状态。 - 场景: 你刚刚提交了 3 次,但觉得这 3 次提交应该合并成一个。你可以运行
git reset --soft HEAD~3,这样你的 HEAD 回到了 3 次提交之前,但所有的代码改动都已在暂存区,你只需运行一次git commit就可以把它们合并成一个干净的提交。
- 作用: 最温柔的重置。只移动
git reset --mixed [commit](这是默认模式):- 作用: 移动
HEAD指针,并清空暂存区。工作区内容不变。 - 效果: 所有在
[commit]之后提交的更改,现在都变成了“未暂存”的本地修改状态。 - 场景: 你最近的几次提交很混乱,你想撤销这几次提交记录,但保留所有的代码修改,然后重新整理、重新
add和commit。
- 作用: 移动
git reset --hard [commit]:- 作用: 最彻底的重置,威力巨大。移动
HEAD指针,同时清空暂存区,并用目标提交的状态覆盖工作区。 - 效果: 所有在
[commit]之后提交的更改全部被永久丢弃。你的代码文件会真的变回[commit]时的样子。 - 场景: 你发现最近的几次提交完全是错误的,代码和思路都有问题,你只想彻底回到某个干净的历史节点,丢弃之后的所有工作。使用前请三思!
- 作用: 最彻底的重置,威力巨大。移动
总结:何时使用哪个命令?
| 你的意图 | 使用的命令 | 影响范围 | 是否重写历史? | 安全性 |
|---|---|---|---|---|
| 丢弃工作区的本地修改 | git restore [file] |
工作区 | 否 | 非常安全 |
| 取消暂存某个文件 | git restore --staged [file] |
暂存区 | 否 | 非常安全 |
| 撤销一个已推送的共享提交 | git revert [commit] |
创建新提交 | 否 (追加历史) | 团队协作安全 |
| 合并最近的几个私有提交 | git reset --soft HEAD~n |
本地历史, 暂存区 | 是 | 仅限本地 |
| 撤销最近的私有提交,但保留代码修改 | git reset --mixed HEAD~n |
本地历史, 暂存区, 工作区 | 是 | 仅限本地 |
| 彻底销毁最近的私有提交和所有修改 | git reset --hard HEAD~n |
本地历史, 暂存区, 工作区 | 是 | 危险,仅限本地 |
| 修改最后一次私有提交的信息或内容 | git commit --amend |
本地历史 | 是 | 仅限本地 |
理解这个表格,你就掌握了 Git “后悔药”的精髓,能够从容应对各种“翻车”现场。
学习路径
- 第一步:掌握本地核心工作流
- 重点练习
init,status,add,commit。这是你每天都要用的循环。理解工作区和暂存区的概念是关键。
- 重点练习
- 第二步:学习分支管理
- 练习
branch,switch,merge。尝试创建一个新功能分支,做一些修改和提交,然后合并回主分支。
- 练习
- 第三步:融入远程协作
- 在 GitHub 或 Gitee 上创建一个仓库,练习
clone,pull,push。模拟与他人协作的流程。
- 在 GitHub 或 Gitee 上创建一个仓库,练习
- 第四步:学会查看历史和撤销操作
- 当你熟悉了基本流程后,再学习
log,diff,reset,revert。这些命令能让你在出问题时从容应对。
- 当你熟悉了基本流程后,再学习
记住,多用 git status和git --help。它会是你最好的向导。
git命令清单
待更新





