Ubuntu 22.04中的版本控制系统(Git实战)
一、什么是版本控制
1. 核心概念
版本控制(Version Control)是一种追踪文件变更、记录修改历史、协作管理项目的技术,核心作用是:
- 回溯历史:随时恢复到任意历史版本(如代码误删、引入bug后回滚);
- 多人协作:多开发者同时修改同一项目,自动合并代码,解决冲突;
- 追踪责任:记录每个修改的作者、时间、内容(便于问题定位);
- 并行开发:通过分支功能同时推进多个功能(如主线开发+bug修复)。
2. 版本控制工具分类
| 类型 | 代表工具 | 核心特点 |
|---|---|---|
| 集中式 | SVN、CVS | 所有版本存储在中央服务器,本地仅存当前版本,依赖网络,单点故障风险高 |
| 分布式 | Git、Mercurial | 每个开发者本地都有完整仓库(包含所有历史版本),离线可开发,协作灵活高效 |
3. Git的核心优势
- 分布式架构:不依赖中央服务器,本地可完成提交、分支等操作;
- 高效性能:压缩存储历史版本,分支切换、合并速度极快;
- 强大分支:支持轻量级分支,轻松实现并行开发与版本管理;
- 完整性保障:通过哈希值校验文件,防止数据篡改或丢失。
4. Git核心术语
- 工作区(Working Directory):本地编辑代码的文件夹(可见文件);
- 暂存区(Staging Area) :临时存储待提交的修改(
.git/index文件); - 本地仓库(Local Repository) :存储所有版本历史(
.git隐藏文件夹); - 远程仓库(Remote Repository):远程服务器上的仓库(如GitHub、GitLab);
- 提交(Commit):将暂存区的修改保存到本地仓库,生成唯一版本号(哈希值);
- 分支(Branch) :独立的开发线路(默认
main分支,原master已逐步淘汰); - 合并(Merge):将一个分支的修改整合到另一个分支。
二、安装及配置Git(Ubuntu 22.04)
1. Git安装(详细步骤)
Ubuntu 22.04默认软件源包含Git,通过APT安装即可,步骤如下:
bash
# 1. 更新软件源(确保获取最新版本)
sudo apt update
# 2. 安装Git(-y自动确认安装)
sudo apt install -y git
# 3. 验证安装是否成功(查看版本号,Ubuntu 22.04默认3.2.0+)
git --version
# 输出示例:git version 2.34.1(版本号可能因系统更新略有差异)
2. Git基础配置(必须步骤)
Git需要配置用户信息(用户名、邮箱),用于标识提交者身份,配置分为「全局配置」和「本地配置」:
- 全局配置:所有本地仓库共用(推荐优先配置);
- 本地配置:仅当前仓库生效(优先级高于全局配置)。
2.1 全局配置(常用)
bash
# 1. 配置全局用户名(替换为你的用户名,如GitHub用户名)
git config --global user.name "Your Name"
# 2. 配置全局邮箱(替换为你的邮箱,如GitHub注册邮箱)
git config --global user.email "your.email@example.com"
# 3. (可选)配置默认文本编辑器(解决冲突、编写提交信息时使用)
# 可选编辑器:vim、nano、code(VS Code)等,这里以vim为例
git config --global core.editor "vim"
# 4. (可选)配置中文显示(解决中文文件名乱码问题)
git config --global core.quotepath false
# 5. 验证配置是否生效(查看所有全局配置)
git config --global --list
# 输出示例:
# user.name=Your Name
# user.email=your.email@example.com
# core.editor=vim
# core.quotepath=false
2.2 本地配置(针对单个仓库)
如果某个仓库需要单独配置用户信息(如工作仓库用公司邮箱),进入仓库目录后执行:
bash
# 1. 进入目标仓库目录(先创建或克隆仓库,后续章节讲解)
cd ~/projects/my-project
# 2. 配置本地用户名和邮箱(覆盖全局配置)
git config user.name "Work Name"
git config user.email "work.email@company.com"
# 3. 查看本地配置
git config --list
# 输出会包含全局配置+本地配置(本地配置优先级更高)
2.3 配置文件位置
- 全局配置文件:
~/.gitconfig(可直接编辑修改); - 本地配置文件:
仓库目录/.git/config(仓库内生效)。
三、建立项目仓库
Git仓库分为「本地仓库」和「远程仓库」,核心流程:本地仓库可独立使用,也可关联远程仓库实现协作/备份。
1. 本地新建仓库(从零开始)
适用于全新项目,步骤如下:
bash
# 1. 创建项目目录(自定义名称和路径)
mkdir -p ~/projects/git-demo # -p确保父目录存在
cd ~/projects/git-demo # 进入项目目录
# 2. 初始化本地仓库(关键命令:在目录中创建.git文件夹)
git init
# 输出:Initialized empty Git repository in /home/yourname/projects/git-demo/.git/
# 3. 查看仓库状态(验证初始化成功)
git status
# 输出:On branch main(默认分支main)
# No commits yet(暂无提交)
# nothing to commit(无待提交文件)
# 说明:.git文件夹是本地仓库核心,存储所有版本历史、配置等,切勿手动修改/删除
2. 克隆远程仓库(从远程导入)
适用于已有远程仓库(如GitHub、GitLab上的项目),通过git clone复制到本地:
bash
# 1. 克隆公开仓库(以GitHub上的测试仓库为例)
# 格式:git clone 远程仓库URL [本地目录名(可选)]
git clone https://github.com/octocat/Hello-World.git ~/projects/hello-world
# 2. 进入克隆后的仓库目录
cd ~/projects/hello-world
# 3. 查看仓库信息(验证克隆成功)
git status
# 输出:On branch main
# Your branch is up to date with 'origin/main'(与远程分支同步)
# 4. 查看远程仓库关联(origin是远程仓库的默认别名)
git remote -v
# 输出:
# origin https://github.com/octocat/Hello-World.git (fetch)
# origin https://github.com/octocat/Hello-World.git (push)
# 说明:克隆仓库会自动完成3件事:
# - 创建本地仓库目录;
# - 初始化本地仓库(.git文件夹);
# - 关联远程仓库(别名origin);
# - 拉取远程仓库的所有代码和历史版本。
克隆私有仓库(需身份验证)
如果远程仓库是私有(如公司GitLab仓库),克隆时需输入用户名和密码,或配置SSH密钥(免密登录):
bash
# 方式1:HTTPS协议(输入用户名+密码)
git clone https://username@gitlab.company.com/team/project.git
# 方式2:SSH协议(需提前配置SSH密钥,免密登录)
# 1. 生成SSH密钥(默认路径~/.ssh/id_rsa)
ssh-keygen -t rsa -C "your.work.email@company.com"
# 按回车默认即可,无需设置密码
# 2. 查看公钥内容(复制到远程仓库的SSH密钥配置中)
cat ~/.ssh/id_rsa.pub
# 复制输出的所有内容(以ssh-rsa开头,以邮箱结尾)
# 3. 克隆私有仓库(SSH协议)
git clone git@gitlab.company.com:team/project.git
四、创建项目并导入源代码
新建仓库后,需将项目文件(源代码、配置文件等)导入仓库,核心步骤:工作区→暂存区→本地仓库。
1. 创建示例项目文件
以C语言项目为例,创建源代码文件和说明文档:
c
// 1. 创建主程序文件hello.c(带详细注释)
vim hello.c
写入以下代码:
c
#include <stdio.h>
int main() {
// 初始版本:输出Hello Git
printf("Hello Git! This is my first commit.\n");
return 0;
}
bash
# 2. 创建项目说明文档README.md
vim README.md
写入:
markdown
# Git Demo 项目
这是一个用于演示Git版本控制的C语言项目。
核心功能:输出问候语,展示Git的提交、修改、冲突解决等操作。
2. 导入文件到本地仓库(三步曲)
Git导入文件需经过「添加到暂存区」和「提交到本地仓库」两个关键步骤:
步骤1:查看文件状态(git status)
bash
# 查看当前工作区和暂存区状态
git status
# 输出:
# Untracked files:(未跟踪文件:Git未管理的新文件)
# hello.c
# README.md
# 提示:使用git add <file>将文件添加到暂存区
步骤2:添加到暂存区(git add)
将需要跟踪的文件添加到暂存区(可单个文件、多个文件或所有文件):
bash
# 方式1:添加单个文件
git add hello.c
# 方式2:添加多个文件(空格分隔)
git add hello.c README.md
# 方式3:添加当前目录所有文件(常用,注意不要添加临时文件)
git add . # "." 代表当前目录
# 再次查看状态(验证添加成功)
git status
# 输出:
# Changes to be committed:(待提交文件:已在暂存区)
# new file: hello.c
# new file: README.md
步骤3:提交到本地仓库(git commit)
将暂存区的文件永久保存到本地仓库,生成唯一版本记录,必须填写提交信息(描述修改内容):
bash
# 基本格式:git commit -m "提交信息"(-m指定提交说明)
git commit -m "feat: 初始化项目,添加hello.c和README.md"
# 输出示例(成功提交):
# [main (root-commit) 7a3f2d1] feat: 初始化项目,添加hello.c和README.md
# 2 files changed, 10 insertions(+)(2个文件变更,新增10行代码)
# create mode 100644 hello.c
# create mode 100644 README.md
# 说明:
# - 7a3f2d1:是提交的唯一版本号(哈希值前7位,用于定位版本);
# - 提交信息规范(推荐):类型: 描述(如feat-新功能、fix-修复bug、docs-文档修改等);
# - 如果未加-m参数,会自动打开编辑器(如vim)让你编写提交信息,编写后保存退出即可。
步骤4:查看提交历史(git log)
验证提交是否成功,查看所有版本记录:
bash
# 方式1:查看完整提交历史
git log
# 输出示例:
# commit 7a3f2d1e890b49e7a23f5d5e321a87556b8f123 (HEAD -> main)
# Author: Your Name <your.email@example.com>
# Date: Tue Oct 10 14:30:00 2023 +0800
#
# feat: 初始化项目,添加hello.c和README.md
# 方式2:简洁显示(仅显示版本号前7位和提交信息)
git log --oneline
# 输出:7a3f2d1 (HEAD -> main) feat: 初始化项目,添加hello.c和README.md
# 方式3:图形化显示(分支合并历史更清晰)
git log --graph --oneline
五、开始项目开发(核心操作)
项目导入仓库后,日常开发的核心流程:修改文件→查看变更→添加暂存→提交仓库→(可选)推送到远程。
1. 修改代码并提交(单文件修改)
步骤1:修改工作区文件
修改hello.c,增加新功能(输出版本信息):
c
#include <stdio.h>
int main() {
// 初始版本:输出Hello Git
printf("Hello Git! This is my first commit.\n");
// 新增功能:输出项目版本
printf("Project Version: v1.0.1\n"); // 新增代码行
return 0;
}
步骤2:查看文件变更(git diff)
确认修改内容,避免误改:
bash
# 查看工作区与暂存区的差异(未add的修改)
git diff hello.c
# 输出示例(+表示新增,-表示删除):
# 4,5d3
# < // 新增功能:输出项目版本
# < printf("Project Version: v1.0.1\n");
# 7a6
# > return 0;
# 说明:如果已执行git add,git diff无法查看差异,需用git diff --cached(查看暂存区与本地仓库的差异)
步骤3:添加到暂存区并提交
bash
# 1. 添加修改后的文件到暂存区
git add hello.c
# 2. 提交到本地仓库(提交信息说明修改内容)
git commit -m "feat: 新增版本输出功能,版本号v1.0.1"
# 3. 查看提交历史(验证提交)
git log --oneline
# 输出:
# 9b2d5c7 (HEAD -> main) feat: 新增版本输出功能,版本号v1.0.1
# 7a3f2d1 feat: 初始化项目,添加hello.c和README.md
2. 多文件修改提交
如果同时修改了多个文件(如hello.c和README.md),可批量提交:
bash
# 1. 修改README.md,更新版本说明
vim README.md
# 新增内容:"当前版本:v1.0.1(支持版本号输出)"
# 2. 查看所有文件的变更
git diff # 不指定文件名,查看所有修改文件的差异
# 3. 批量添加所有修改文件到暂存区
git add . # 谨慎使用!确保只添加需要提交的文件(避免添加临时文件)
# 4. 提交(提交信息概括所有修改)
git commit -m "docs: 更新README.md,添加v1.0.1版本说明"
# 5. 查看历史
git log --oneline
# 输出新增一条提交记录
3. 忽略不需要跟踪的文件(.gitignore)
项目中存在临时文件(如编译生成的.o、可执行文件、日志文件等),无需Git跟踪,通过.gitignore文件配置:
步骤1:创建.gitignore文件
bash
vim .gitignore
写入以下内容(C语言项目常用配置):
# 编译生成的可执行文件
hello
a.out
# 目标文件(.o)
*.o
# 日志文件
*.log
# 临时文件
*.tmp
.DS_Store # Mac系统临时文件
步骤2:添加并提交.gitignore
bash
git add .gitignore
git commit -m "chore: 添加.gitignore,忽略编译文件和临时文件"
说明:
-
.gitignore仅对「未跟踪文件」生效,如果文件已被Git跟踪(已add/commit),修改.gitignore无法忽略,需先移除跟踪:bash# 移除已跟踪文件的跟踪(不删除物理文件) git rm --cached 不需要跟踪的文件
六、解决冲突(多人协作核心)
冲突是多人协作中最常见的问题,当多个开发者修改同一文件的同一行代码 ,或同一分支的不同提交修改同一处时,Git无法自动合并,需手动解决。
1. 冲突产生场景(模拟多人协作)
假设两个开发者(A和B)同时基于main分支开发,流程如下:
开发者A的操作:
bash
# 1. 基于main分支创建新分支(模拟A的开发分支)
git checkout -b feature/A-dev # -b创建并切换分支
# 2. 修改hello.c的同一行(第4行)
vim hello.c
# 修改内容:printf("Hello Git! This is A's modification.\n");
# 3. 提交修改
git add hello.c
git commit -m "feat: A修改问候语"
# 4. 切换回main分支,准备合并
git checkout main
开发者B的操作(模拟另一人修改):
bash
# 1. 基于main分支创建新分支(模拟B的开发分支)
git checkout -b feature/B-dev
# 2. 修改hello.c的同一行(第4行,与A冲突)
vim hello.c
# 修改内容:printf("Hello Git! This is B's modification.\n");
# 3. 提交修改
git add hello.c
git commit -m "feat: B修改问候语"
# 4. 切换回main分支,准备合并
git checkout main
合并分支触发冲突:
bash
# 1. 先合并A的分支到main(无冲突)
git merge feature/A-dev
# 输出:Merge made by the 'ort' strategy. 成功合并
# 2. 再合并B的分支到main(触发冲突)
git merge feature/B-dev
# 输出提示冲突:
# Auto-merging hello.c
# CONFLICT (content): Merge conflict in hello.c
# Automatic merge failed; fix conflicts and then commit the result.
2. 解决冲突的步骤
步骤1:查看冲突状态
bash
git status
# 输出:
# You have unmerged paths.(存在未合并路径)
# (fix conflicts and run "git commit")
# Unmerged paths:
# both modified: hello.c(双方都修改了hello.c)
步骤2:编辑冲突文件(核心)
打开冲突文件hello.c,Git会用特殊标记标注冲突位置:
c
#include <stdio.h>
int main() {
// 冲突位置:A和B修改了同一行
<<<<<<< HEAD // HEAD表示当前分支(main)的内容(A的修改)
printf("Hello Git! This is A's modification.\n");
=======
printf("Hello Git! This is B's modification.\n");
>>>>>>> feature/B-dev // 待合并分支(B的分支)的内容
printf("Project Version: v1.0.1\n");
return 0;
}
步骤3:手动解决冲突
删除冲突标记(<<<<<<<、=======、>>>>>>>),修改为最终需要的内容(如协商后保留两者的修改,或选择其一):
c
#include <stdio.h>
int main() {
// 解决冲突:保留A和B的修改,添加标注
printf("Hello Git! This is A's modification.\n");
printf("Hello Git! This is B's modification.\n");
printf("Project Version: v1.0.1\n");
return 0;
}
步骤4:提交解决后的代码
bash
# 1. 添加解决冲突后的文件到暂存区
git add hello.c
# 2. 提交合并结果(无需写-m,Git自动生成合并提交信息)
git commit
# 自动打开编辑器,保存默认信息即可(或手动修改)
# 3. 验证冲突解决成功
git log --oneline --graph
# 输出会显示合并记录,分支已合并到main
3. 冲突预防技巧
- 频繁同步:多人协作时,每天开发前拉取(
git pull)远程分支最新代码; - 细分功能:每个分支只开发一个小功能,减少同一文件的修改频率;
- 及时提交:完成一个功能就提交,避免大量代码堆积后合并;
- 沟通协调:避免多人同时修改同一文件的同一部分(提前沟通分工)。
七、撤销修改(误操作补救)
开发中难免出现误修改、误提交,Git提供多种撤销方案,需根据「修改所处阶段」选择对应命令。
场景1:工作区修改(未执行git add)
误修改了文件,但还没添加到暂存区,想放弃修改,恢复到最近一次提交的状态:
bash
# 示例:误修改了hello.c,未git add
git status # 确认状态:modified: hello.c(未add)
# 撤销单个文件的修改(核心命令)
git checkout -- hello.c
# 撤销当前目录所有文件的修改(谨慎使用)
git checkout -- .
# 验证:文件已恢复到最近提交的版本
git status # 输出:nothing to commit, working tree clean
场景2:暂存区修改(已git add,未git commit)
已执行git add将修改添加到暂存区,但想撤销暂存,恢复到工作区未add的状态:
bash
# 示例:已git add hello.c,未commit
git status # 确认状态:Changes to be committed: modified: hello.c
# 撤销暂存(核心命令:git reset HEAD <文件>)
git reset HEAD hello.c
# 验证:暂存区已撤销,修改回到工作区
git status # 输出:modified: hello.c(未add状态)
# (可选)如果想同时放弃工作区的修改,再执行场景1的命令
git checkout -- hello.c
场景3:本地仓库提交(已git commit,未推送到远程)
已提交到本地仓库,但发现提交错误(如提交信息写错、漏改代码),想撤销该提交:
方式1:修正最近一次提交(推荐,不删除历史)
如果只是提交信息错误,或漏加文件,可修正最近一次提交:
bash
# 1. 补充修改(如漏加的文件,或修正代码)
git add 漏加的文件 # 如有漏加文件
# 2. 修正最近一次提交(--amend修改上一次提交)
git commit --amend
# 自动打开编辑器,修改提交信息,保存退出即可
# 验证:提交历史中,上一次提交已被替换(无新提交记录)
git log --oneline
方式2:回滚到指定版本(删除提交历史,谨慎使用)
如果提交的代码有严重bug,想彻底删除该提交,回滚到之前的版本:
bash
# 1. 查看提交历史,找到要回滚的目标版本号(如7a3f2d1)
git log --oneline # 输出:9b2d5c7(错误提交)、7a3f2d1(目标版本)
# 2. 回滚到目标版本(--hard:彻底覆盖工作区和暂存区,谨慎使用!)
git reset --hard 7a3f2d1
# 验证:提交历史已删除错误提交,文件恢复到目标版本
git log --oneline # 输出仅显示7a3f2d1及之前的提交
场景4:已推送到远程仓库(git push后)
如果错误提交已推送到远程仓库(如GitHub),切勿使用git reset (会导致多人协作冲突),应使用git revert创建新提交,撤销旧提交的修改:
bash
# 1. 查看远程提交历史,找到错误提交的版本号(如9b2d5c7)
git log --oneline
# 2. 撤销指定提交(核心命令:git revert 版本号)
git revert 9b2d5c7
# 自动打开编辑器,编写撤销提交的信息(默认即可),保存退出
# 3. 推送撤销提交到远程仓库
git push origin main
# 说明:
# - git revert不会删除历史提交,而是新增一个"撤销提交",安全可靠;
# - 远程仓库的错误提交依然存在,但修改已被撤销。
撤销操作总结表
| 场景 | 推荐命令 | 风险等级 |
|---|---|---|
| 工作区修改(未add) | git checkout -- <文件> | 低 |
| 暂存区修改(已add未commit) | git reset HEAD <文件> + git checkout -- <文件> | 低 |
| 本地提交(未push)- 修正信息 | git commit --amend | 中 |
| 本地提交(未push)- 删除提交 | git reset --hard <版本号> | 高 |
| 远程提交(已push) | git revert <版本号> + git push | 低 |
八、Git命令汇总(分类整理)
1. 配置类
| 命令 | 功能描述 |
|---|---|
| git config --global user.name "姓名" | 配置全局用户名 |
| git config --global user.email "邮箱" | 配置全局邮箱 |
| git config --global core.editor "vim" | 配置默认编辑器 |
| git config --global --list | 查看全局配置 |
| git config --list | 查看当前仓库配置(全局+本地) |
2. 仓库操作类
| 命令 | 功能描述 |
|---|---|
| git init | 初始化本地仓库 |
| git clone <远程URL> [本地目录] | 克隆远程仓库到本地 |
| git remote -v | 查看远程仓库关联(origin是默认别名) |
| git remote add <别名> <远程URL> | 添加远程仓库关联(如git remote add origin ) |
| git remote remove <别名> | 删除远程仓库关联 |
3. 提交相关类
| 命令 | 功能描述 |
|---|---|
| git status | 查看工作区、暂存区状态 |
| git diff [<文件>] | 查看工作区与暂存区的差异 |
| git diff --cached [<文件>] | 查看暂存区与本地仓库的差异 |
| git add <文件> / git add . | 添加文件到暂存区 |
| git commit -m "提交信息" | 提交暂存区到本地仓库 |
| git commit --amend | 修正最近一次提交 |
| git log | 查看提交历史(完整) |
| git log --oneline | 简洁查看提交历史(版本号+信息) |
| git log --graph --oneline | 图形化查看提交历史(分支合并清晰) |
4. 分支操作类
| 命令 | 功能描述 |
|---|---|
| git branch | 查看所有本地分支(*表示当前分支) |
| git branch <分支名> | 创建新分支 |
| git checkout <分支名> | 切换分支 |
| git checkout -b <分支名> | 创建并切换分支 |
| git merge <分支名> | 合并指定分支到当前分支 |
| git branch -d <分支名> | 删除已合并的分支 |
| git branch -D <分支名> | 强制删除未合并的分支 |
5. 冲突解决类
| 命令 | 功能描述 |
|---|---|
| git status | 查看冲突文件 |
| git add <冲突文件> | 解决冲突后添加到暂存区 |
| git commit | 提交冲突解决结果 |
6. 撤销修改类
| 命令 | 功能描述 |
|---|---|
| git checkout -- <文件> | 撤销工作区修改(未add) |
| git reset HEAD <文件> | 撤销暂存区修改(已add未commit) |
| git reset --hard <版本号> | 回滚到指定版本(本地未push) |
| git revert <版本号> | 撤销指定提交(已push到远程) |
7. 远程协作类
| 命令 | 功能描述 |
|---|---|
| git pull <远程别名> <分支名> | 拉取远程分支最新代码并合并(如git pull origin main) |
| git push <远程别名> <分支名> | 推送本地分支到远程仓库(如git push origin main) |
| git push -u <远程别名> <分支名> | 推送并关联远程分支(后续可直接git push) |
九、本章小结
本章详细讲解了Ubuntu 22.04中Git版本控制系统的核心知识点与实战操作,核心要点总结如下:
- 基础认知:Git是分布式版本控制工具,核心优势是本地仓库完整、分支灵活、协作高效,核心流程是「工作区→暂存区→本地仓库→远程仓库」;
- 环境配置:通过APT快速安装Git,必须配置用户名和邮箱(标识提交者),可根据需求配置全局或本地参数;
- 仓库操作 :支持本地新建仓库(
git init)和克隆远程仓库(git clone),.git文件夹是仓库核心,切勿手动修改; - 日常开发 :修改文件后通过
git add添加到暂存区,git commit提交到本地仓库,git log查看历史,git diff查看变更; - 冲突解决 :多人协作时冲突不可避免,需通过编辑冲突文件(删除冲突标记、协商内容)→
git add→git commit完成解决,预防冲突的关键是频繁同步和细分功能; - 撤销修改 :根据修改所处阶段(工作区、暂存区、本地仓库、远程仓库)选择对应命令,已推送远程的修改优先使用
git revert(安全无风险); - 核心命令:掌握配置、提交、分支、冲突解决、撤销修改的核心命令,可满足日常开发和协作需求。
Git是程序员必备工具,建议在实际项目中多练习(如搭建个人GitHub仓库、模拟多人协作),熟练掌握后可大幅提升开发效率和代码管理能力。实际工作中,结合远程仓库(GitHub、GitLab)可实现跨团队协作、代码备份和版本管理,是大型项目开发的基础。