Linux开发工具详解(二):Git版本控制、GitHub协作与GDB调试实战

Linux开发工具详解(二):Git版本控制、GitHub协作与GDB调试实战


🔥 星恒随风: 个人主页 ❄️ 个人专栏: 《指针合集》 | 《C语言基础》 | 《数据结构》 | 《机器学习导论》 | 《前端基础》 | 《python基础》 | 《C++从入门到入土》 | 《Linux的学习之旅》 ✨ 数据即知识,压缩即智能


文章目录

前言:写完代码以后还有两个问题

1. 代码怎么管理?

一个项目开发过程中会不断出现:

text 复制代码
第一次能运行
第二次加功能
第三次改接口
第四次修Bug
第五次重构

如果使用最原始的方法:

text 复制代码
project-v1

project-v2

project-v3

project-final

project-final2

project-真最终版

很快就会遇到:

text 复制代码
哪个版本改了什么?

什么时候改的?

谁改的?

还能不能回去?

两个人怎么同时开发?

因此需要:

text 复制代码
版本控制系统

2. Bug怎么定位?

程序运行结果错误:

text 复制代码
Expected: 5050
Actual:   0

只靠:

cpp 复制代码
printf("here1\n");
printf("here2\n");
printf("x=%d\n", x);

当然也能调试。

但复杂程序中,我们更希望:

text 复制代码
让程序停在指定位置
单步执行
进入函数
查看变量
修改变量
查看调用栈
观察变量何时变化

这就是:

text 复制代码
GDB

解决的问题。

所以这一篇的主线就是:

text 复制代码
Git
↓
管理代码历史

GDB
↓
定位代码问题

一、什么是版本控制?

1. 版本控制解决什么?

版本控制系统可以记录:

text 复制代码
谁
在什么时候
修改了哪些文件
具体改了什么
为什么修改

并允许:

text 复制代码
查看历史
回退版本
创建分支
合并代码
多人协作

2. Git是什么?

Git 是一个:

text 复制代码
分布式版本控制系统

"分布式"非常重要。

传统集中式系统更多依赖:

text 复制代码
中央服务器

而 Git 每个完整克隆通常都拥有:

text 复制代码
完整版本历史

所以本地也可以进行大量操作:

text 复制代码
commit
log
diff
branch

并不要求时刻连接 GitHub。


二、Git和GitHub不是同一个东西

1. Git

Git 是:

text 复制代码
版本控制工具

安装在本地。


2. GitHub

GitHub 是:

text 复制代码
Git 代码托管与协作平台

除此之外还提供:

text 复制代码
Issue
Pull Request
Actions
Release
Code Review

等能力。

所以:

text 复制代码
Git != GitHub

关系更接近:

text 复制代码
Git
↓
版本控制协议与工具

GitHub
↓
基于Git的远程托管与协作平台

三、安装Git

1. Ubuntu

bash 复制代码
sudo apt update
sudo apt install -y git

2. Fedora / RHEL

bash 复制代码
sudo dnf install -y git

旧 CentOS:

bash 复制代码
sudo yum install -y git

检查:

bash 复制代码
git --version

四、第一次使用Git要配置身份

1. 配置用户名

bash 复制代码
git config \
    --global \
    user.name \
    "Your Name"

2. 配置邮箱

bash 复制代码
git config \
    --global \
    user.email \
    "you@example.com"

查看:

bash 复制代码
git config --global --list

这些信息会进入:

text 复制代码
Commit Metadata

用于标识:

text 复制代码
谁进行了这次提交

五、Git最重要的四个区域

1. 工作区

就是你真实看到和编辑的文件:

text 复制代码
main.c
Makefile
README.md

2. 暂存区

也叫:

text 复制代码
Index
Staging Area

作用是:

text 复制代码
准备"下一次 commit 到底包含哪些内容"

3. 本地仓库

执行:

bash 复制代码
git commit

之后,提交记录进入:

text 复制代码
Local Repository

4. 远程仓库

例如:

text 复制代码
GitHub

对应常见远端名字:

text 复制代码
origin

六、Git数据流一定要理解

text 复制代码
Working Tree
     |
     | git add
     v
Staging Area
     |
     | git commit
     v
Local Repository
     |
     | git push
     v
Remote Repository

这张图几乎可以解释:

text 复制代码
80%的Git入门问题

七、git add到底在干什么?

1. 它不是"提交代码"

例如:

bash 复制代码
git add main.c

只是:

text 复制代码
把当前 main.c 的内容
加入暂存区

准备参加:

text 复制代码
下一次 commit

2. 添加所有变化

bash 复制代码
git add .

初学阶段非常常见。

但在实际项目中,提交前建议先:

bash 复制代码
git status

确认到底有哪些文件会被提交。


八、git commit是什么?

bash 复制代码
git commit \
    -m "fix: correct progress calculation"

意思是:

text 复制代码
把当前暂存区的状态
记录为一个新的本地版本

所以:

text 复制代码
commit

本质更接近:

text 复制代码
创建项目历史快照

九、commit message应该怎么写?

1. 不推荐

text 复制代码
update
修改代码
123
test
aaa

过几个月以后几乎无法理解。


2. 更推荐

例如:

text 复制代码
fix: prevent division by zero

feat: add progress bar

refactor: split process module

docs: update README

让别人看到历史时能够快速知道:

text 复制代码
为什么改

十、git push是什么?

执行:

bash 复制代码
git push

意味着:

text 复制代码
把本地提交
同步到远程仓库

第一次绑定上游分支时可能使用:

bash 复制代码
git push -u origin main

以后:

bash 复制代码
git push

即可。


十一、2026年使用GitHub要注意认证方式

1. 不要再使用GitHub账户密码进行Git认证

GitHub 已经不再支持:

text 复制代码
用户名 + GitHub登录密码

完成 Git 的 HTTPS 操作认证。

现在常见方法有:

text 复制代码
SSH

Personal Access Token

GitHub CLI

Git Credential Manager

2. HTTPS方式

远程地址类似:

text 复制代码
https://github.com/user/project.git

如果命令行要求输入 Password:

text 复制代码
不是输入GitHub登录密码

而是使用PAT等认证方式

3. SSH方式

远程地址类似:

text 复制代码
git@github.com:user/project.git

比较适合:

text 复制代码
长期在自己的开发机器上使用

配置完成后:

bash 复制代码
git pull
git push

都比较方便。


十二、git clone:把远程仓库复制到本地

bash 复制代码
git clone <repository>

结果大致是:

text 复制代码
远程 GitHub 仓库
        ↓
    git clone
        ↓
本地工作区 + .git仓库

进入:

bash 复制代码
cd project

即可开始开发。


十三、本地已有项目如何接入Git?

1. 初始化

bash 复制代码
git init

2. 添加文件

bash 复制代码
git add .

3. 第一次提交

bash 复制代码
git commit \
    -m "init: initial project"

4. 添加远端

bash 复制代码
git remote add origin <repository>

查看:

bash 复制代码
git remote -v

5. 推送

bash 复制代码
git push -u origin main

具体默认分支可能取决于:

text 复制代码
仓库配置
Git版本
项目设置

所以遇到问题先:

bash 复制代码
git branch

确认本地分支名称。


十四、git status:最应该频繁使用的命令

执行:

bash 复制代码
git status

可以看到:

text 复制代码
当前在哪个分支

哪些文件被修改

哪些文件未跟踪

哪些修改已经暂存

哪些修改还未暂存

初学 Git 时,遇到:

text 复制代码
我现在到底什么状态?

第一条命令应该就是:

bash 复制代码
git status

十五、git diff:提交前看看自己改了什么

1. 工作区与暂存区的差异

bash 复制代码
git diff

2. 暂存区与最近提交的差异

bash 复制代码
git diff --cached

因此一个不错的提交习惯是:

text 复制代码
修改代码
↓
git diff
↓
git add
↓
git diff --cached
↓
git commit

十六、git log:查看历史

bash 复制代码
git log

更紧凑:

bash 复制代码
git log --oneline

例如:

text 复制代码
7c19f20 fix: correct calculation
123af92 feat: add progress bar
98cb3ab init: initial project

这里每个提交都有一个:

text 复制代码
Commit Hash

用于唯一标识这次提交。


十七、git pull是什么?

bash 复制代码
git pull

用于:

text 复制代码
从远端获取更新
+
整合进当前分支

多人协作时:

text 复制代码
先 pull
再开发/提交

是一种常见流程。

但真实项目中还需要进一步理解:

text 复制代码
fetch
merge
rebase

之间的关系。

入门阶段先掌握:

text 复制代码
clone
status
add
commit
pull
push
log
diff

即可。


十八、.gitignore有什么用?

有些文件不应该提交:

text 复制代码
*.o
可执行文件
构建目录
IDE配置
日志文件
临时文件

例如:

gitignore 复制代码
*.o
*.out

build/

.vscode/

*.log

之后:

text 复制代码
Git默认忽略这些文件

十九、一个C/C++项目的.gitignore示例

gitignore 复制代码
# object files
*.o
*.obj

# executables
*.out
*.exe

# build directories
build/
cmake-build-*/

# debug files
*.core

# editor
.vscode/
.idea/

# temporary files
*.swp
*.tmp

二十、为什么Git要有暂存区?

很多人第一次接触 Git 会问:

text 复制代码
为什么不能直接:

修改
↓
commit

暂存区的价值在于:

text 复制代码
一次工作中可能改了很多东西

但你希望拆成:

text 复制代码
Commit 1
修Bug

Commit 2
修改文档

Commit 3
重构函数

于是可以:

text 复制代码
选择性 git add

让每个 Commit 更清晰。

甚至:

bash 复制代码
git add -p

可以按代码块选择:

text 复制代码
哪些修改进入下一次提交

二十一、Git分支的基本思想

1. 为什么需要分支?

假设:

text 复制代码
main

是稳定版本。

你要开发一个:

text 复制代码
progress-bar

新功能。

不希望开发到一半影响主线。

于是:

text 复制代码
main
  |
  o----o
       \
        o----o feature

2. 创建并切换分支

现代 Git:

bash 复制代码
git switch -c feature/progress

开发完成后:

bash 复制代码
git switch main

再根据团队流程:

text 复制代码
merge
Pull Request

整合代码。


二十二、从Git进入GDB:版本管理解决不了Bug本身

Git 可以告诉我们:

text 复制代码
代码什么时候变坏了
谁改了什么

但要真正回答:

text 复制代码
程序为什么得到错误结果?

需要:

text 复制代码
Debugger

Linux 下最经典的就是:

text 复制代码
GDB

二十三、GDB是什么?

GDB:

text 复制代码
GNU Debugger

可以帮助我们:

text 复制代码
设置断点
单步执行
查看变量
修改变量
查看栈帧
查看调用链
监视内存或变量变化

二十四、调试之前为什么要加-g?

假设:

bash 复制代码
gcc main.c -o app

程序当然可以运行。

但是 GDB 很难获得完整的:

text 复制代码
源文件
行号
变量名
类型

映射信息。

因此调试版本应该加入:

bash 复制代码
-g

例如:

bash 复制代码
gcc main.c \
    -g \
    -O0 \
    -Wall \
    -Wextra \
    -o app

其中:

text 复制代码
-g
↓
生成调试信息

-O0
↓
尽量减少优化造成的调试干扰

也可以根据需求考虑:

text 复制代码
-Og

二十五、启动GDB

bash 复制代码
gdb ./app

进入:

text 复制代码
(gdb)

退出:

gdb 复制代码
quit

或者:

text 复制代码
Ctrl + D

二十六、list:查看源代码

gdb 复制代码
list

简写:

gdb 复制代码
l

查看:

text 复制代码
main函数
gdb 复制代码
list main

查看指定文件:

gdb 复制代码
list main.c:20

二十七、break:设置断点

1. 按行号

gdb 复制代码
break 20

简写:

gdb 复制代码
b 20

2. 按函数

gdb 复制代码
break main
gdb 复制代码
break Sum

3. 文件加行号

gdb 复制代码
break main.c:20

适合:

text 复制代码
多文件工程

二十八、查看和管理断点

1. 查看

gdb 复制代码
info breakpoints

常见简写:

gdb 复制代码
i b

2. 删除

删除编号 2:

gdb 复制代码
delete 2

删除全部:

gdb 复制代码
delete

3. 禁用

gdb 复制代码
disable 2

4. 重新启用

gdb 复制代码
enable 2

二十九、run与continue

1. run

gdb 复制代码
run

简写:

gdb 复制代码
r

含义:

text 复制代码
从程序开头开始执行

直到:

text 复制代码
遇到断点
收到信号
程序结束

2. continue

gdb 复制代码
continue

简写:

gdb 复制代码
c

表示:

text 复制代码
从当前停止位置继续运行

直到下一个停止点。


三十、next与step:调试最常用的区别

假设:

c 复制代码
int n = Sum(1, 100);

1. next

gdb 复制代码
next

简称:

gdb 复制代码
n

执行:

text 复制代码
下一行

但遇到:

text 复制代码
函数调用

一般:

text 复制代码
不会进入函数内部

2. step

gdb 复制代码
step

简称:

gdb 复制代码
s

遇到:

text 复制代码
函数调用

会尝试进入:

text 复制代码
函数内部

3. 可以类比IDE

text 复制代码
next
≈ Step Over / F10

step
≈ Step Into / F11

三十一、finish:把当前函数执行完

如果已经进入:

text 复制代码
Sum()

但不想继续一行一行走:

gdb 复制代码
finish

作用:

text 复制代码
运行到当前函数返回

并通常显示返回值。


三十二、until:快速执行到后面

例如:

gdb 复制代码
until 30

可以让程序继续运行到:

text 复制代码
指定位置

在调试循环时比较方便。


三十三、print:查看表达式

查看变量:

gdb 复制代码
print result

简称:

gdb 复制代码
p result

也可以计算表达式:

gdb 复制代码
p start + end

甚至:

gdb 复制代码
p array[10]

三十四、display:每次暂停自动显示

gdb 复制代码
display i

之后每次程序停下:

text 复制代码
GDB都会自动输出 i

查看 display:

gdb 复制代码
info display

取消:

gdb 复制代码
undisplay 1

三十五、set var:临时修改程序变量

假设程序:

c 复制代码
int flag = 0;

导致:

text 复制代码
结果错误

调试时可以:

gdb 复制代码
set var flag = 1

再继续运行。

如果结果立刻恢复正常:

text 复制代码
说明 flag 很可能就是问题来源

这种方法非常适合:

text 复制代码
验证Bug假设

但注意:

text 复制代码
修改只发生在当前调试进程

源代码本身并没有被改

三十六、backtrace:查看调用栈

gdb 复制代码
backtrace

简称:

gdb 复制代码
bt

例如:

text 复制代码
#0 Divide()
#1 Calculate()
#2 Process()
#3 main()

它能回答:

程序到底是从哪一条调用链走到这里的?

在:

text 复制代码
崩溃
段错误
深层函数错误
递归

场景中非常重要。


三十七、info locals:查看当前局部变量

gdb 复制代码
info locals

可以一次看到:

text 复制代码
当前栈帧中的局部变量

相比逐个:

gdb 复制代码
p a
p b
p c

更方便。


三十八、watch:变量什么时候被改坏了?

这是一条非常有用的命令。

假设:

text 复制代码
result

本来应该保持正确。

但某个地方莫名其妙变了。

你不知道:

text 复制代码
是谁改的

可以:

gdb 复制代码
watch result

继续:

gdb 复制代码
continue

当 result 的值发生变化时:

text 复制代码
GDB会暂停程序

并显示:

text 复制代码
Old value
New value

这属于:

text 复制代码
Watchpoint
数据断点

非常适合:

text 复制代码
变量被意外修改
内存被错误覆盖
状态莫名变化

的 Bug。GDB 官方文档同样把 watchpoint 定义为在表达式值发生变化时停止程序。


三十九、条件断点

假设:

c 复制代码
for (int i = 0;
     i < 100000;
     ++i)
{
    Process(i);
}

Bug 只在:

text 复制代码
i == 30000

出现。

如果每次都停:

text 复制代码
完全不可用

所以可以:

gdb 复制代码
break main.c:20 if i == 30000

程序只有在:

text 复制代码
到达20行
并且
i == 30000

时才停止。

GDB 的断点可以附加条件,条件为真时才真正停下,这在循环和高频路径中特别有用。


四十、给已有断点添加条件

假设断点编号:

text 复制代码
2

可以:

gdb 复制代码
condition 2 i == 30

于是:

text 复制代码
Breakpoint 2

以后只在:

text 复制代码
i == 30

时生效。


四十一、GDB最常用命令速查

目的 命令
启动 gdb ./app
查看代码 list
设置断点 break
查看断点 info breakpoints
运行 run
继续 continue
单步不进入函数 next
单步进入函数 step
执行完当前函数 finish
查看变量 print
自动显示变量 display
修改变量 set var
查看调用栈 backtrace
查看局部变量 info locals
监视变量变化 watch
删除断点 delete
退出 quit

四十二、一个完整GDB调试案例

1. Bug代码

c 复制代码
#include <stdio.h>

int flag = 0;

int Sum(
    int start,
    int end)
{
    int result = 0;

    for (int i = start;
         i <= end;
         ++i)
    {
        result += i;
    }

    return result * flag;
}

int main(void)
{
    int start = 1;
    int end = 100;

    int ret =
        Sum(start, end);

    printf(
        "%d\n",
        ret
    );

    return 0;
}

我们期待:

text 复制代码
5050

实际:

text 复制代码
0

2. 编译调试版本

bash 复制代码
gcc main.c \
    -g \
    -O0 \
    -Wall \
    -Wextra \
    -o app

3. 启动

bash 复制代码
gdb ./app

4. main设置断点

gdb 复制代码
b main
r

5. 找到Sum调用位置

gdb 复制代码
l

然后:

gdb 复制代码
s

进入:

text 复制代码
Sum

6. 执行循环

可以:

gdb 复制代码
until

或者逐步:

gdb 复制代码
n

7. 查看result

gdb 复制代码
p result

得到:

text 复制代码
5050

说明:

text 复制代码
求和本身正确

8. 查看flag

gdb 复制代码
p flag

得到:

text 复制代码
0

于是我们怀疑:

text 复制代码
result * flag

就是问题。


9. 临时修改

gdb 复制代码
set var flag = 1

继续:

gdb 复制代码
n

最终:

text 复制代码
5050

此时就基本确认:

text 复制代码
Bug来自flag初始值

四十三、GDB调试思路比命令更重要

真正调试时不要:

text 复制代码
程序一错
↓
从第一行开始next
↓
一直按几百次

更高效的思路应该是:

text 复制代码
观察错误现象
↓
提出假设
↓
确定可疑代码区域
↓
设置断点
↓
观察关键变量
↓
缩小范围
↓
验证假设

GDB 只是:

text 复制代码
验证假设的工具

而不是:

text 复制代码
自动帮你找到Bug的魔法

四十四、什么是CGDB?

CGDB 可以理解成:

text 复制代码
GDB
+
更方便查看源码的终端界面

如果纯 GDB 的:

text 复制代码
list

使用起来不够直观,可以尝试:

text 复制代码
CGDB

但学习阶段仍建议先掌握原生 GDB 的:

text 复制代码
break
run
next
step
print
watch
bt

因为这些调试思想在:

text 复制代码
VS
VSCode
CLion
GDB
LLDB

中都是共通的。


四十五、Git和GDB如何形成完整工作流?

可以形成:

text 复制代码
拉取代码
   ↓
git pull
   ↓
编辑代码
   ↓
Vim / VSCode
   ↓
编译
   ↓
gcc / g++
   ↓
程序出现Bug
   ↓
GDB
   ↓
修复Bug
   ↓
重新测试
   ↓
git diff
   ↓
git add
   ↓
git commit
   ↓
git push

这已经是一套最基础的:

text 复制代码
真实开发流程

四十六、一套推荐的日常Git工作流程

bash 复制代码
git status

git pull

# 修改代码

git diff

# 编译和测试

git status

git add .

git diff --cached

git commit \
    -m "fix: correct sum calculation"

git push

随着项目复杂度提高,再继续学习:

text 复制代码
branch
merge
rebase
stash
tag
reset
revert
cherry-pick

即可。


四十七、Git与GDB最容易混淆的几个问题

1. git add不是提交

text 复制代码
git add
↓
暂存

git commit
↓
本地提交

git push
↓
上传远程

2. commit不等于GitHub已经更新

只执行:

bash 复制代码
git commit

代码仍然主要在:

text 复制代码
本地仓库

还需要:

bash 复制代码
git push

才能同步到远程。


3. GitHub密码不能再直接用于git push

HTTPS:

text 复制代码
PAT / GitHub CLI / Credential Manager

或者:

text 复制代码
SSH

而不是账户登录密码。


4. 没有-g也能用GDB,但调试体验会很差

没有调试信息时:

text 复制代码
源码行号
变量名
函数信息

可能大量缺失。

所以:

bash 复制代码
-g

是源码级调试的核心选项。


5. next和step区别

text 复制代码
next
↓
不进入函数

step
↓
进入函数

这是最需要记住的一组。


6. watch和display不是一回事

text 复制代码
display x
↓
每次程序停下时显示x

watch x
↓
x发生变化时让程序停下

四十八、整套Linux开发工具知识图

text 复制代码
                  Linux开发
                      |
      ┌───────────────┼───────────────┐
      ↓               ↓               ↓
    编辑            构建             管理
      |               |               |
     Vim          GCC / G++          Git
                      |
                   Makefile

                      |
                      ↓
                    运行
                      |
               ┌──────┴──────┐
               ↓             ↓
             正常            Bug
                              |
                              ↓
                             GDB
                              |
                              ↓
                           修复代码
                              |
                              ↓
                         Git Commit

相关推荐
Mortalbreeze1 小时前
MySQL 基础篇(五):数据操作基础 —— CRUD
linux·服务器·数据库·mysql
cuijiecheng20181 小时前
Windows 下使用 GitHub Private Repository 管理私人 Visual Studio/C++ 项目
windows·github·visual studio
怕浪猫8 小时前
GEO 优化到底是什么?AI时代内容创作者必须懂的新技能
算法·面试·github
miofly9 小时前
Aleph Alpha 开源 78B 参数 MoE 模型 Kolibri
开源·github
JackSparrow41410 小时前
和AI一起将全部CSDN博文迁移到个人博客站
人工智能·程序人生·ai·github·cloudflare·astro·静态博客
Ivanqhz11 小时前
激活函数在 Transformer 中的作用及各种变体简述
java·linux·数据库·人工智能·深度学习
by2099911 小时前
学会使用std::string类,并理解其内部是如何管理字符串的详细阐述(上)
c++·笔记·字符串·类和对象·string
青柠之夏cc12 小时前
AI与教育:个性化学习助手让“因材施教“成为现实,但代价是隐私?
人工智能·学习
笑鸿的学习笔记12 小时前
C++笔记之大块顺序写
java·c++·笔记