系统梳理了 Git 的核心命令体系 ,重点包括:基础操作命令(add、commit、status 等)、分支管理(merge vs rebase 的选择)、远程协作(fetch/pull/push 的典型流程)、以及撤销与恢复(reset/revert/stash 的适用场景)。其中特别针对 merge vs rebase、reset vs revert、fetch vs pull 等易混淆命令,给出了明确的区分原则和选择依据
1.配置全局用户名和邮箱
配置用户名和邮箱,用于代码提交的署名
git
git config --global user.name
git config --global "你的邮箱@example.com"
配置好用户名和邮箱之后,可以通过git config --list 查看对应配置信息 
2.设置远程仓库地址以及分支
git
git remote add origin "远程仓库地址" //添加远程仓库地址并且用origin来代替该地址
git branch -M main //设置本地仓库的分支为main
常见误区:
git remote add origin 和 git branch -M main 并不会 在本地 main 分支和远程 main 分支之间建立跟踪关系(upstream)。它们各自的作用如下:
| 命令 | 实际作用 | 是否建立分支跟踪 |
|---|---|---|
git remote add origin <url> |
给远程仓库起一个别名 origin,并记录其地址。相当于告诉 Git:"以后我用 origin 代替这个长长的 URL"。 |
❌ 否。只是定义了远程仓库的存在,和分支无关。 |
git branch -M main |
将当前分支(比如 master)强制重命名为 main。 |
❌ 否。只是改了本地分支的名字,完全不涉及远程。 |

3.初始化 Git 仓库
在指定的项目文件下,使用以下命令初始化git仓库
git
git init

4.提交暂存区
将目录下指定文件放入本地git暂存区,在执行commit命令之前会一直保存,一旦执行commit命令之后就会清除当前暂存区记录
git
git add "08. ai_partner_6.py"
5.提交记录到版本库
git
git commit -m "提交说明"

6.查看git提交状态
当前工作目录和暂存区相对于最近一次提交(HEAD)有哪些变化(比如修改了哪些文件、新增了哪些文件、删除了哪些文件)
例如新增了一个文件,就会显示new file记录,修改了一个文件内容就会显示modified记录
git
git status

7.查看提交历史记录
每次执行 git commit 才会产生一条新的提交记录
git
git log

8.提交暂存区记录到远程仓库
首次推送(-u 设置上游,以后可直接 git push)
git
git push -u origin main

最终在github上对应仓库的分支下显示提交的文件信息 
其他操作命令
git log
查看提交历史
js
git log
执行git commit命令之后,提交记录就会显示在这里

js
git log --oneline
简洁一行显示

js
git log --graph --all
图形化显示分支历史 
git diff
查看工作区与暂存区、暂存区与 HEAD(也可以是其他的分支比如main,master等)、工作区与 HEAD 之间的文件内容差异
查看工作区与暂存区
js
git diff
如图中,#创建OpenAI客户端这个记录是暂存区中的记录,下方则是工作区最新的记录,当暂存区记录和工作区记录都是最新记录,结果就会显示为空 
js
git diff --staged
最近一次提交,也就是上一次 git commit 时的项目快照和执行 git add 之后暂存区里保存的版本的对比

js
git diff HEAD
最近的一次git commit提交记录和工作区记录

分支管理
git branch
列出、创建或删除分支。
js
git branch
列出本地分支 
js
git branch 分支名
创建一个新的分支,当前处在main分支 
js
git branch -d 分支名
删除分支 
git switch
切换分支
js
git switch 分支名
切换到指定分支 如图,切换到了feature分支,通过git branch命令可以查看到当前分支前有*号标识 
js
git switch -c 分支名
创建分支并切换 如图,创建了一个other分支,并且切换到了other分支 
git merge
将指定分支合并到当前分支(生成一个合并提交) 例如,有个test.file文件,文件内容原本有"测试使用111",并且当前分支是在master

现在切换到main分支,并且写入一段内容,然后提交修改


bash
git add test.txt & git commit -m "change on main"
由于没有合并分支,所以当切换到master目录下之后,再查看test.txt,显示的还是"测试使用111"

执行合并 将main分支合并到master分支,合并之后再切换到master分支下,内容就变成"change on main"了
bash
git merge main


git rebase
将当前分支的提交复制到另一个分支的最新提交之后,形成一条直线历史,不产生合并提交
- 环境准备
bash
cd /tmp
mkdir git-rebase-demo2
cd git-rebase-demo2
git init
master分支上创建初始提交
bash
echo "v1" > file.txt
git add file.txt
git commit -m "C0: initial commit on master"

- 创建并切换到
feature分支,做两次提交
bash
git checkout -b feature
# 第一次提交
echo "v2 from feature" >> file.txt
git add file.txt
git commit -m "C1: feature commit 1"
# 第二次提交
echo "v3 from feature" >> file.txt
git add file.txt
git commit -m "C2: feature commit 2"

- 切换回
main,新增两个提交(制造分叉)
bash
git checkout main
# 第一个新提交
echo "v4 from main" >> file.txt # 注意:还在同一个文件 file.txt
git add file.txt
git commit -m "C3: main commit 1"
# 第二个新提交
echo "v5 from main" >> file.txt
git add file.txt
git commit -m "C4: main commit 2"

此时 master 上有 C3、C4,file.txt 内容为:
bash
v1
v4 from master
v5 from master
而 feature 上的 file.txt 内容为:
bash
v1
v2 from feature
v3 from feature
通过git log命令查看分支记录,可以看到,master和feature记录从C0处分叉了

- 在
feature上执行git rebase main
bash
git switch feature
git rebase master
由于两个分支都修改了文件的同一块区域,系统不知道应该合并哪个部分,从而导致冲突发生
系统提示,不能将C1的提交合并进来,此时,就需要人为处理该冲突,调整冲突部分
冲突后,文件显示的内容 
bash
# 编辑 file.txt,手工合并内容,比如最终想要:
# v1
# v4 from master
# v5 from master
# v2 from feature
# v3 from feature
执行git add file.txt解决冲突,然后继续合并git rebase --continue,如果继续出现冲突,重复此步骤即可

此时可以看到,分支记录被合并成线性记录了

与git merge区别
- 本质区别:历史是"分叉"还是"直线"
git merge |
git rebase |
|
|---|---|---|
| 历史形状 | 保留分叉,能看到分支从哪里来、何时合并 | 拉直成一条线,看不出曾经有并行开发 |
| 是否产生合并提交 | 是(非 fast‑forward 时) | 否(但会创建新的提交副本) |
| 冲突解决次数 | 一次(合并时) | 可能多次(每个重放的提交都可能冲突) |
| 对已推送分支的影响 | 安全,不需要强制推送 | 改写历史,需要 --force,影响协作者 |
场景1:排查 bug(git bisect 或手动查找)
- merge 历史:你能看到分支的并行开发轨迹,容易定位某个功能是何时从哪个分支合并进来的。
- rebase 历史:所有提交排成一条线,你无法判断哪些提交原本属于同一个特性分支,回溯时可能丢失上下文。
场景2:团队协作
- merge:多人从同一主分支拉出特性分支,完成后合并回去。每个人都可以随时 pull 并 merge,不会改写他人历史,安全简单。
- rebase :如果你 rebase 了一个已经推送到远程的分支,其他人基于旧历史工作,再拉取时会出现大量重复提交和冲突,团队协作会变得非常痛苦。所以 rebase 一般只用于本地未推送的分支。
场景3:代码审查(PR/MR)
- merge:PR 页面会清晰显示"合并提交",你可以看到所有特性分支上的提交。
- rebase:PR 历史是一条直线,看起来像是直接在主分支上开发,有时会让审查者困惑"这个分支到底改了什么"。
那为什么还要用 rebase?
- 追求线性历史 :有些项目(尤其是开源项目)希望主分支历史非常干净,没有多余的合并提交。
rebase可以让每次 PR 以"一组有序的补丁"形式合入。 - 避免"分叉污染" :如果每个小特性都产生一个合并提交,主分支历史会变得杂乱。
rebase可以消除那些无意义的 merge commit。
常用 rebase 拉取上游最新代码
bash
git pull --rebase
注意:如果本地工作区或暂存区有未提交的变更,需要先提交之后才能执行以上命令,否则会导致这些改动丢失
-
从远程拉取最新提交 (
git fetch)- 将远程分支(如
origin/main)的最新提交下载到本地的远程跟踪分支(origin/main)。
- 将远程分支(如
-
将本地当前分支的未推送提交"变基"到远程跟踪分支的最新提交上 (
git rebase origin/main)- 这个过程完全在本地进行:Git 会把本地提交临时拿出来,然后放到
origin/main指向的提交之后,生成新的提交哈希。
- 这个过程完全在本地进行:Git 会把本地提交临时拿出来,然后放到
结论:整个流程不直接在远程创建或修改任何东西,只是利用远程的数据在本地改写历史。
- 举例:
想象你和同事在跑接力赛,跑道上有多个接力点(每个接力点就是一个"提交")。
- 远程仓库:裁判手里拿着的正式成绩单。
- 本地仓库:你自己记的小本本。
正常情况(没分叉)
你和裁判的成绩单一致:第1棒 → 第2棒。你接着跑了第3棒,记在小本本上。这时裁判又更新了第2棒的成绩(同事跑快了)。你需要把你的第3棒"接到"裁判最新的第2棒后面。
git pull --rebase 就是做这件事:
- 先看裁判的最新成绩 (
git fetch):哦,裁判的第2棒已经不是原来的了。 - 把你自己的第3棒暂时拿在手里。
- 把小本本上的记录改成裁判的最新顺序 :
第1棒 → 裁判的新第2棒 → 你的第3棒。 - 把你的第3棒重新抄到后面(可能会和裁判的第2棒有冲突,需要你手动调整)。
整个过程只改你小本本上的记录,裁判手里的成绩单完全没动。
远程协作
git remote
管理远程仓库的别名和地址。
js
git remote -v
查看所有的远程仓库
添加远程仓库并命名为(别名)
js
git remote add (远程地址别名) 远程地址
删除名为 xxx 的远程
js
git remote rm 远程地址
git clone
将远程仓库完整复制到本地,自动建立跟踪分支
js
git clone 远程仓库地址
克隆指定分支
js
git clone -b dev <url>
git fetch
从远程仓库下载最新的提交和引用(分支、标签),但不自动合并到本地分支。
下载远程地址的所有最新信息
bash
git fetch 远程地址别名/远程地址
只下载指定分支
bash
git fetch 远程地址 分支名
git pull
git fetch + git merge(默认)合并远程分支到当前分支
bash
git pull 远程地址 分支名
等价于:
git fetch 远程地址 分支名
git merge 远程地址 分支名
区别(fetch vs pull) :
fetch只下载,不改变本地工作区;pull会直接合并,可能产生冲突。
执行时机 :想要将远程的最新改动同步到本地并自动合并时。推荐 先 fetch 再 diff 看变化,最后手动 merge 或 rebase。
git push
将本地提交推送到远程仓库
推送当前分支到远程分支
bash
git push 远程地址 分支名
推送并建立上游跟踪(下次直接 git push)
bash
git push -u 远程地址 分支名
强制覆盖(慎用!)
bash
git push --force
撤销与恢复
git reset
移动分支指针,回退到指定提交。有三种模式:
--soft:仅移动 HEAD,保留暂存区和工作区。--mixed(默认):移动 HEAD + 重置暂存区,保留工作区。--hard:移动 HEAD + 重置暂存区 + 重置工作区(丢弃所有未提交改动)。
撤销上一次 commit,改动回到暂存区
bash
git reset --soft HDEA~1
例如:对file.txt文件做修改,然后提交保存,查看历史可以看到Test 1的分支提交记录
执行git reset --soft HDEA~1,系统撤销了Test 1的提交记录,并且不会改动工作区和暂存区 
bash
git reset (--mixed) HEAD~1
例如:将file.txt文件内容修改为"spider man",然后git add & git commit提交记录,再修改为"spider man测试",git add添加到暂存区,然后工作区改为"spider man测试123"
执行git reset HEAD~1,可以看到记录已经撤销,并且查看暂存区可以看到,之前git add的"spider man测试"记录此时也没有了

bash
git reset --hard f876b77
例如:将file.txt文件内容修改为"spider mantst",然后git add & git commit提交记录,再修改为"spider man111",git add添加到暂存区,然后工作区改为"spider man测试111333"
执行git reset --hard f876b77,此时HEAD,暂存区,工作区都被重置到指定的版本 
git revert <commit>
创建一个新提交 ,用来抵消指定提交的更改(安全撤销,不改变历史) 当你在提交记录的过程中发现某个历史记录有问题,想撤销,通过revert可以重新创建一个基于该历史记录的提交,抵消该历史提交,而不会删除历史记录 
git restore(Git 2.23+)
恢复工作区或暂存区的文件(替代 git checkout -- <file> 和 git reset 的部分功能)
bash
git restore README.md # 丢弃工作区修改(恢复到最近提交)
git restore --staged main.py # 将 main.py 从暂存区移出(但保留工作区修改)
git rm
从工作区和暂存区删除文件,并记录本次删除到暂存区。
丢弃工作区修改(恢复到最近提交)
bash
git rm 文件名
如果暂存区中有未提交的修改,是无法直接删除这个文件的,需要先提交之后才可以
仅从版本控制中删除(保留工作区文件),常用于忽略文件
js
git rm --cached 文件名

日志与差异高级
git reflog
记录本地仓库 HEAD 和分支引用的所有移动(即使 git reset 丢失的提交也能找回)。
bash
git reflog
git reset --hard HEAD@{2} # 回到两步骤前的状态

git show <commit>
显示某次提交的详细内容和差异。
bash
git show f876b77

git blame <file>
逐行显示文件的每一行最后一次是谁在什么提交中修改的
bash
git blame test.txt

储藏与清理
git stash
临时保存工作区和暂存区的未提交改动,使工作区干净(便于切换分支或拉取代码)。
bash
git stash # 储藏
git stash save "wip" # 带说明储藏
git stash list # 查看储藏列表
git stash pop # 应用最新的储藏并删除
git stash apply stash@{1} # 应用指定储藏但不删除
git stash drop # 删除最新的储藏
基于哪个版本(commit)保存的
执行时机:正在做的工作未完成,但急需切换到其他分支处理问题,又不希望提交半成品时。
标签(版本发布)
git tag
给某次提交打上永久标记(通常用于版本号)
bash
git tag v1.0.0 # 轻量标签
git tag -a v1.0.0 -m "release" # 附注标签
git push origin v1.0.0 # 推送标签到远程
执行时机:软件发布时,或需要标记一个重要的里程碑。
配置与帮助
git config
查看或设置 Git 配置(用户名、邮箱、别名、行为等)
bash
git config --global user.name "Your Name"
git config --global core.editor vim
git config alias.co checkout # 设置别名:git co 代替 git checkout
git help
打开任意命令的详细文档。
bash
git help commit
git commit --help # 效果相同
总结对照表(易混淆命令)
| 命令 A | 命令 B | 核心区别 | 执行时机建议 |
|---|---|---|---|
git fetch |
git pull |
fetch 只下载,pull 下载+合并 | 想安全查看远程更新时用 fetch,然后手动 merge/rebase |
git merge |
git rebase |
merge 保留分叉历史,rebase 线性历史 | 公共分支用 merge;私有分支用 rebase 保持整洁 |
git reset |
git revert |
reset 改写历史(危险),revert 增加反向提交(安全) | 本地未推送用 reset;已推送到公共分支用 revert |
git checkout |
git switch + git restore |
checkout 职责过重,新命令更专一 | 建议养成用 switch/restore 的习惯 |
git commit -a |
git add . + git commit |
-a 只自动暂存已跟踪文件,不包含新文件 |
新文件必须用 git add |