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安装即可,步骤如下:
# 1. 更新软件源(确保获取最新版本)sudoaptupdate# 2. 安装Git(-y自动确认安装)sudoaptinstall-ygit# 3. 验证安装是否成功(查看版本号,Ubuntu 22.04默认3.2.0+)git--version# 输出示例:git version 2.34.1(版本号可能因系统更新略有差异)2. Git基础配置(必须步骤)
Git需要配置用户信息(用户名、邮箱),用于标识提交者身份,配置分为「全局配置」和「本地配置」:
- 全局配置:所有本地仓库共用(推荐优先配置);
- 本地配置:仅当前仓库生效(优先级高于全局配置)。
2.1 全局配置(常用)
# 1. 配置全局用户名(替换为你的用户名,如GitHub用户名)gitconfig--globaluser.name"Your Name"# 2. 配置全局邮箱(替换为你的邮箱,如GitHub注册邮箱)gitconfig--globaluser.email"your.email@example.com"# 3. (可选)配置默认文本编辑器(解决冲突、编写提交信息时使用)# 可选编辑器:vim、nano、code(VS Code)等,这里以vim为例gitconfig--globalcore.editor"vim"# 4. (可选)配置中文显示(解决中文文件名乱码问题)gitconfig--globalcore.quotepathfalse# 5. 验证配置是否生效(查看所有全局配置)gitconfig--global--list# 输出示例:# user.name=Your Name# user.email=your.email@example.com# core.editor=vim# core.quotepath=false2.2 本地配置(针对单个仓库)
如果某个仓库需要单独配置用户信息(如工作仓库用公司邮箱),进入仓库目录后执行:
# 1. 进入目标仓库目录(先创建或克隆仓库,后续章节讲解)cd~/projects/my-project# 2. 配置本地用户名和邮箱(覆盖全局配置)gitconfig user.name"Work Name"gitconfig user.email"work.email@company.com"# 3. 查看本地配置gitconfig--list# 输出会包含全局配置+本地配置(本地配置优先级更高)2.3 配置文件位置
- 全局配置文件:
~/.gitconfig(可直接编辑修改); - 本地配置文件:
仓库目录/.git/config(仓库内生效)。
三、建立项目仓库
Git仓库分为「本地仓库」和「远程仓库」,核心流程:本地仓库可独立使用,也可关联远程仓库实现协作/备份。
1. 本地新建仓库(从零开始)
适用于全新项目,步骤如下:
# 1. 创建项目目录(自定义名称和路径)mkdir-p~/projects/git-demo# -p确保父目录存在cd~/projects/git-demo# 进入项目目录# 2. 初始化本地仓库(关键命令:在目录中创建.git文件夹)gitinit# 输出:Initialized empty Git repository in /home/yourname/projects/git-demo/.git/# 3. 查看仓库状态(验证初始化成功)gitstatus# 输出:On branch main(默认分支main)# No commits yet(暂无提交)# nothing to commit(无待提交文件)# 说明:.git文件夹是本地仓库核心,存储所有版本历史、配置等,切勿手动修改/删除2. 克隆远程仓库(从远程导入)
适用于已有远程仓库(如GitHub、GitLab上的项目),通过git clone复制到本地:
# 1. 克隆公开仓库(以GitHub上的测试仓库为例)# 格式:git clone 远程仓库URL [本地目录名(可选)]gitclone https://github.com/octocat/Hello-World.git ~/projects/hello-world# 2. 进入克隆后的仓库目录cd~/projects/hello-world# 3. 查看仓库信息(验证克隆成功)gitstatus# 输出:On branch main# Your branch is up to date with 'origin/main'(与远程分支同步)# 4. 查看远程仓库关联(origin是远程仓库的默认别名)gitremote-v# 输出:# origin https://github.com/octocat/Hello-World.git (fetch)# origin https://github.com/octocat/Hello-World.git (push)# 说明:克隆仓库会自动完成3件事:# - 创建本地仓库目录;# - 初始化本地仓库(.git文件夹);# - 关联远程仓库(别名origin);# - 拉取远程仓库的所有代码和历史版本。克隆私有仓库(需身份验证)
如果远程仓库是私有(如公司GitLab仓库),克隆时需输入用户名和密码,或配置SSH密钥(免密登录):
# 方式1:HTTPS协议(输入用户名+密码)gitclone https://username@gitlab.company.com/team/project.git# 方式2:SSH协议(需提前配置SSH密钥,免密登录)# 1. 生成SSH密钥(默认路径~/.ssh/id_rsa)ssh-keygen-trsa-C"your.work.email@company.com"# 按回车默认即可,无需设置密码# 2. 查看公钥内容(复制到远程仓库的SSH密钥配置中)cat~/.ssh/id_rsa.pub# 复制输出的所有内容(以ssh-rsa开头,以邮箱结尾)# 3. 克隆私有仓库(SSH协议)gitclone git@gitlab.company.com:team/project.git四、创建项目并导入源代码
新建仓库后,需将项目文件(源代码、配置文件等)导入仓库,核心步骤:工作区→暂存区→本地仓库。
1. 创建示例项目文件
以C语言项目为例,创建源代码文件和说明文档:
// 1. 创建主程序文件hello.c(带详细注释)vim hello.c写入以下代码:
#include<stdio.h>intmain(){// 初始版本:输出Hello Gitprintf("Hello Git! This is my first commit.\n");return0;}# 2. 创建项目说明文档README.mdvimREADME.md写入:
# Git Demo 项目 这是一个用于演示Git版本控制的C语言项目。 核心功能:输出问候语,展示Git的提交、修改、冲突解决等操作。2. 导入文件到本地仓库(三步曲)
Git导入文件需经过「添加到暂存区」和「提交到本地仓库」两个关键步骤:
步骤1:查看文件状态(git status)
# 查看当前工作区和暂存区状态gitstatus# 输出:# Untracked files:(未跟踪文件:Git未管理的新文件)# hello.c# README.md# 提示:使用git add <file>将文件添加到暂存区步骤2:添加到暂存区(git add)
将需要跟踪的文件添加到暂存区(可单个文件、多个文件或所有文件):
# 方式1:添加单个文件gitaddhello.c# 方式2:添加多个文件(空格分隔)gitaddhello.c README.md# 方式3:添加当前目录所有文件(常用,注意不要添加临时文件)gitadd.# "." 代表当前目录# 再次查看状态(验证添加成功)gitstatus# 输出:# Changes to be committed:(待提交文件:已在暂存区)# new file: hello.c# new file: README.md步骤3:提交到本地仓库(git commit)
将暂存区的文件永久保存到本地仓库,生成唯一版本记录,必须填写提交信息(描述修改内容):
# 基本格式:git commit -m "提交信息"(-m指定提交说明)gitcommit-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)
验证提交是否成功,查看所有版本记录:
# 方式1:查看完整提交历史gitlog# 输出示例:# 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位和提交信息)gitlog--oneline# 输出:7a3f2d1 (HEAD -> main) feat: 初始化项目,添加hello.c和README.md# 方式3:图形化显示(分支合并历史更清晰)gitlog--graph--oneline五、开始项目开发(核心操作)
项目导入仓库后,日常开发的核心流程:修改文件→查看变更→添加暂存→提交仓库→(可选)推送到远程。
1. 修改代码并提交(单文件修改)
步骤1:修改工作区文件
修改hello.c,增加新功能(输出版本信息):
#include<stdio.h>intmain(){// 初始版本:输出Hello Gitprintf("Hello Git! This is my first commit.\n");// 新增功能:输出项目版本printf("Project Version: v1.0.1\n");// 新增代码行return0;}步骤2:查看文件变更(git diff)
确认修改内容,避免误改:
# 查看工作区与暂存区的差异(未add的修改)gitdiffhello.c# 输出示例(+表示新增,-表示删除):# 4,5d3# < // 新增功能:输出项目版本# < printf("Project Version: v1.0.1\n");# 7a6# > return 0;# 说明:如果已执行git add,git diff无法查看差异,需用git diff --cached(查看暂存区与本地仓库的差异)步骤3:添加到暂存区并提交
# 1. 添加修改后的文件到暂存区gitaddhello.c# 2. 提交到本地仓库(提交信息说明修改内容)gitcommit-m"feat: 新增版本输出功能,版本号v1.0.1"# 3. 查看提交历史(验证提交)gitlog--oneline# 输出:# 9b2d5c7 (HEAD -> main) feat: 新增版本输出功能,版本号v1.0.1# 7a3f2d1 feat: 初始化项目,添加hello.c和README.md2. 多文件修改提交
如果同时修改了多个文件(如hello.c和README.md),可批量提交:
# 1. 修改README.md,更新版本说明vimREADME.md# 新增内容:"当前版本:v1.0.1(支持版本号输出)"# 2. 查看所有文件的变更gitdiff# 不指定文件名,查看所有修改文件的差异# 3. 批量添加所有修改文件到暂存区gitadd.# 谨慎使用!确保只添加需要提交的文件(避免添加临时文件)# 4. 提交(提交信息概括所有修改)gitcommit-m"docs: 更新README.md,添加v1.0.1版本说明"# 5. 查看历史gitlog--oneline# 输出新增一条提交记录3. 忽略不需要跟踪的文件(.gitignore)
项目中存在临时文件(如编译生成的.o、可执行文件、日志文件等),无需Git跟踪,通过.gitignore文件配置:
步骤1:创建.gitignore文件
vim.gitignore写入以下内容(C语言项目常用配置):
# 编译生成的可执行文件 hello a.out # 目标文件(.o) *.o # 日志文件 *.log # 临时文件 *.tmp .DS_Store # Mac系统临时文件步骤2:添加并提交.gitignore
gitadd.gitignoregitcommit-m"chore: 添加.gitignore,忽略编译文件和临时文件"说明:
.gitignore仅对「未跟踪文件」生效,如果文件已被Git跟踪(已add/commit),修改.gitignore无法忽略,需先移除跟踪:# 移除已跟踪文件的跟踪(不删除物理文件)gitrm--cached不需要跟踪的文件
六、解决冲突(多人协作核心)
冲突是多人协作中最常见的问题,当多个开发者修改同一文件的同一行代码,或同一分支的不同提交修改同一处时,Git无法自动合并,需手动解决。
1. 冲突产生场景(模拟多人协作)
假设两个开发者(A和B)同时基于main分支开发,流程如下:
开发者A的操作:
# 1. 基于main分支创建新分支(模拟A的开发分支)gitcheckout-bfeature/A-dev# -b创建并切换分支# 2. 修改hello.c的同一行(第4行)vimhello.c# 修改内容:printf("Hello Git! This is A's modification.\n");# 3. 提交修改gitaddhello.cgitcommit-m"feat: A修改问候语"# 4. 切换回main分支,准备合并gitcheckout main开发者B的操作(模拟另一人修改):
# 1. 基于main分支创建新分支(模拟B的开发分支)gitcheckout-bfeature/B-dev# 2. 修改hello.c的同一行(第4行,与A冲突)vimhello.c# 修改内容:printf("Hello Git! This is B's modification.\n");# 3. 提交修改gitaddhello.cgitcommit-m"feat: B修改问候语"# 4. 切换回main分支,准备合并gitcheckout main合并分支触发冲突:
# 1. 先合并A的分支到main(无冲突)gitmerge feature/A-dev# 输出:Merge made by the 'ort' strategy. 成功合并# 2. 再合并B的分支到main(触发冲突)gitmerge 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:查看冲突状态
gitstatus# 输出:# You have unmerged paths.(存在未合并路径)# (fix conflicts and run "git commit")# Unmerged paths:# both modified: hello.c(双方都修改了hello.c)步骤2:编辑冲突文件(核心)
打开冲突文件hello.c,Git会用特殊标记标注冲突位置:
#include<stdio.h>intmain(){// 冲突位置: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");return0;}步骤3:手动解决冲突
删除冲突标记(<<<<<<<、=======、>>>>>>>),修改为最终需要的内容(如协商后保留两者的修改,或选择其一):
#include<stdio.h>intmain(){// 解决冲突:保留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");return0;}步骤4:提交解决后的代码
# 1. 添加解决冲突后的文件到暂存区gitaddhello.c# 2. 提交合并结果(无需写-m,Git自动生成合并提交信息)gitcommit# 自动打开编辑器,保存默认信息即可(或手动修改)# 3. 验证冲突解决成功gitlog--oneline--graph# 输出会显示合并记录,分支已合并到main3. 冲突预防技巧
- 频繁同步:多人协作时,每天开发前拉取(
git pull)远程分支最新代码; - 细分功能:每个分支只开发一个小功能,减少同一文件的修改频率;
- 及时提交:完成一个功能就提交,避免大量代码堆积后合并;
- 沟通协调:避免多人同时修改同一文件的同一部分(提前沟通分工)。
七、撤销修改(误操作补救)
开发中难免出现误修改、误提交,Git提供多种撤销方案,需根据「修改所处阶段」选择对应命令。
场景1:工作区修改(未执行git add)
误修改了文件,但还没添加到暂存区,想放弃修改,恢复到最近一次提交的状态:
# 示例:误修改了hello.c,未git addgitstatus# 确认状态:modified: hello.c(未add)# 撤销单个文件的修改(核心命令)gitcheckout -- hello.c# 撤销当前目录所有文件的修改(谨慎使用)gitcheckout --.# 验证:文件已恢复到最近提交的版本gitstatus# 输出:nothing to commit, working tree clean场景2:暂存区修改(已git add,未git commit)
已执行git add将修改添加到暂存区,但想撤销暂存,恢复到工作区未add的状态:
# 示例:已git add hello.c,未commitgitstatus# 确认状态:Changes to be committed: modified: hello.c# 撤销暂存(核心命令:git reset HEAD <文件>)gitreset HEAD hello.c# 验证:暂存区已撤销,修改回到工作区gitstatus# 输出:modified: hello.c(未add状态)# (可选)如果想同时放弃工作区的修改,再执行场景1的命令gitcheckout -- hello.c场景3:本地仓库提交(已git commit,未推送到远程)
已提交到本地仓库,但发现提交错误(如提交信息写错、漏改代码),想撤销该提交:
方式1:修正最近一次提交(推荐,不删除历史)
如果只是提交信息错误,或漏加文件,可修正最近一次提交:
# 1. 补充修改(如漏加的文件,或修正代码)gitadd漏加的文件# 如有漏加文件# 2. 修正最近一次提交(--amend修改上一次提交)gitcommit--amend# 自动打开编辑器,修改提交信息,保存退出即可# 验证:提交历史中,上一次提交已被替换(无新提交记录)gitlog--oneline方式2:回滚到指定版本(删除提交历史,谨慎使用)
如果提交的代码有严重bug,想彻底删除该提交,回滚到之前的版本:
# 1. 查看提交历史,找到要回滚的目标版本号(如7a3f2d1)gitlog--oneline# 输出:9b2d5c7(错误提交)、7a3f2d1(目标版本)# 2. 回滚到目标版本(--hard:彻底覆盖工作区和暂存区,谨慎使用!)gitreset--hard7a3f2d1# 验证:提交历史已删除错误提交,文件恢复到目标版本gitlog--oneline# 输出仅显示7a3f2d1及之前的提交场景4:已推送到远程仓库(git push后)
如果错误提交已推送到远程仓库(如GitHub),切勿使用git reset(会导致多人协作冲突),应使用git revert创建新提交,撤销旧提交的修改:
# 1. 查看远程提交历史,找到错误提交的版本号(如9b2d5c7)gitlog--oneline# 2. 撤销指定提交(核心命令:git revert 版本号)gitrevert 9b2d5c7# 自动打开编辑器,编写撤销提交的信息(默认即可),保存退出# 3. 推送撤销提交到远程仓库gitpush 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)可实现跨团队协作、代码备份和版本管理,是大型项目开发的基础。