1.Git是什么
Git (分布式版本控制工具):
- 它是一个软件工具,安装在本地计算机上。
- 它的作用是追踪和管理项目(尤其是代码)的历史版本。
- “分布式”意味着每个开发者都有完整的代码历史记录,无需依赖中心服务器即可工作。
GitHub (代码托管平台):
- 它是一个基于网络的在线服务/平台。
- 它的作用是托管(存储)使用 Git 进行版本控制的代码仓库。
- 它提供了一个协作环境,方便团队成员分享代码、合并更改、进行代码审查等。
2.Git的用途
Git 作为版本控制工具,主要用于管理项目开发的历史记录和协作,其主要用途包括:
- 追踪历史记录 (Tracking History):
- 它可以记录项目中每一次文件更改的详细信息(谁在什么时候做了什么修改)。
- 你可以随时查看、比较项目在不同时间点的状态,相当于拥有了“时间机器”。
- 版本回退 (Reverting Versions):
- 如果代码出现 bug 或需要撤销最近的更改,Git 可以轻松地将整个项目恢复到历史上的任何一个工作版本。
- 分支管理 (Branch Management):
- Git 最强大的功能之一是分支 (Branch)。它允许开发者在不影响主线代码的情况下,创建独立的环境来开发新功能或修复 bug。
- 完成后,可以将这些分支合并 (Merge) 回主线。
- 多人协作 (Team Collaboration):
- 通过与 GitHub、GitLab 或 Bitbucket 等代码托管平台配合使用,Git 使得团队成员能够同时在同一个项目上工作,并有序地整合彼此的修改,避免冲突。
- 代码备份与同步 (Code Backup and Synchronization):
- 将本地仓库同步到远程仓库(如 GitHub),可以作为代码的远程备份,防止本地数据丢失。
- 这也方便了在多台设备之间同步你的工作进度。
总而言之,Git 的核心作用就是确保代码的演变过程是安全、可控、可追溯的,并有效地支持团队协作。
3.为什么使用GIT
使用 Git 的主要原因在于它能够解决在软件开发(或任何文档项目管理)过程中遇到的历史管理、错误回退和团队协作等核心问题。
1. 💾 确保项目历史的安全性与完整性 (Security and Integrity)
- 完整的历史记录: Git 会记录项目自创建以来的每一次有效更改(Commit),包括修改的内容、修改人和修改时间。这就像项目有一个完整的审计追踪,任何时候都可以知道发生了什么。
- 版本回溯(后悔药): 如果你发现最新的代码引入了 Bug,或者想要撤销一系列操作,Git 可以让你一键回到历史上的任何一个稳定版本,极大地降低了犯错的风险。 *
2. 🤝 强大的团队协作能力 (Team Collaboration)
- 高效合并: 多个开发者可以同时在项目的不同部分工作。当他们完成自己的工作后,Git 可以智能地合并这些修改,减少人工协调和文件覆盖的风险。
- 分支隔离 (Branching): 这是 Git 最重要的特性。开发者可以在一个独立的分支上开发新功能(Feature)、修复 Bug(Fix)或进行实验,而不会影响到项目主线(Main/Master)的稳定性。只有在测试通过后,才将分支合并回去。 *
3. 🌐 分布式优势 (Distributed Advantage)
- 本地完整备份: 由于 Git 是一个“分布式”系统,每个克隆了代码仓库的开发者本地都拥有完整的项目历史副本。这意味着即使中心服务器(如 GitHub)出现故障,团队成员仍然可以在本地继续工作,并在服务器恢复后轻松同步。
- 离线工作: 开发者可以在没有网络连接的情况下,进行提交 (Commit)、创建分支等所有的本地版本控制操作。
4. 🚀 标准化流程 (Standardized Workflow)
- 专业标准: Git 和 GitHub/GitLab 等平台已成为现代软件开发的行业标准。掌握它们是软件工程师、数据科学家等技术职位的基本技能。
- 清晰的工作流程: 它提供了一套清晰、一致的工作流程(Git Flow),帮助团队规范代码的提交、审查和发布过程。
简而言之:使用 Git 可以让您的项目管理变得更专业、更安全、更高效。
4.要学什么?怎么用
4.1基本概念
4.1.1仓库
Git 仓库(Repository,简称 Repo)是 Git 用来保存项目及其历史记录的地方。你可以把它想象成一个“带有时间机器的项目文件夹”。
在 Git 仓库中,不仅保存了你的代码文件,还保存了每一次修改的历史(Commit)、分支(Branch)以及标签(Tag)。
以下是关于 Git 仓库的核心概念、结构以及如何操作的完整指南。
1. Git 仓库的两种形式
Git 是分布式的,这意味着仓库可以在不同的地方存在。
-
本地仓库 (Local Repository):
位于你自己的电脑上。包含了项目的所有历史记录。即使没有网络,你也可以提交代码、查看历史或切换分支。
-
远程仓库 (Remote Repository):
托管在服务器上(如 GitHub, GitLab, Gitee)。用于团队协作和代码备份。
2. 如何获取一个仓库
主要有两种方式来“拥有”一个 Git 仓库:
A. 将现有文件夹初始化为仓库 (git init)
如果你有一个现成的项目文件夹,想开始用 Git 管理它:
cd your_project_folder # 进入你的项目目录
git init # 初始化
这会在当前目录下创建一个隐藏的 .git 文件夹,Git 的所有魔法都在这里发生。
B. 克隆远程仓库 (git clone)
如果你想下载别人的代码或自己托管在 GitHub 上的代码:
git clone https://github.com/username/project.git
这会下载整个项目及其完整的历史记录到你的电脑上。
3. 仓库内部的工作流 (核心概念)
在 Git 仓库中工作时,文件会流经三个主要区域。理解这一点是使用 Git 的关键:
- 工作区 (Working Directory): 你平时编辑代码、肉眼看得到的文件夹。
- 暂存区 (Staging Area / Index): 一个临时的保存区域,你把你想要提交的文件“挑选”出来放在这里。
- 本地仓库 (Local Repository): 实际上存储历史快照的地方。
基本操作流程:
- 修改文件(在工作区)。
git add将文件放入暂存区。git commit将暂存区的内容永久保存到本地仓库。
4. 常用仓库管理命令
| 操作 | 命令 | 说明 |
|---|---|---|
| 查看状态 | git status |
最重要命令。随时查看哪些文件被修改了,哪些在暂存区。 |
| 添加文件 | git add . |
将当前目录下所有修改添加到暂存区。 |
| 提交保存 | git commit -m "描述" |
将暂存区内容生成一个新版本(快照)。 |
| 查看历史 | git log |
查看提交历史记录。 |
| 关联远程 | git remote add origin <URL> |
将本地仓库连接到远程服务器。 |
| 推送到远程 | git push -u origin main |
将本地的提交上传到远程仓库。 |
| 拉取更新 | git pull |
从远程仓库下载最新的更改并合并到本地。 |
5. 两个重要的配置文件
在仓库根目录下,有两个文件非常重要:
.gitignore:- 这是一个文本文件,列出了 Git 应该忽略的文件。
- 用途: 防止编译产生的临时文件(如
.o,.exe,build/)、敏感信息(如密码配置)或系统文件(如.DS_Store)被提交到仓库中。
README.md:- 这是项目的说明书。通常使用 Markdown 格式编写。
- GitHub/Gitee 会默认在项目主页展示这个文件的内容。
6. 常见误区提示
注意: 不要手动修改或删除项目根目录下的 .git 隐藏文件夹。
如果删除了它,你的项目文件夹就会变回普通文件夹,所有的版本历史记录、分支信息都会永久丢失。
4.1.2 协议
1. 本地协议 (Local Protocol)
这是最基本的协议,用于在同一台机器上不同目录之间,或通过共享文件系统(如 NFS)进行克隆。
- 格式:
git clone /opt/git/project.gitgit clone file:///opt/git/project.git(显式指定)
- 优点:
- 简单: 不需要配置服务器,利用现有的文件权限。
- 快速: 如果在同一文件系统下,Git 会尝试使用硬链接(Hard Links),速度极快。
- 缺点:
- 局限性: 无法跨网段访问(除非挂载了共享网络硬盘)。
- 安全性: 如果使用共享文件系统,通常意味着用户有对整个仓库目录的完整 shell 访问权限,难以做到精细的权限控制。
2. HTTP / HTTPS 协议
这是目前最流行的协议,尤其是 HTTPS。现代 Git 使用的是 "Smart HTTP" 协议,而在早期版本中使用的是效率较低的 "Dumb HTTP"。
- 格式:
https://github.com/user/project.git - 优点:
- 防火墙友好: 使用标准的 80 或 443 端口,几乎所有企业防火墙都允许通过。
- 简便性: 不需要配置 SSH 密钥,只需要用户名/密码(或 Token)。
- 单一 URL: 在现代 Git 服务器(如 GitHub/GitLab)上,匿名只读访问和认证写访问通常可以使用同一个 URL。
- 缺点:
- 凭证管理: 每次推送都需要输入密码(除非配置了凭证助手 Credential Helper)。
- 性能: 虽然 Smart HTTP 已经很快,但在某些极端的大文件传输场景下,可能略慢于 SSH。
3. SSH 协议 (Secure Shell)
这是在 Linux/Unix 环境下进行自主托管(Self-hosted)或团队开发最常用的协议。
- 格式:
user@server:project.git或ssh://user@server/project.git - 优点:
- 安全性高: 数据全程加密,且必须经过身份验证。
- 无需输入密码: 配置 SSH Key 后,推送代码非常流畅,无需人工干预。
- 原生支持: 几乎所有 Linux 服务器都默认安装并开启了 SSH 服务。
- 缺点:
- 不支持匿名访问: 必须有服务器的访问权限才能读取数据(这对开源项目是不利的)。
- 配置门槛: 对于新手来说,生成和管理 SSH 密钥对(public/private key)可能稍显复杂。
4. Git 协议
这是 Git 自带的一种守护进程协议(daemon),监听 9418 端口。
- 格式:
git://server/project.git - 优点:
- 速度最快: 它是专门为 Git 传输设计的,且没有加密解密的开销。
- 缺点:
- 无身份验证: 这是一个纯粹的传输协议,通常只用于公开项目的只读访问(Read-only)。
- 防火墙问题: 使用非标准的 9418 端口,容易被企业防火墙拦截。
- 无加密: 数据传输是明文的,不适合传输敏感代码。
总结与对比
| 协议类型 | 典型用途 | 优点 | 缺点 |
|---|---|---|---|
| Local | 本地备份、NFS 共享 | 极快、配置简单 | 仅限本地或共享磁盘 |
| HTTPS | GitHub/GitLab 通用 | 穿透防火墙、通用性强 | 推送时需凭证管理 |
| SSH | 团队内部开发、Linux 服务器 | 安全、免密推送 (Key)、高效 | 不支持匿名读取 |
| Git | 公共开源项目的只读镜像 | 传输速度最快 | 无加密、无鉴权、非标端口 |
4.1.3配置用户名和邮箱
1. 全局配置(最常用)
如果你希望这台电脑上所有的项目都默认使用同一个身份(比如你的 GitHub 账号),使用 --global 参数。
git config --global user.name "你的名字"
git config --global user.email "你的邮箱@example.com"
- 你的名字:可以用英文也可以用中文,这里建议使用你常用的 ID (如 GitHub 用户名)。
- 你的邮箱:建议使用你注册 GitHub/Gitee/GitLab 时用的邮箱。这样你的提交记录才能在这些网站上正确统计(也就是会有“绿色的格子”)。
2. 针对特定项目配置(局部)
如果你只是想在当前这个特定项目中使用不同的身份(例如:平时用个人邮箱,但这个项目是学校作业或公司项目,需要用特定邮箱),你需要先进入该项目的文件夹,然后去掉 --global 参数:
cd 你的项目目录
git config user.name "你的特定名字"
git config user.email "你的特定邮箱@university.edu.cn"
注意:局部配置的优先级高于全局配置。
3. 如何查看配置是否成功
你可以使用以下命令查看当前生效的配置列表:
git config --list
或者只查看特定的项:
git config user.name
git config user.email
4.1.4. 四个“物理”区域 (代码存放在哪里?)
这四个概念按顺序构成了代码的“流转路径”:
- 本地工作区 (Working Directory)
- 是什么: 就是你电脑文件管理器里能看得到的那个文件夹。
- 状态: 你在这里写代码、改论文。这里的修改是未被追踪的,如果不保存到 Git,删了就找不回了。
- 对应的动作:编辑文件。
- 暂存区 (Staging Area / Index)
- 是什么: 一个临时的“购物车”或“发货清单”。
- 作用: Git 允许你挑选文件提交。比如你改了 A 和 B 两个文件,但只想先把 A 存入历史记录,你就只把 A 放到暂存区。
- 对应的命令:
git add
- 本地仓库 (Local Repository)
- 是什么: 位于你电脑上的
.git文件夹内部。 - 作用: 存档的地方。一旦提交到这里,就生成了一个永久的历史版本(快照)。
- 对应的命令:
git commit
- 是什么: 位于你电脑上的
- 远程仓库 (Remote Repository)
- 是什么: 托管在互联网上的服务器(如 GitHub, Gitee, GitLab)。
- 作用: 类似于网盘,用于备份代码和与他人协作。
- 对应的命令:
git push(上传) /git pull(下载)
4.1.5. 两个“逻辑”标记 (如何定位代码?)
这两个概念用于在海量的历史记录中找到你想要的那一刻:
- 版本号 (Commit ID / Hash)
- 是什么: Git 不像 Word 那样用
v1,v2命名,而是给每一次提交生成一个唯一的、长长的字符串(哈希值),例如a1b2c3d...。 - 作用: 它是版本的“身份证号”。如果你想回退到某次修改,就需要用到这个号码。
- 是什么: Git 不像 Word 那样用
- HEAD
- 是什么: 一个指针,或者理解为地图上的“你在这里” (You are here) 标记。
- 作用: 它指向你当前正在操作的那个版本(通常是当前分支的最新一次提交)。当你切换分支或回退版本时,HEAD 就会移动,你的工作区文件也会随之改变。
总结:一张图看懂数据流向
根据你图片中的层级,标准的工作流是这样的:
- 在 工作区 写代码。
- 用
git add放入 暂存区。 - 用
git commit生成 版本号 并存入 本地仓库(HEAD 指向这里)。 - 用
git push同步到 远程仓库。
4.2操作
4.2.1基本操作
1. 代码流转三部曲 (Add -> Commit -> Push)
这三个命令对应了代码从你电脑走向远程服务器的三个阶段(对应图2的层级):
Step 1: 暂存 (git add)
- 图解位置: 本地工作区 $\rightarrow$ 暂存区
- 作用: 挑选你想要提交的文件。
- 操作:
git add .:把所有修改过的文件(比如你刚写完的.cpp和.h头文件)全部放入暂存区。git add main.cpp:只暂存特定文件。
Step 2: 提交 (git commit)
- 图解位置: 暂存区 $\rightarrow$ 本地仓库
- 图中批注解读: “区分不同类别的修改”。
- 这意味着你的 commit message(提交信息)应该清晰地分类。比如,不要把“修复 Bug”和“开发新功能”混在一个 commit 里提交。
- 良好的习惯: 每次只做一个逻辑上的修改就 commit 一次。
- 命令:
git commit -m "Fix: 修复了内存泄漏问题"
Step 3: 推送 (git push)
- 图解位置: 本地仓库 $\rightarrow$ 远程仓库
- 作用: 把你的代码同步到 GitHub/Gitee 服务器。
- 命令:
git push origin main
2. 同步更新:Fetch vs Pull (图1的重点)
你的思维导图中非常准确地把 git pull 拆解成了两步,这是很多初学者容易搞混的地方。
拉取 (git fetch)
- 图中批注解读: “将远程仓库所包含分支的最新 commit-id 记录到本地文件”。
- 这是一个非常底层的解释。它的意思是:
fetch只是去远程服务器“看了一眼”,把远程最新的变化(Commit ID)下载到了本地的.git目录里(更新了origin/main指针),但并没有修改你工作区里的代码。 - 此时的状态: 你的代码还没变,但 Git 已经知道远程有了新版本。
- 这是一个非常底层的解释。它的意思是:
拉取合并 (git pull)
- 图解公式:
git pull=git fetch+git merge - 作用: 不仅下载远程的更新(Fetch),还自动把这些更新合并(Merge)到你当前正在编辑的文件里。
- 建议: 在绝大多数日常开发中,直接用
git pull即可。但如果你担心远程代码和你的有冲突,可以先fetch看看,再决定要不要merge。
3. 监控与“后悔药” (Status, Log, Reflog)
查看状态 (git status)
- 作用: 这是一个仪表盘。它告诉你文件当前在哪个区域(是已修改但未暂存?还是已暂存未提交?)。
查看历史 (git log)
- 作用: 查看提交日志(Commit ID, 作者, 时间, 内容)。
救命命令 (git reflog)
- 这是图中最高阶的命令。
- 区别:
git log记录的是代码的提交历史;git reflog记录的是你的每一次 Git 操作历史(包括被你撤销的、删除的 commit)。 - 场景: 比如你不小心
git reset --hard把昨晚写的代码回退没了,git log里已经看不到那条记录了,但在git reflog里还能找到!它是 Git 的“黑匣子”,能帮你找回丢失的代码。
4.2.2逆向操作
1. 工作区 (Workspace) —— 还没 git add
当你修改了文件,但发现改错了,想放弃修改,恢复到上一次提交的状态:
-
推荐指令 (新版):
git restore <文件名> # 或者放弃所有修改 git restore . -
传统指令 (旧版):
git checkout -- <文件名>
2. 暂存区 (Staging Area) —— 已经 git add,但还没 git commit
当你把文件放入了暂存区,但想撤回(变回未暂存状态,但保留修改内容):
-
推荐指令 (新版):
git restore --staged <文件名> -
传统指令 (旧版):
git reset HEAD <文件名>
3. 本地仓库 (Local Repository) —— 已经 git commit
当你已经提交了代码,但想撤销这次提交。这里有三种程度的"后悔药":
A. 只是提交信息写错了,或者漏提了几个文件
不需要删除提交,直接修正最后一次提交:
# 修改后重新提交,会覆盖上一次的 commit ID
git commit --amend
B. 彻底撤销提交 (Git Reset)
使用 git reset 可以将当前分支的指针(HEAD)向后移动。
-
场景 1:撤销提交,但保留代码在暂存区 (Soft Reset)
- 适用于:想重新调整一下提交内容再 commit。
git reset --soft HEAD~1 -
场景 2:撤销提交,保留代码在工作区 (Mixed Reset, 默认)
- 适用于:发现代码还有问题,想继续改改。
git reset HEAD~1 -
场景 3:彻底放弃修改,回到上一个版本 (Hard Reset) ⚠️ 危险操作
- 适用于:刚才写的全是垃圾,完全不想要了。
git reset --hard HEAD~1
4. 远程仓库 (Remote Repository) —— 已经 git push
代码已经推送到远程服务器(如 GitHub/GitLab),此时要非常小心,因为其他人可能已经拉取了你的代码。
A. 安全做法:使用 git revert (推荐)
这不会删除历史记录,而是生成一个新的提交,反向抵消掉之前的修改。
- 适用于:公共分支(如 master/main/develop),不破坏他人协作。
git revert <Commit ID>
git push origin <分支名>
B. 暴力做法:强制推送 (Force Push)
如果你确定只有你一个人在使用这个分支,或者你必须抹除某次提交记录(如提交了密码):
-
先在本地回滚(如
git reset --hard)。 -
强制推送到远程:
git push --force # 或者更安全的做法(如果远程有更新则报错) git push --force-with-lease
5. 救命药:Git Reflog
如果你不小心用 git reset --hard 删除了重要的提交,或者误删了分支,Git 还有一个隐藏的"后悔药"。
Git 会记录HEAD引用的每一次移动(即使是 reset 掉的)。
-
查看记录:
git reflog你会看到类似
HEAD@{1}: reset: moving to HEAD~1的记录。 -
找回丢失的提交:
找到你丢失的那个 Commit ID,然后重置回去:
git reset --hard <Commit ID>
6.checkout
1. git checkout -- file
- 作用: 撤销单个文件在工作区中的修改。
- 效果: 用当前 HEAD 版本的
file文件内容覆盖工作区和暂存区的同名文件。 - 新命令推荐:
git restore <file>(作用更明确)
2. git checkout (无参数或仅带分支名)
当 git checkout <branch-name> 时,Git 会:
- 切换到指定分支。
- 将整个工作区的内容更新为该分支最新提交(HEAD)的状态。
- 如果切换分支会导致未提交的修改丢失,
git checkout会失败并提示你先提交或藏匿(stash)修改。
- 如果没有任何修改: 只是简单切换分支。
- 如果工作区有修改: 通常不会导致
workspace -> null的效果,因为它会尝试保护你的修改。
3. git checkout -f (或 git checkout --force) ⚠️ 危险操作
这是最直接实现 "workspace -> null" 的方式,但通常用于切换分支时。
- 作用: 强制切换到指定的分支或提交。
- 效果:
- 它会丢弃工作区和暂存区中所有与目标分支/提交冲突的未提交修改。
- 这正是您图片中 "workspace -> null" 最暴力的实现方式:它会强制清除工作区中那些妨碍切换分支的修改。
- 新命令推荐: 如果你的目的是放弃工作区修改,请使用
git restore .或git reset --hard,而不是依赖checkout -f的副作用。
💡 总结与更推荐的 Git 逆向操作
为了避免混淆,建议使用更现代、目标更明确的命令来清除工作区修改:
| 目标 | 老命令(git checkout 系列) | 新命令(推荐) |
|---|---|---|
| 撤销单个文件修改 | git checkout -- <file> |
git restore <file> |
| 撤销所有文件修改 | 不直接推荐 | git restore . |
| 彻底回退到上个版本 (放弃所有修改和暂存) | 不直接推荐 | git reset --hard HEAD |
总结速查表
| 场景 | 推荐指令 | 作用 |
|---|---|---|
| 工作区 (改乱了想还原) | git restore . |
丢弃本地所有未暂存的修改 |
| 暂存区 (add 后想撤回) | git restore --staged . |
将文件从暂存区移回工作区 |
| 修补提交 (写错注释) | git commit --amend |
修改最后一次提交而不产生新记录 |
| 撤销提交 (想重新提) | git reset --soft HEAD~1 |
撤销 Commit,保留文件在暂存区 |
| 完全回退 (不要代码了) | git reset --hard HEAD~1 |
彻底丢弃最后一次提交的所有内容 |
| 远程回退 (安全做法) | git revert <CommitID> |
新增一个反向提交来抵消修改 |
4.2.3 本地仓库整理操作
1. 清理分支 (Branch Cleanup)
随着开发进行,本地会积累大量已经合并或废弃的分支。
-
查看本地分支:
git branch -
删除已合并的分支(安全删除):
Git 会检查该分支是否已合并到当前分支,如果未合并会阻止删除。
git branch -d <分支名> -
强制删除分支(慎用):
不管是否合并,直接删除(适用于废弃的实验性分支)。
git branch -D <分支名> -
清理无效的远程追踪分支:
如果远程仓库(如 GitHub/GitLab)上的分支已经被删除,但你本地的 git branch -a 还能看到 remotes/origin/xxx,使用此命令清理:
git fetch -p # 或者 git remote prune origin
💡 高级技巧:批量删除已合并分支
如果你有大量已合并的分支(master/main 除外),可以在 Bash 中运行:
git branch --merged | grep -v "*" | grep -v "master" | grep -v "main" | xargs -n 1 git branch -d
2. 清理工作区 (Working Directory Cleanup)
当你编译项目或生成了大量临时文件(且没有加入 .gitignore)时,可以使用 git clean。
-
第一步:演习(Dry Run)—— 非常重要!
先看看如果不加干预会删除哪些文件,防止误删重要数据。
git clean -n # 如果想连同文件夹一起看: git clean -nd -
第二步:执行清理
确认无误后,执行删除。
# 删除未追踪的文件 git clean -f # 删除未追踪的文件和目录 git clean -fd
3. 清理暂存区 (Stash Cleanup)
开发过程中可能使用 git stash 临时保存过代码,久而久之会堆积。
-
查看暂存列表:
git stash list -
删除指定的暂存:
git stash drop stash@{0} # 删除索引为0的暂存 -
清空所有暂存(慎用):
一次性删除所有 stash 记录,无法恢复。
git stash clear
4. 整理提交历史 (Commit History)
如果你的提交历史很乱(例如有很多 "fix typo", "update", "wip" 等琐碎提交),可以使用变基(Rebase)将其合并。
-
交互式变基:
整理最近的 N 次提交(例如最近 3 次)。
git rebase -i HEAD~3- 进入编辑器后,将需要合并的提交前的
pick改为squash(或s)。 - 保存退出后,Git 会让你编辑合并后的新 Commit Message。
- 进入编辑器后,将需要合并的提交前的
⚠️ 警告:什么时候绝对不要用 Rebase?
如果这几个提交是在公共分支(如 master / main / develop)上,且别人可能已经拉取了代码,绝对不要 Rebase! Rebase 会修改历史(修改 Commit ID),这会导致同事的代码与远程冲突,引发灾难。 Rebase 仅限用于整理你自己私有的、还未合并到主干的分支。
5. 仓库瘦身与维护 (Garbage Collection)
Git 也是数据库,长时间使用后会有很多悬空对象(Dangling objects),占用磁盘空间。
-
手动触发垃圾回收:
压缩文件版本,移除不可达的对象,优化仓库体积。
git gc通常 Git 会自动运行此命令,但手动运行可以强制立即优化。
6. 终极重置 (The "Nuclear" Option)
如果你的本地仓库彻底乱套了,想要完全放弃本地修改,让它变得和远程仓库(origin/main)一模一样:
⚠️ 警告: 此操作会丢失所有本地未提交的代码!
# 1. 获取远程最新状态
git fetch origin# 2. 强制重置当前分支到远程状态
git reset --hard origin/main# 3. 清理所有未追踪文件
git clean -fd
总结建议
| 操作目的 | 常用命令 | 风险等级 |
|---|---|---|
| 日常清理 | git fetch -p (同步远程删除) |
🟢 低 |
| 删除分支 | git branch -d |
🟢 低 |
| 清理文件 | git clean -fd (先用 -n) |
🟡 中 (文件不可找回) |
| 整理提交 | git rebase -i |
🟡 中 (若已推送到远程,需强制推送) |
| 重置仓库 | git reset --hard |
🔴 高 (丢失所有进度) |
4.2.4分支操作
1. 现代化命令:switch 与 restore (推荐)
Git 2.23 版本引入了两个新命令,用来替代功能过于杂乱的 git checkout。建议养成使用新命令的习惯,语义更清晰。
| 操作 | 旧命令 (Old) | 新命令 (New & Recommended) |
|---|---|---|
| 切换分支 | git checkout <分支名> |
git switch <分支名> |
| 创建并切换 | git checkout -b <新分支> |
git switch -c <新分支> |
| 撤销文件修改 | git checkout <文件> |
git restore <文件> |
2. 本地分支高频操作速查
🔎 查看分支
# 查看本地分支(带 * 号的是当前分支)
git branch# 查看所有分支(包含远程分支 remotes/origin/xxx)
git branch -a# 查看分支指向的最新 commit 信息(很实用)
git branch -v
🛠 创建与切换
# 仅创建,不切换
git branch feature-login# 切换到已存在的分支
git switch feature-login# 创建并立刻切换过去(最常用)
git switch -c feature-login
🧩 合并分支 (Merge)
假设你现在位于 main 分支,想把 feature-login 的代码合进来:
# 1. 先切回主分支
git switch main# 2. 执行合并
git merge feature-login
💡 小贴士:
如果想要在合并时强制生成一个新的 Commit 节点(保留分支历史结构,而不是 Fast-forward 直线合并),请加上 --no-ff 参数:
git merge --no-ff feature-login
✏️ 重命名分支
如果你手滑把分支名打错了(比如把 feature 打成了 future):
# 重命名当前所在的分支
git branch -m <新名字># 重命名指定分支(不需要先切换过去)
git branch -m <旧名字> <新名字>
3. 远程分支交互 (Remote Interaction)
🚀 推送分支到远程
你在本地新建了 dev 分支,远程仓库还没有:
# 第一次推送,并建立追踪关系(upstream)
git push -u origin dev
以后只需要输入 git push 即可。
📥 拉取远程新分支
同事在远程建立了个 bugfix-101 分支,你想拉到本地开发:
git fetch
# 直接切换,Git 会自动在本地建立同名分支并关联
git switch bugfix-101
🗑 删除远程分支
注意: 也就是删除 GitHub/GitLab 上的分支。
git push origin --delete <分支名>
4. 常见场景实战
场景一:处理冲突 (Conflict)
当你执行 git merge 时,如果两个分支修改了同一行代码,Git 会报错 CONFLICT。
-
打开文件:你会看到
<<<<<<< HEAD和>>>>>>> feature-x的标记。 -
手动修改:保留想要的代码,删除标记符号。
-
重新提交:
git add . git commit -m "Fix merge conflicts"
场景二:分支游离状态 (Detached HEAD)
如果你用 git checkout <commit-id> 切换到了某个具体的提交点,而不是分支名,你会进入“游离状态”。
-
表现:你做的修改如果提交,一旦切走就会丢失。
-
救法:如果你在这个状态下写了代码,想保存下来,必须立刻新建一个分支指向它:
git switch -c <新分支名>
4.2.5解决冲突
第一阶段:定位冲突 (Identify)
当你执行 git merge 或 git pull 出现冲突时,终端会提示 CONFLICT (content): Merge conflict in filename。
-
查看冲突文件列表: 使用以下命令查看哪些文件处于“冲突”状态:
git status- 输出中标记为
both modified的文件就是你需要处理的文件。
- 输出中标记为
第二阶段:解决冲突 (Resolve)
你可以选择 手动编辑代码 或 使用工具。
方法 A:手动编辑(通用方法)
-
打开冲突文件。你会看到 Git 自动插入的冲突标记:
Plaintext
<<<<<<< HEAD var limit = 100; // 当前分支(你原本的代码) ======= var limit = 200; // 传入分支(你要合并进来的代码) >>>>>>> feature-branch<<<<<<< HEAD到=======之间:是你当前所在分支的代码。=======到>>>>>>> branch-name之间:是另一个分支(或者远端)的代码。
-
修改代码。你需要做的是:
- 决定保留哪一部分(保留上面、保留下面,或者两者结合修改)。
- 删除 所有的标记符号(
<<<<<<<,=======,>>>>>>>)。
修改后示例:
var limit = 150; // 假设我们要取折中值,或者只保留某一方 -
保存文件。
方法 B:使用 IDE 工具(推荐)
如果你使用的是 VS Code、IntelliJ IDEA 或 Trae 等现代编辑器:
- 打开冲突文件。
- 编辑器通常会高亮显示冲突,并提供按钮:
- Accept Current Change (保留当前/HEAD)
- Accept Incoming Change (保留传入)
- Accept Both Changes (保留两者)
- Compare Changes (对比差异)
- 点击按钮即可自动清理标记并保留选中的代码。
方法 C:命令行“二选一”快捷策略
如果你确定完全不需要看代码,只想直接覆盖(非常暴力,慎用):
-
完全保留当前分支版本(丢弃对方的):
git checkout --ours <filename> -
完全保留传入分支版本(丢弃自己的):
git checkout --theirs <filename>
第三阶段:提交更改 (Commit)
解决完所有文件的冲突后,你需要告诉 Git 冲突已解决。
-
将修改后的文件加入暂存区(这一步是标记“冲突已解决”):
git add <filename> # 或者如果都修好了 git add . -
检查状态: 再次运行
git status,确保所有文件都已变更为绿色(Ready to commit)。 -
完成合并提交:
git commit # 通常不需要加 -m,Git 会自动生成一个 "Merge branch..." 的提交信息,直接保存退出即可注意:如果你是在
git rebase过程中遇到的冲突,请使用git rebase --continue而不是git commit。
🚨 紧急撤销 (Abort)
如果你在解决冲突的过程中把代码改乱了,或者不想合并了,可以随时终止这次合并,回到冲突发生之前的状态:
-
如果是合并冲突 (
merge):git merge --abort -
如果是变基冲突 (
rebase):git rebase --abort
总结 Checklist
git status找到红色的both modified文件。- 打开文件,搜索
<<<<<<<。 - 修改代码,删除所有 Git 标记符号。
git add <file>。git commit(或git rebase --continue)。
4.3 使用规范
1. 迭代全景图
这是一个闭环流程,通常以 1-2 周为一个周期:
2. 详细流程拆解
第一阶段:需求规划 (Planning)
- 输入:来自导师/老板的想法,或产品经理的需求文档 (PRD)。
- 动作:
- Sprint Planning 会议:团队坐在一起,从需求池(Backlog)里挑出这 2 周能做完的任务。
- 任务拆解:将大功能拆成具体的开发任务(Task),例如“设计数据库表”、“编写 API 接口”、“前端页面实现”。
- 估时:评估每个任务需要多少小时。
第二阶段:设计与开发 (Development) —— Git 操作高频区
这是你写代码的主战场。
-
切分支 (Branching):不要直接在
main或master上写。基于主分支创建一个功能分支:git checkout -b feature/login-module -
编码 (Coding):编写代码,实现逻辑。
-
本地自测:运行单元测试,确保逻辑跑通。
-
处理冲突 (Rebase):
-
在你开发这几天,同事可能已经合并了代码到
main。 -
关键动作:在提交前,先拉取最新代码并变基(这就是你刚才问的 Rebase 场景):
git fetch origin git rebase origin/main -
如果有冲突,就在这里解决。
-
第三阶段:代码评审与合并 (Code Review & Merge)
- 提交 PR/MR:将代码推送到远程,发起 Pull Request (GitHub) 或 Merge Request (GitLab)。
- Code Review (CR):
- 资深工程师或导师查看你的代码。
- 检查点:代码规范、是否有 Bug、是否这类逻辑太复杂。
- 修改:根据评论修改代码,再次 push(会自动更新 PR)。
- 合并 (Merge):评审通过后,代码被合并进入
dev或main分支。
第四阶段:测试 (QA & Testing)
- CI/CD 流水线:代码合并后,自动化工具(如 Jenkins, GitHub Actions)会自动构建项目并运行自动化测试。
- 人工测试:测试人员(QA)在测试环境(Staging)验证功能。
- 如果有 Bug -> 提单 -> 你修 Bug -> 重新走合并流程。
第五阶段:发布与复盘 (Release & Retro)
- 上线 (Deploy):将测试通过的代码发布到生产环境(Production)。
- 回顾会议 (Retrospective):
- 迭代结束,团队坐下来聊聊:上个周期哪个环节卡住了?Git 冲突为什么这么多?API 文档为什么没对齐?
- 目的是为了下一次迭代更顺畅。
3. 针对个人的最佳实践 (研究生/独立开发者版)
既然你对 C++、Linux 和 AI 部署感兴趣,你的个人项目迭代可以简化为:
- Issue 驱动:在 GitHub/Gitee 仓库里建 Issue,列出“今天要做的功能”。
- 分支开发:强迫自己用
feature/xxx分支开发,哪怕只有你一个人。这能保护你的主分支永远是可运行的。 - 定期 Rebase:如果你在尝试 Trae 或其他 AI 工具协助编码,AI 生成的代码要像对待同事的代码一样,合并前仔细 Check 并解决潜在逻辑冲突。
- 写好 Makefile/CMake:Linux 环境下,确保你的构建脚本是自动化的,这相当于简易版的 CI/CD。
