linux入门

真正从一窍不通开始学 Linux。

参考文献(

【Linux工具】:软件包管理器yum | 编辑器vim | 编译器gcc/g++ | 调试器gdb | 自动化构建工具make/Makefile | Linux小程序:进度条 | git命令行_yum包管理器-CSDN博客

鸟哥的 Linux 私房菜 -- 浅谈备份策略 (vbird.org)

(新)VMware虚拟机安装Linux教程(超详细)-CSDN博客

【Linux】CentOS更换国内阿里云yum源(超详细)_centos更换yum源-CSDN博客

Linux 命令大全 | 菜鸟教程 (runoob.com)

and so on

Linux是什么

硬件暂略(

粗浅理解:也就是说你在硬件层面上理解了 CPU,DRAM,显卡,硬盘,主机板和芯片组后,发现需要一个东西来安排输入到 RAM,安排 CPU 运算,安排输出硬件的调用,于是我们需要一个汇编程序来实现,这个程序叫做内核,内核需要一直存在于内存中。
然后有了这个内核后我们就可以调用内核来操作,为了保护内核和方便操作,我们把内核所在的内存和用户使用的内存分开,并开发了内核对应的接口,类似内核的语法,即为系统调用。

基本的 Linux 是底层硬件之上一层的内核和系统调用,这也就是操作系统,提供了最底层的硬件控制与资源管理的完整架构。Linux 这个架构沿袭 Unix,稳定且功能强大。

在 Linux 上我们是需要做开发,
写代码,编译代码,调试代码,自动化构建项目,上传github/gitee。
需要用到的工具有:
软件包管理器 yum,文本编译器 vim,代码编译 gcc/g++,调试器 gdb,自动化构建项目 make/Makefile,以及 Linux 上的 git 命令行。

下载

见参考文献(

常用命令

首先,Linux 的文件系统为树形结构,所有文件都在根目录 / 下。
常见目录有:

  • /bin:存放基本基本命令的二进制文件,如 ls,cp 等。
  • /etc:存放系统配置文件,如 passwd,hosts 等。
  • /home:存放用户的主目录,每个用户都有一个子目录。
  • /var:存放可变数据文件,如日志文件,缓存文件等。

文件操作

ls 列出目录内容(list)
ll 列出目录内容及详细属性
cp <file1> <file2> 复制文件(copy)
mv <file1> <file2> 移动或重命名文件(move)
rm <file> 删除文件(remove)
ln <file1> <file2> 为某文件在另一位置建立一个同步的链接(link)

对于 rm

可以使用 rm -r 来删除文件夹及内容,可使用 rm -i 增加一次确认环节以免误操作。

对于 ln

当我们需要在不同的目录用到相同的文件时不需要在每一个目录下都放一个文件,只需要用 ln 命令链接到某一个文件,而不用占用磁盘空间。

链接分为两类,硬链接(hard link)和软链接(symbolic link)。
硬链接的意思是一个文件可以有多个名称,而软链接的方式则是产生一个特殊的文件,这个档案的文件是指向另一个文件位置。
硬链接存在于同一个文件系统,而软链接却可以跨越不同的文件系统。
两者都只占用非常少量的磁盘空间。

软链接
以路径的形式存在,类似 Windows 中的快捷方式。
可以跨文件系统
可以对不存在的文件名进行链接
可以对目录进行链接
删除源文件链接失效

硬链接
以文件副本形式存在,但不占用实际空间。实际上指向了源文件的索引节点。
不能对目录创建
只能在同一文件系统中
删除源文件链接不失效

目录操作

mkdir <dir> 创建目录(make directory)
rmdir <dir> 删除空目录(remove directory)
cd <dir> 切换目录(change directory)
pwd 显示当前目录(print working directory)

另外 . 表示当前目录,.. 表示上一级目录。

权限管理

chmod 755 <file> 修改文件权限(change mode)
chown <user>:<group> <file> 修改文件所有者(change owner)

Linux 的文件调用权限分为三级,文件所有者(Owner),用户组(Group),其他用户(Other Users)。

对于 chmod

Pasted image 20240916115858.png

Pasted image 20240916115934.png

这里的 755 就是指分别对 Owner,Group 和 Other Users 用上方对应的方式给予读写运行的权限。也可以不用数字,直接用 u,g,o 或者 a(all) 加上 +/-rwx 来表明,例如 ugo+rug+w,o-w,还有其他参数,暂不一一说明。

对于 chown

Linux/Unix 是多人多工操作系统,所有的文件均有拥有者。chown 可以将指定文件的拥有者改为指定的用户或组。

进程管理

Linux 通过进程管理工具,来控制和监控系统中的进程,常用的工具包括 ps,top 和 kill 等。

ps -aux 显示所有进程(process status)
top 实时显示系统资源使用情况
kill -9 PID 强制终止进程

对于 ps

ps 的参数比较多

  • -A 列出所有进程
  • -w 显示加宽可以显示更多资讯
  • -au 显示较详细的咨询
  • -aux 显示所有包含其他使用者的进程

结果格式为

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

  • USER:行程拥有者
  • VSZ:占用的虚拟内存
  • RSS:占用的内存大小
  • TTY:终端的次要装置号码(minor device numberof tty)
  • STAT:该行程的状态
  • START:形成开始时间
  • TIME:执行的时间
  • COMMAND:所执行的命令

其中,STAT 又分

  • D:无法中断的休眠状态(通常 IO 的进程)
  • R:正在执行中
  • S:静止状态
  • T:暂停执行
  • Z:不存在但暂时无法消除
  • W:没有足够内存分页可分配
  • <:高优先序的行程
  • N:低优先序的行程
  • L:有内存分页分配并锁在内存中(实时系统)

对于 kill

在使用 kill 命令时,需要具有相应的权限,否则可能无法终止进程。

某些进程可能需要发送多次信号才能终止,比如一些守护进程。

强制杀死进程可能会导致数据丢失或其他副作用,因此应谨慎使用。

这里 kill 可以带参数,但类型太多(64种),暂时只记住 -9 是强制终止。

其他

cat: Read a text file
less: Read a large text file
touch: Create new files
clear: Clear terminal screen
lsblk: List disks and partitions(list blocks)
fdisk: List and manage disks and partitions  **
find: Search for files(names,types) **
grep: Search in file content **
history: Look back into what commands you ran in the past
lshw: Get the hardware details(-C for a class of hardware)
sudo: Run commands with root privileges
ip: Check IP address and other info
ping: Check if the remote system is reachable
ssh: Connecting to remote systems
scp: Copy files between remote systems
exit: Close the terminal
shutdown: Turn off or reboot the system
man: Learn about commands in detail

快捷键

Linux 黑话解释:Linux 中的 Super 键是什么? | Linux 中国 - 知乎 (zhihu.com)
13 Keyboard Shortcuts Every Ubuntu User Should Know (itsfoss.com)
21 Useful Linux Terminal Shortcuts Pro Users Love (itsfoss.com)
31 Basic Yet Essential Ubuntu Commands (itsfoss.com)

若干,可以先记一些

super

类似 win 键盘上的 win 键,也确实是这个键。

实际效果也跟 win 快捷键相似。

super 打开活动概览
super + tab 切换开放应用
super + d 显示桌面
super + a 打开应用菜单
super + s 显示快速设定
super + left 将活动窗口移至最左侧
super + right 将活动窗口移至最右侧
super + up 最大化活动窗口
super + down 最小化活动窗口
super + l 锁定屏幕

一些常用快捷键

ctrl + alt + t 打开终端
super + space 切换输入法
alt + F2 快速运行命令
ctrl + q 关闭应用窗口
ctrl + alt + up/down 切换工作区
ztrl + alt + del 登出

终端快捷键

ctrl + a: Move to the start of the line
ctrl + e: Move to the end of the line
ctrl + u: Delete from the cursor to start
ctrl + k: Delete from the cursor to the end
ctrl + w: Delete a single word before the cursor
ctrl + l: Clear terminal screen (kind of)
ctrl + c: Stop the current process/execution
ctrl + d: Logout or exit from the terminal
ctrl + z: Pause the current process
ctrl + r: Search command history
up: Show the previous command from history
down: Show the next command from history
!!: Repeat the last command  (sudo !!)
!n: Repeat the nth command from history
Tab: Auto-complete the command
Tab twice: List all the possible auto-completes
ctrl + shift + c: Copy the selected text
ctrl + shift + v: Paste the copied text
ctrl + shift + n: Open a new terminal window
ctrl + shift + t: Open new tab
ctrl + Tab / ctrl + PgDn: Switch tabs

软件包管理

确保系统稳定,安全,高效运行。

Linux 下安装软件有三种方式,

源代码安装:自己下载,自己编译安装,……
rpm 包安装:自己下载,自己解压安装,……
yum 安装:帮我们查找并下载,帮我们安装,帮我们解决依赖关系

前期在学习的过程中一般都使用 yum,后期学习或在工作时,可能需要使用一些框架,库之类的,那时就可以使用源代码或 rm 安装。yum 是一条命令或者是个工具,类似手机上的应用商店,它的配置文件中指明我们应该去哪里下载资源。

概念

软件包:在 Linux 下安装软件,一个通常的办法是下载到程序的源代码,进行编译,得到可执行程序。有些人把一些常用的软件编译好,做成软件包(类似windows的安装程序)放在服务器上,通过包管理器可以很方便地获取到这个编译好的软件包,直接进行安装,软件包和软件包管理器就好比 APP 和应用商店。

软件包管理: 通过特定的工具来安装,更新,配置和卸载应用程序及其依赖项的过程。

依赖项:一个软件包为了正常运行所需的其他软件包或库文件。

仓库:存储软件包的远程服务器,用户可以从这些服务器下载和安装软件包。

参数详解

较为通用的有,
安装:install+软件包名称
更新:update/upgrade+软件包名称
搜索:search/ss+软件包名称
卸载:remove/uninstall+软件包名称

不同的Linux发行版提供了各自的软件包管理工具,这些工具具有不同的命令和参数:

APT(Advanced Packaging Tool) Debian/Ubuntu

apt update 更新软件包列表
apt upgrade 升级所有可升级的软件包
apt install <package-name> 安装指定软件包
apt remove <package-name> 卸载软件包
apt purge <package-name> 卸载软件包并删除其配置文件
apt search <keyword> 搜索包含关键字的软件包
apt show <package-name> 显示软件包的详细信息

add-apt-repository

管理 PPAs

snap

管理 snap packages

YUM(Yellowdog Upgrater Modified) -CentOS/Red Hat(旧版)

yum install <package-name> 安装软件包
yum update 更新所有软件包
yum update <package-name> 更新指定软件包
yum remove <package-name> 卸载软件包
yum search <keyword> 搜索包含关键字的软件包
yum info <package-name> 显示软件包的详细信息
yum clean all 清楚yum缓存
yum list 查询所有已安装和可安装的软件包
yum list <package-name> 查询执行软件包的安装情况

DNF(Dandified Yum) -CentOS/Red Hat(新版)

暂略

Zypper -openSUSE

暂略

Pacman -Arch Linux

暂略

这些命令和参数是软件包管理工具的核心功能。可能会因版本变化而变更。

实操

以 yum 为例。

安装/卸载

sudo yum install -y Irzsz

-y 表示 yes 是指下载过程出现的问题均同意。

出现 complete 表示安装完成。

安装软件由于需要向系统盘中写入内容,所以需要 sudo 或者在 root 下进行。

yum 安装软件只能一个一个安,否则会报错。

关于 yum 的所有操作必须保证主机(虚拟机)网络畅通,可以通过 ping 指令验证。

ping www.baidu.com

ctrl z 退出 ping。

sudo yum remove -y lrzsz

lrzsz

虽然不是软件包管理,但顺带学一下,lrzsz 用于 windows 机器和远端的 Linux 通过 xshell 传输文件,输入 rz 可以拖拽上传,反之亦然。

查看软件包

可以通过 yum list 罗列当前的安装的软件包,可以通过 grep 筛选到我们关注的包。

yum list | grep lrzsz

结果为

lrzsz.x86_64                          0.12.20-36.el7             @base

lszrz.x86_64 是软件包的名称和软件适合的版本。

0.12.20-36.el7el7 是操作系统发行版本,CentOS7。

@base 指的是软件的提供者,epel 指扩展源。

好玩的命令 - gong_ - 博客园 (cnblogs.com)

yum 源

是什么?虚拟机(?)默认带的 yum 可能版本老或者是国外的,导致一些问题,这时需要手动更新 yum 源。

yum 的配置文件在 /etc/yum.repos.d/ 下,所有扩展名是 .repo 的都是。

vi CentOS-Base.repo

打开看看,

[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/os/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

[base]:容器名称,放在 [] 里。
name:容器说明。
mirrorlist:镜像站点。
baseurl:yum源服务器的地址,默认是 CentOS 官方的 yum 源服务器。
gpgcheck:如果为 1 则表示 RPM 的数字证书生效,为 0 则不生效。
enabled:此容器是否生效,如果不写或是 enabled 则生效,如果是 enable=0 则不生效。
gpgkey:数字证书的公钥文件保存位置,不用修改。

该配置文件定义了可用的软件仓库.

  • 修改 yum 源前先备份,可以用 cpmv,或者压缩 zip
  • 然后 rm 删除原本的 CentOS-Base.repo。
  • 再下载阿里云的 yum 源,wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
  • 然后清理 yum,yum clean all。这会清理 yum 所有已下载的元数据和软件包缓存。
  • 重新生成缓存,yum makecache。这时 yum 会读取刚刚更新的配置文件,并为每个配置好的仓库生成一个缓存,这涉及到从每个仓库的元数据服务器下载必要的信息,例如软件包列表,版本等,并将其存储在本地文件系统(通常是/var/cache/yum/)。

扩展源

CentOS-Epel.repo 就是扩展源,它默认是没有的,像 Base 这种 yum 源对软件的要求就是稳定,可靠,来源明确,但通常这样软件更新速度就比较慢,所以有很多软件就开发出来放在 Epel 中。Base 就像应用商城下载,Epel 就像浏览器下载。

编辑器 vim

写代码,调试代码,编译、链接代码在 Windows 中都可以在 VScode/devc++ 中完成,这是集成开发环境。
而在 Linux 中我们用的是独立的工具,写代码用 vim,编译用 gcc/g++,调试用 gdb,维护项目关系用 make/Makefile。

首先来看 vim。

Pasted image 20240914135509.png

非常简洁明了的图表,
艹,这个东西感觉比较难记(
先往后看

让我们用 Clion VScode(

编译器 gcc/g++

区别 gcc 只能编译 c。

首先,一段 c/c++ 代码写完后变成可执行文件有四个步骤。

  • 预处理:大概是把 # 的内容处理,包括头文件,宏定义,生成 .i/.ii 文件。
  • 编译:把预处理后的代码转换成汇编语言,经过词法分析和语法分析,生成 .s 文件。
  • 汇编:汇编器逐行处理汇编代码,转换为二进制文件格式,每个源文件对应一个 .o/.obj 目标文件。
  • 链接:将多个目标文件和 .lib/.a 库文件合并成一个 .exe 可执行文件的过程,同时解决符号解析问题,确定代码中引用的符号(eg函数和变量)在最终的可执行文件中的位置。

(实际开发中,为了提高编译速度和代码复用性,通常会将编译过程与构建系统结合使用,构建系统相关在后文)

除了 c/c++,Linux 几乎可以在命令行中执行大部分后端语言,如 python,java。如 python test.py

头文件和库文件-静态库和动态库

头文件与库文件的区别-CSDN博客

C头文件与库文件的区别-古丁高手-ChinaUnix博客

关于linux下的库文件_linux magic.h-CSDN博客

头文件和库文件-静态库和动态库 - 骏骏 - 博客园 (cnblogs.com)

这里需要注意,预处理导入的是头文件,而链接中链接的是库文件,二者并不相同。头文件中其实只有一个函数的声明,而实现在链接库里,比如 stdio.h 的实现在 glibc。所以预处理后的代码中其实并没有头文件中对应函数的实现,因而需要链接这一过程。

头文件一般是声明其他函数,同时可以通过头文件找到库文件。而库文件中有需要用的函数,但库文件已被转换为二进制,看不到原始的代码。另外,库文件可以包含头文件,头文件不可包含库文件。使用库文件还可以减少重复编译的时间,增强程序的模块化。

更进一步的,将库文件连接到程序中的方式分为静态连接库和动态连接库。Windows 下分别是 .lib 和 .dll 文件,Unix 下分别是 .a(archive 压缩文件,其中就是若干 .o 的压缩) 和 .so(shared object)。内容都是将函数编译后供自己或他人调用。两种库的区别在于如果是动态库,则最后程序运行时需要这个动态库的支持,若是静态的,则最后的可执行文件运行时可以脱离这个库独立运行。

相关报错

  • undefined reference to 'xxx'.
  • /usr/bin/ld:cannot find -lxxx
  • xxx.h:No such file or directory

这几个都不是编译错误而是链接错误,即源程序没有错,而是编译选项不对或缺少相关库文件(前两个)/头文件(后一个)。

库文件相关

-l(小写 L ) 参数紧接着的就是库名,而库名和库文件名又不同,库文件名为 libm.so 则库名为 m,编译时就需要使用 -lm。当然代码里也需要有头文件。

放在/lib,/usr/lib,/usr/local/lib 里的库可以用 -l 参数,但若在其他目录就会出现第二个报错,这时可以使用 -L 参数。例如 X11 库在 /usr/X11R6/lib 下,就要用 -L/usr/X11R6/lib -lX11 参数。

头文件相关

-I(大写 i)参数用来指定头文件目录,/usr/include 一般不需要指定,但若头文件在 /myinclude 里,那编译命令就要加上 -I/myinclude 参数,否则会出现第三个报错。-I 参数可以使用相对路径,比如当前目录可以用 -I. 来指定。

编译过程

一步到位

gcc test.cg++ test.cpp -o test.out

这里 -o 是指定目标名称,没有时默认是 a.out

分步观察

gcc -E test.c -o test.i 预处理:`#` 即头文件展开,条件编译,去掉注释,宏定义等
gcc -S test.i -o test.s 编译:转汇编语言(其实就是指令集的宏定义)
gcc -c test.s -o test.o 汇编:转二进制目标文件
gcc test.o -o mytest    链接:生成可执行程序

这里每一步后都可以打开看看其内容,有更深的理解。

gcc 选项

-E 只激活预处理,不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言,不进行汇编和链接
-c 编译到目标代码
-o 文件输出到文件
-g 生成调试信息,GNU 调试器可利用该信息
-static 此选项对生成的文件采用静态链接
-shared 此选项将尽量使用动态库,所以生成的文件比较小,但是需要系统调动态库
-O0 -O1 -O2 -O3 编译器优化选项,-O0 没有优化,-O1 缺省值,-O3 优化级别最高
-w 不生成任何警告信息
-Wall 生成所有警告信息

参数是 ESc,生成文件是 iso(

生成库文件

写头文件只需要申明并重命名文件为 .h 就行了,那库文件如何生成呢。

静态库

首先把源文件汇编了 gcc -c magic.c 生成 magic.o,然后用压缩命令生成静态库文件。
ar rc libmagic.a magic.o 其中 rc 是压缩选项,libmagic.a 是给静态库取的名,后面还可以跟多个 .o 文件,把他们压缩成一个库文件。

然后就可以链接了 gcc -o main main.o -lmagic -L.

动态库

直接用 gcc 生成,首先汇编 gcc -fPIC -c magic.c (Position-Independent-Code,用于确定库中函数的链接位置,生成位置无关的代码),然后从二进制文件生成动态库文件 gcc -shared -o libmagic.so magic.o 后面可以跟很多 .o 文件。

使用时需要设置动态库的路径。可以用 ldd 命令 ldd main 查看程序用到了哪些动态库,会指出动态库的路径,也会指出 not found。

另,链接是 gcc 调用了 ld 命令,所以可以自己调用 ld 或者写在 Makefile 里(?后面再看)。

动态链接改静态链接

新版本 Linux 一般不会安装 libc.a 而是安装 libc.so,所以就用不了 -static 改静态链接,解决方法就是安装 glibc-static

调试器 gdb

我自信不调试 先放一放

项目自动化构建工具 make/makefile

30a5dfd22310742dfcc575f112d43e90.png

一个项目长这样

8bd1d2f3602b16d35d43eeec76cfd4f4.png

多文件结构

在 C++ 里,多文件项目结构也是重要的结构,这与以前的算法竞赛单文件只考虑自带头文件的格式有很大不同。

首先分成三类文件,头文件,模块文件,主程序文件。

头文件就是声明,不止一类函数,也包括数据结构都是可以声明的。
模块文件就是头文件函数的实现。
主程序文件就是把上述代码去掉后的主程序。

因为一个大型的程序编译的时间很长很长,所以人们就把模块文件先编译成二进制文件,直到最后一步链接才会用到它,这样就能节省大量编译时间。

头文件里除了函数声明,也需要放类定义,结构定义,以及模板函数和内联函数。不能有函数定义,也不能有变量定义(static 和 extern 可以)。

另外,引用头文件时我们见到过 <xx.h>"xx.h",区别在于 <> 是从标准库的头文件目录,例如 Linux 下的 /usr/include,/usr/local/include,而 "" 是优先从当前文件目录查找,找不到时再找标准库。

如果用命令行直接编译,那么我们需要列出所有自己写的的库文件,所以不使用 IDE 时,大概就需要用到 make/Makefile。

项目

首先需要理解项目。

在 C# 入门里发现,我们能用 dotnet 新建一个 C# 项目,这样 VScode 才能运行源代码。

借言:做项目的本质是按照他人(客户,上级……)的意愿,遵循一定的开发流程(产品,研发,测试……),遵循一定的开发规范(需求文档,设计文档,开发文档,测试文档……),进行软件开发。

makefile

背景

  • 会不会写 makefile,一定程度显示出一个人完成大型工程的能力。
  • 一个工程中的源文件不计其数,按类型,功能,模块分别放在若干个目录里。makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至进行更复杂的功能操作。
  • makefile 带来的好处是自动化编译,只要写好了 makefile,只需要一个 make 命令,整个工程完全自动编译,极大提高开发效率。
  • makefile 是一个文件,里面用特定的语言表明了编译的顺序,make 是一个命令工具,用来解释 makefile 的内容。一般来说,大多数 IDE 都有这个命令,如 Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的make。可见,makefile 都成为了一种在工程方面的编译方法。
  • make 和 makefile 一起完成项目自动化构建。

make 的语法

在 makefile 里,我们需要写若干组依赖关系及其依赖方法。例如,test 依赖 test.c 通过 gcc 这一依赖方法生成,于是我们写成

test:test.c
	gcc test.c -o test

第一行前面是目标文件,后面是依赖文件。
第二行是依赖方法,即 gcc。

我们还可以写出

test:test.c main.c
	gcc $^ -o $@

这里 $^ 可以表示所有依赖的文件,$@ 表示目标文件。这里的依赖文件和写编译命令时是一样的。

makefile 的运行过程是

  • 找到第一个命令的目标文件,如果目标文件不存在或依赖文件的修改时间比目标文件新,则执行依赖方法
  • 如果依赖文件不存在,它会在当前文件里寻找依赖文件的依赖关系,试图生成
  • 如果找到最后某个依赖文件不存在也找不到依赖关系,make 会退出并报错;但如果是命令错误,编译失败,make 不会报错。

所以我们还可以写

test:test.o
	gcc $^ -o $@
test.o:test.s
	gcc -c $^ -o $@
test.s:test.i
	gcc -S $^ -o $@
test.i:test.c
	gcc -E %^ -o $@

这样为了生成 test,make 就会向前寻找并四次编译。
而我们做的只是输入命令 make。当我们的项目文件多的时候,这种自动化编译的优势更加明显。

需要注意的是,make 默认只生成一个目标文件。

另外,我们一般在 makefile 后面里写上 clean,形如

.PHONY:clean
clean:
	rm -f test

此时只找第一个目标文件会由于 clean 不被依赖而无法运行,就可以使用 make clean 来直接操作,清除可执行文件。

这里的 .PHONY 表示定义伪目标,它的含义是使 make clean 时,clean 总是可执行的。

代码管理工具 git

是什么

git 是目前世界上最先进的分布式版本控制系统。它可以让你类似一棵树(然而不是)一样存储你代码的不同版本,也能进行两个版本的合并。

github/gitee 是基于 git 搭建的版本控制代码托管的平台,是为客户提供 git 服务的网站,提供了很多丰富的功能,很多技术大牛或互联网大厂都在 github 上有自己的开源代码。同时也是全球最大同性交友网站

体验 git

先体验一下。

这里主要内容还是 git 分支管理。

Learn Git Branching 这是一个本地+远端的教程,可以先完成一部分本地的内容。

区分分支和提交记录:分支是若干个指针,提交记录组成一棵树,HEAD 是一个特殊的指针,既可以指向分支也可以指向提交记录。分支<br-name> 是自己取的名字,提交记录<rc-name>是一串 hash,可以用能唯一确定的前若干位来代表。

内容包括:提交、分支,在提交树上移动,整理提交记录

用到的命令包括

git commit 提交
git branch <br-name> 在 HEAD 处新建分支
git branch -b <br-name> 在 HEAD 处新建分支并将 HEAD 移动到该分支
git checkout <name> 将 HEAD 移动到分支或提交记录
git merge <br-name> 将分支及其与 HEAD 的 LCA 之间的修改合并到 HEAD 上
git rebase <name> 将 HEAD 移动到分支或提交记录
cat .git/HEAD 
git symbolic-ref HEAD 
^ 在 <name> 后使用表示 parent
~<num> 若干级 parent
git branch -f <br-name> <rc-name> 将某分支移动到某提交记录
git reset <rc-name> 本地从 HEAD 撤销至某提交记录
git revert <rc-name> 远端在某提交记录下方新建提交记录表示撤销
git cherry-pick <rc-name>... 将一些提交复制到 HEAD 下面
git rebase -i <rc-name> 交互式(interactive) rebase,整理 HEAD 开始的若干提交记录
git commit --amend 对 HEAD 所在提交记录追加修改
git tag <tag-name> <rc-name> 在某提交记录建立标签
git bisect 查找产生 Bug 的提交记录
git describe <name> 描述离 <name> 最近的标签,<tag>_<dis>_g<hash>,hash 是 <name> 的

或许可以针对这些命令另写一份 Learn Git Branching 学习笔记,因为很多操作的具体含义还并不是很清楚,也包括一些合理但不符合”树“形态的命令让我困惑。

66bb0721ae4eb4e2388c5708306f3ff1.png

简单实操

查看有没有 git git --version
下载一个 git yum install git

然后去 code 里找到 https 复制准备克隆到本地。
git clone https://github.com/LLLMMKK/test.git
这里需要 github 的用户名和密码。不知道为啥总是 Authentication failed,于是 google 了 “git 私有仓库 clone” 用 token 解决了。

![[Pasted image 20240920121051.png]]

在 Windows 下能看到 test 文件夹,在 Linux 下被隐藏了。
一个 README.md,另一个 .git 就是本地仓库,关于配置,分支等等都在里面,所以不要修改 .git 的内容。

将代码复制到 test 里。
cp ../test.cpp .

然后可以尝试提交
git add .
git commit -m "first commit"
git log
git status

再试试上传到远端仓库
git push

直接 git push 会 warning 因为它不知道是所有分支还是当前分支,不过已经成功 push 了。
maching 是默认 push 本地所有分支,simple 是默认只把当前所在分支 push 到曾 pull 下来的对应分支(如果有的话),另外也会检查各个分支的名称是否相对应。
根据提示可以用 git config --global push.default <mode> 来更改。

最后再来试试从远端仓库拉取,可以先在 github 上修改一下代码,然后
git fetch
就会发现我们拉取下来了一个更改记录。

![[Pasted image 20240920185600.png]]

这说明 origin/main 已经被更新,然后
git merge origin/main

![[Pasted image 20240920185727.png]]

就成功了。

另外的,git pull <repo-name> <br-name> 相当于 git fetchgit merge <br-name>
并且我们可以随时通过 git log 查看提交记录。
也可以通过 git branch -a 查看分支情况。

理解 git

git 用到的基本操作有 git clonegit addgit commitgit checkoutgit pushgit pull

区分文件和更改(?)

文件状态

haotu

workspace:工作区

就是在本地计算机上能看到的项目文件,它是你实际查看,编辑,删除和创建文件的地方。所有对文件的更改首先发生在工作区。

工作区的文件可能是

  • 未跟踪(Untracked):新创建的文件,未被 git 记录。
  • 已修改(Modified):已被 git 跟踪的文件发生了更改,但这些更改还没有被提交到 git 记录中。

staging area:暂存区

也被称为索引(Index),是一个临时存储区域,用于保存即将提交到本地仓库的更改。你可以选择性的将工作区中的修改添加到暂存区中,这样可以一次提交多个文件的更改而不必提交所有文件的更改。
git add <file> 添加指定文件到暂存区
git add . 添加所有更改到暂存区

local repository:本地仓库

是一个隐藏在 .git 中的数据库,用于存储项目的所有提交历史记录。每次提交更改时,git 会将暂存区中的内容保存到本地仓库中。使用 git commit -m "commit message" 提交。

remote repository:远端仓库

如果想要通过 git 分享代码给别人或与其他开发人员合作,就需要将数据放到一台其他开发人员能够连接到的服务器上,例如 github。

状态转换

新建的文案文件是 Untracked 的,
touch newfile.txt
git status

通过 git add 将 Untracked 的文件添加到暂存区后变为 Tracked,
git add newfile.txt
git status

对已跟踪的文件进行更改后,这些更改会显示为 Modified,但更改还未添加到暂存区
echo "Hello,World!" > newfile.txt
git status

使用 git add 将修改后的文件添加到暂存区后,文件进入 Staged 状态,等待提交。
git add newfile.txt
git status

使用 git commit 将暂存区的更改提交到本地仓库后,这些更改被记录下来,文件返回 Tracked 状态。
git commit -m "Add newfile.txt"
git status

基本命令

创建仓库命令

git init 初始化仓库
git clone 拷贝一份远程仓库

提交与修改

git add 添加文件到暂存区
git status 查看仓库当前状态,显示有变更的文件
git diff 比较文件的不同,及暂存区和工作区的差异
git difftool 使用外部差异工具查看和比较文件的更改
git range-diff 比较两个提交范围之间的差异
git commit 提交暂存区到本地仓库
git reset 回退版本
git rm 将文件从暂存区和工作区中删除
git mv 移动或重命名工作区文件
git notes 添加注释
git checkout 分支切换
git switch 更清晰地切换分支
git restore 恢复或撤销文件的更改
git show 显示 git 对象的详细信息

提交日志

git log 查看历史提交记录
git blame <file> 以列表形式查看指定文件的历史修改记录
git shortlog 生成简介的提交日志摘要
git describe 生成一个可读的字符串,该字符串基于 git 的标签系统来描述当前的提交

远程操作

git remote 远程仓库操作
git fetch 从远程获取代码库
git pull 下载远程代码并合并
git push 上传远程代码并合并
git submodule 管理包含其他 git 仓库的项目

写代码

to be continued,在这里实践上面的操作。。。

posted @ 2024-12-25 17:04  llmmkk  阅读(13)  评论(0编辑  收藏  举报