目录
[一 版本控制器git](#一 版本控制器git)
[1 版本控制器](#1 版本控制器)
[2 git简史](#2 git简史)
[3 理解git的版本控制 git github&&gitee](#3 理解git的版本控制 git github&&gitee)
[二 下载git](#二 下载git)
[1 Windows](#1 Windows)
[2 Linux系统](#2 Linux系统)
1) CentOS版本 CentOS版本)
2) Ubuntu版本 Ubuntu版本)
[三 理解git](#三 理解git)
[四 git操作](#四 git操作)
[1 git clone](#1 git clone)
[2 三板斧](#2 三板斧)
[1)git add](#1)git add)
2)git commit -m"XXX"git commit -m"XXX")
[3)git push](#3)git push)
[3 git log](#3 git log)
[4 git status](#4 git status)
[5 git pull](#5 git pull)
[6 .gitignore](#6 .gitignore)
[7 关于冲突的问题](#7 关于冲突的问题)
[五 调试器 gdb/ cgdb](#五 调试器 gdb/ cgdb)
[1 dubug版本和release版本](#1 dubug版本和release版本)
[2 什么样的程序才能调试](#2 什么样的程序才能调试)
[3 见见gbd,cgbd](#3 见见gbd,cgbd)
[4 cgbd调试技巧](#4 cgbd调试技巧)
[b [文件名:] 行号](#b [文件名:] 行号)
[b 函数名](#b 函数名)
[info b](#info b)
[d 行号](#d 行号)
[断点是可以被"使能"的 enable / disable](#断点是可以被“使能”的 enable / disable)
[continue / c](#continue / c)
[(3)until finish](#(3)until finish)
[set var 确定问题原因](#set var 确定问题原因)
一 版本控制器git
不知道你工作或学习时,有没有遇到这样的情况:我们在编写各种文档时,为了防止文档丢失,更改 失误,失误后能恢复到原来的版本,不得不复制出一个副本,比如:
"报告-v1"
"报告-v2"
"报告-v3"
"报告-确定版"
"报告-最终版" "报告-究极进化版"
...
每个版本有各自的内容,但最终会只有一份报告需要被我们使用。 但在此之前的工作都需要这些不同版本的报告,于是每次都是复制粘贴副本,产出的文件就越来越 多,文件多不是问题,问题是:随着版本数量的不断增多,你还记得这些版本各自都是修改了什么吗?
文档如此,我们写的项目代码,也是存在这个问题的!!
1 版本控制器
为了能够更方便我们管理这些不同版本的文件,便有了版本控制器 。所谓的版本控制器,就是能让你了解到一个文件的历史,以及它的发展过程的系统。通俗的讲就是一个可以记录工程的每一次改动和版本迭代的一个管理系统,同时也方便多人协同作业。
目前最主流的版本控制器就是Git。Git可以控制电脑上所有格式的文件,例如doc、excel、dwg、dgn、rvt等等。对于我们开发人员来说,Git最重要的就是可以帮助我们管理软件开发项目中的源代码文件!
2 git简史
同生活中的许多伟大事物一样,Git诞生于一个极富纷争大举创新的年代。
Linux内核开源项目有着为数众多的参与者。绝大多数的Linux内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991−2002年间)。到2002年,整个项目组开始启用一个专有的分布式版本控制系统BitKeeper来管理和维护代码。
到了2005年,开发BitKeeper的商业公司同Linux内核开源社区的合作关系结束,他们收回了Linux内核社区免费使用BitKeeper的权力。这就迫使Linux开源社区(特别是Linux的缔造者Linus Torvalds)基于使用BitKeeper时的经验教训,开发出自己的版本系统。他们对新的系统制订了若干目标:
• 速度
• 简单的设计
• 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
• 完全分布式
• 有能力高效管理类似Linux内核一样的超大规模项目(速度和数据量)
自诞生于2005年以来,Git日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。
3 理解git的版本控制 git github&&gitee
我们用一个小故事来理解git:
有一个同学叫李四,他有一个室友叫张三。有一天他们的c语言老师让他们写一个实验报告,李四就开始写,写了第一版交上去老师说不行,写第二版交上去老师说不行.......写到第n版的时候,老师说:李四你怎么越写越差呢。算了你把第二版交上来吧。李四这个时候就傻眼了,我不记得第二版的内容了啊!
张三看到李四的情况,于是他每次修改实验报告的时候,他都会把上一次的报告保留下来。到最后,老师也说李四你现在写的还没之前写得好,算了,你把第三版交上来吧,我就算你过,这个时候张三就能交出来第三版的实验报告。
其实这个故事里面,张三和李四就是程序员,老师就是产品经理。
如果我们在做项目的时候,每一次都把之前的记录下来,可是实际的项目都很大啊,每一次的都保留下来,那修改了成千上万次有那么多的空间保存吗?所以我们每一次不需要保存所有的内容,只需要记录修改

那么git就是实现这个操作的工具,是记录每次的修改和版本的迭代的一个管理系统
注意:
Git仅能跟踪文本文件的改动(如代码 ,txt文件),可以清晰的显示修改细节。对于图片,视频等二进制文件,虽然也能控制,但无法跟踪文件的变化,只能看到内存大小的变化
gitee和github是基于git工具的,来完成本地仓库和远程仓库同步的网站
二 下载git
git支持Windows和Linux,按照不同的系统对应不同的方法:
1 Windows
打开Git 官网下载页,自动下载适配版本
双击安装包,一路 "Next"(默认选项足够用,不用改)
安装完成后,右键点击桌面,出现 "Git Bash Here" 就说明成功了(点击打开,这是 Git 的命令行工具)

2 Linux系统
1) CentOS版本

2) Ubuntu版本

三 理解git
git是去中心化的,分布式的版本控制器
去中心化的:在本地就可以完成版本管理(例如版本的提交,日志的提交,版本的回退),只不过做完需要同步到远端,在网络层面上是中心化的,但是在版本控制上各自管理自己的
分布式的: git自带客户端和服务端,可以在·多个平台进行同步的管理
git是CS一体的 :
指同时具备「客户端 本地完整工作能力」和「服务端协作中转能力」,且二者在仓库结构上完全统一、无需分离部署
四 git操作
1 git clone
我们如果在gitee网站创建一个仓库,那此时这个仓库就是远程仓库
假设此时我们建好的远程仓库叫做118_delete

那么此时我们查看这个仓库的文件和目录

修改记录都在.git中,.git才是真正的仓库
在.git中:

2 三板斧
我们要理解三板斧,首先要理解git的核心区域

仓库其实是分两个区域
1)git add
把修改信息,添加到本地仓库的暂存区
添加到暂存区时,如果想要对刚才的操作反悔的话,是可以实现的
2)git commit -m"XXX"
把修改信息,提交到本地仓库中 也就是把信息从暂存区提交到修改记录版本链中

例如我们写一段提交日志,那么刷新gitee就会得到:

3)git push
本地仓库和远端仓库同步

之后刷新gitee就可以看到代码的改动了
3 git log
逆向显示提交记录

4 git status
实时显示当前工作区、暂存区与本地仓库之间的文件状态差异,让你知道哪些文件被修改、哪些已暂存、哪些未被追踪
核心作用
- 查看文件状态:告诉你哪些文件处于「已修改但未暂存」「已暂存待提交」「未被 Git 追踪」等状态。
- 引导下一步操作 :输出中会给出明确的命令提示,比如告诉你可以用
git add暂存文件,或用git commit提交。- 避免误操作 :在执行
git commit前运行它,能确保你提交的内容符合预期,防止遗漏或错误提交
5 git pull
核心作用是将远程仓库中指定分支的最新提交,拉取并自动合并到本地当前工作分支,完成「远程→本地」的版本同步,确保本地分支与远程分支保持一致
相当于把远端仓库同步到本地
6 .gitignore
在仓库的目录下,还有一个文件叫做.gitignore

核心作用
.gitignore 是一个纯文本配置文件 ,核心功能是告诉 Git 哪些文件或目录不需要进行版本追踪(即忽略这些文件,不将其纳入暂存区和本地仓库)。
简单说:被 .gitignore 匹配到的文件,git add 不会主动追踪它们,git status 也不会显示它们的未追踪状态,从而避免无关文件混入版本控制。
使用规则
通配符 *
示例:*.zip(忽略所有 zip 压缩包)、src/*/temp(忽略 src 目录下任意子目录中的 temp 文件 / 目录)
7 关于冲突的问题
如果两个程序员同时在本地写项目,然后传到远端的仓库里去,那么其中一个程序员怎吗知道另一个程序员是否提交了代码呢,怎么知道自己本地的仓库是否数据更新到最新了呢

假如说张三先提交代码到gitee,如果此时李四直接提交,会失败。需要先将远端仓库和本地仓库同步之后(利用pull),才能提交,更新push
这就说明了仓库会强制代码同步
五 调试器 gdb/ cgdb
gdb和cgdb都是调试器,但是cgdb在gdb的基础上增加了简单的可视化界面
gdb在系统里是默认安装的
cgbd在系统里是没有安装的,我们需要另外下载,在Linux中输入下面这段话就可以下载cgbd
yum------Centos版本
apt------Ubuntu版本
1 dubug版本和release版本
程序的发布方式有两种:dubug版本和release版本
dubug方式:开发阶段自测
release方式:测试人员
注意:release方式下,是不能调试的!
gcc,g++ 编译程序都是以release版本发布的!!!
2 什么样的程序才能调试
当我们用gdb调试文件的时候,会发现无法调试,是因为编译程序都是以release方式发布的

如果我们想要调试程序,就需要转换到debug版本--->在源代码⽣成⼆进制程序的时候,加上++-g++ 选项,如果没有添加,程序无法被编译

-g :给形成的可执行程序内部,添加可调试信息(形成的可执行程序体积会变大)
3 见见gbd,cgbd
调试的本质:找到问题
调试的目的:解决问题
辅助工具找到问题,和程序员或AI解决问题

调试器只能帮助我们找到问题,但是解决问题还是需要靠程序员自己
4 cgbd调试技巧
我们用cgbd更加方便,推荐使用cgbd,因为cgdb是半图形化界面------>一半代码一半调试信息
开始:gdb binFile;
退出:Ctrl + d 或 quit调试命令
我们先来给一个总体的表,来看看cgbd调试有哪些技巧

(1)断点
b [文件名:] 行号
在文件的指定行号设置断点

b 函数名
在函数的开头设置断点
info b
查看当前所有断点的信息

d 行号
删除该行的断点

断点的本质

断点的作用就是可以让程序停下来

断点是可以被"使能"的 enable / disable
断点的 "使能 "(Enabled,也可称为 "启用"),指的是让已经创建 / 设置好的断点处于**「有效状态」**
对应的概念是 "禁用"(Disabled,非使能):断点依然存在于调试器的断点列表中(没有被删除),但处于**「无效状态」**


continue / c
从当前位置开始连续执行程序,直到遇到下一个断点
p/print
打印,用来查看函数,变量的值

(2)逐语句/逐过程---小范围寻找问题

**逐语句 s :**可以进入函数内部
**逐过程 n :**不进入函数内部,把函数当成一个语句(或者说命令)来执行
(3)until finish
until:直接调转到给定的行号

finish:执行当前函数返回并停止(把该函数执行完)
(4)监视变量
display:显示监视的变量
undisplay:取消显示监视的变量

取消显示"的操作和断点的新建、删除很类似------常显示也是有1、2、3......这样的编号的,所以也要通过编号来取消
(5)常见的三种技巧---加餐
watch
执行时监视⼀个表达式(如变量)的值。如果监视的表达式在程序运行期间的值发⽣变化,GDB会暂停程序的执行,并通知使用者




注意:
• 如果你有⼀些变量不应该修改,但是你怀疑它修改导致了问题,你可以watch它,如
果变化了,就会通知你.
set var 确定问题原因
set var:可以直接在调试期间修改变量
示例:更改⼀下标志位,假设我们想得到 +-result
bash
// mycmd.c
#include <stdio.h>
int flag = 0; // 故意错误
//int flag = -1;
//int flag = 1;
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result*flag;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
printf("running done, result is: [%d-%d]=%d\n", start, end, n);
return 0;
}
bash
(gdb) l main
15
16 return result*flag;
17 }
18
19 int main()
20 {
21 int start = 1;
22 int end = 100;
23 printf("I will begin\n");
24 int n = Sum(start, end);
(gdb) b 24
Breakpoint 1 at 0x11ca: file mycmd.c, line 24.
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:24
24 int n = Sum(start, end);
(gdb) n
25 printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=0 # 这⾥结果为什么是0?
26 return 0;
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:24
24 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:9
9 {
(gdb) n
10 int result = 0;
(gdb) n
11 for(int i = s; i <= e; i++)
(gdb)
13 result += i;
(gdb)
11 for(int i = s; i <= e; i++)
(gdb)
13 result += i;
(gdb) until 14
Sum (s=1, e=100) at mycmd.c:16
16 return result*flag;
(gdb) p result
$1 = 5050
(gdb) p flag
$2 = 0
(gdb) set var flag=1 # 更改flag的值,确认是否是它的原因
(gdb) p flag
$3 = 1
(gdb) n
17 }
(gdb) n
main () at mycmd.c:25
25 printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=5050 # 是它的原因
26 return 0;
条件断点
添加条件断点


给已存在的断点新增条件

条件断点添加常见两种方式:1、新增;2、给已有断点追加

