Git原理+使用(超详细)

Git初识

当我们写项目代码时,需要不断的更新版本,那么就需要一个东西去管理这些不同版本的文件—版本控制器。

目前最主流的版本控制器就是Git。它是一个可以记录工程的每一次改动和版本迭代的管理系统,同时方便多人协同作业。

!注意:Git只能跟踪文本文件的改动,比如第几行改了什么,但是图片,视频,二进制文件,并不能直观的观察到改了什么,比如只知道图片从100kb变为120kb。

安装Git

前言(目前显示的ubuntu平台)

你可以通过输入git来看看有没有安装Git,如果安装了就会弹出以下界面。

安装Git

sudo apt-get install git -y

查看Git安装版本

Git基本操作

创建Git本地仓库

因为仓库是进行版本控制的文件目录,要想对文件进行版本控制,就必须先创建一个仓库。

我们先创建一个gitcode目录,后续操作都在这个目录里面进行。

通过 git init命令创建一个本地仓库

之后我们会发现有个.git的隐藏文件 ,注意不要修改这个目录的文件,它是用来跟踪管理仓库的,我们可以输入tree .git命令进去看看

配置Git

安装完Git后最好先设置你的用户名称和e-mail地址。

git config [ --global ] user.name "Your Name"
git config [ --global ] user.email "email@example.com"
------------------------------------------------------------------------
your name改为你的名字
email "email@example.com改为你的邮箱

--global是个可以选项,如果带上该选项表明这台机器上的所有Git仓库都会用这个配置,如果希望不同仓库有不同的名称和邮箱地址就不要带 。

可以通过一个命令来查看配置

root@hecs-95072:~/gitcode# git config -l
user.name=pikes
user.email=2994322314@qq.com
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true

 删除对应命令配置

git config [ --global ] --unset user.name
git config [ --global ] --unset user.email

工作区,暂存区,版本库

  • 工作区:也就是电脑上要写的代码或文件的目录
  • 暂存区:一般存放在.git目录下的index文件中
  • 版本库:也叫仓库,这个版本库中的所有文件都可以被Git管理起来,对于每个文件的修改,删除,Git都能跟踪。

在工作区写的代码和文件 必须通过git add命令,让暂存区的文件索引更新,再通过git commiit命令才能将文件添加到仓库中进行管理~

添加文件

我们可以在包含.git的目录下创建一个文件,写入一些内容,使用git add命令将文件添加到暂存区

添加⼀个或多个⽂件到暂存区: git add [ file1 ] [ file2 ] ...
添加指定⽬录到暂存区,包括⼦⽬录: git add [ dir ]
添加当前⽬录下的所有⽂件改动到暂存区: git add .

使用 git commit命令将暂存区的内容添加到仓库中

提交暂存区全部内容到本地仓库中: git commit - m "message"
提交暂存区的指定⽂件到仓库区: git commit [ file1 ] [ file2 ] ... - m "message"

 注意 -m选项是要描述本次提交的message信息,以确保下次查看时知道本地提交的具体信息

通过 git log命令查看历史提交记录,因为我提交过几次,所以会出现一下信息

如果想看简便的信息,可以加上一个参数

前面一大串黄色的字符串是每次提交的commit id。

查看.git目录

1:index就是我们的暂存区,add后的内容就添加在这里

2:HEAD就是我们默认指向master分支的指针

可以通过命令来查看

root@hecs-95072:~/gitcode# cat .git/HEAD
ref: refs/heads/master
root@hecs-95072:~/gitcode# cat .git/refs//heads/master 
946c80e794901d4169040596e7d827647dc1e829

打引出来的字符串就是最新的commit id

3:objects是Git的对象库,里面包含了创建的各种版本库对象和内容,当执行git add命令时,暂存区目录更新,同时工作区被修改的文件内容被写入到对象库中一个新的对象中

我们可以看看object里面有什么

 

commit id分为两部分,前两位是文件夹名称,后38位是文件名称。因为文件是经过安全哈希算法加密过的文件,我们要使用git cat-file命令来查看版本库对象的内容

可以看到有一行tree c8d28685fa88d74a960702c1674b1559623b2c09。用同样的命令查看

再继续看ReadMe中对应的

这样就看到了我们刚刚做的修改。

修改文件

当我们对ReadMe文件进行修改后,仓库中的ReadMe和工作区中的ReadMe是不同的,可以通过git status来查看距上次提交之后是否对文件进行修改。

它提示了,我们修改过了ReadMe但并没有添加和修改。

当我们好几个月前修改的代码,我们通过这个命令是看不到具体什么地方被修改的,所以我们就需要通过另一个命令来显示暂存区和工作区文件的差异git diff [file],也可以通过git diff HEAD -- [file]命令查看版本库和工作区的文件区别

版本回退

因为我们提到过,Git能够管理文件的历史版本,这也是它的主要作用之一。如果你因为工作出现问题,要在某个特定的历史版本重新开始,就需要版本回退功能了。

执行git reset命令用于回退版本,回退的本质是将版本库中的内容回退,工作区和暂存区是否回退由命令参数决定:

git reset [-- soft | -- mixed | -- hard ] [ HEAD ]
        --soft        --mixed                --hardHEAD
将版本库回退到某个指定版本工作区,工作区暂存区不变 默认选项,将暂存区的内容回退指定版本内容,工作区不变   暂存区和工作区回退到指定版本代表指定回退的版本

HEAD 说明:
可直接写成 commit id,表⽰指定退回的版本
HEAD 表⽰当前版本
HEAD^ 上⼀个版本
HEAD^^ 上上⼀个版本
以此类推...
可以使⽤ 〜数字表⽰:
HEAD~0 表⽰当前版本
HEAD~1 上⼀个版本
HEAD^2 上上⼀个版本
以此类推..

版本回退原理

 Git的版本回退速度非常快,因为Git内部有个指向当前分支的HEAD指针,就是refs/heads/master文件里保存的当前的master分支最新的commit id,当我们回退时候,master指针就会指向对应版本。

撤销修改

当我们在工作区写了很长时间代码后,但是老板不满意需要恢复到上一个版本怎么办,这时候分为三种情况:

1.工作区的代码,还没有add

root@hecs-95072:~/gitcode# vim ReadMe 
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试撤销修改 //新增代码

可以使用git checkout -- [file]命令会到最近一次add或者commit时状态

2.已经add,但没有commit

我们可以使用git reset命令,带上--mixed参数,然后用git checkout -- [file]命令撤销在工作区的修改

3.已经add和commit

可以用git reset --hard HEAD^命令回退到上一个版本,但有个前提,就是还没有把自己本地版本库推送到远程。

删除文件

可以通过git rm [file]命令删除暂存区和工作区文件

root@hecs-95072:~/gitcode# touch test1 //创建文件
root@hecs-95072:~/gitcode# ls
ReadMe  test1
root@hecs-95072:~/gitcode# git add test1  //add到暂存区
root@hecs-95072:~/gitcode# git commit -m "add test1"  //提交到版本库
[master 7b8ebfd] add test11 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 test1
root@hecs-95072:~/gitcode# git status
On branch master
nothing to commit, working tree clean
root@hecs-95072:~/gitcode# git rm test1  。。删除暂存区和工作区的test1文件
rm 'test1'
root@hecs-95072:~/gitcode# git status  //查看状态
On branch master
Changes to be committed:(use "git restore --staged <file>..." to unstage)deleted:    test1root@hecs-95072:~/gitcode# git commit -m "delete test1"  //提交修改结果
[master 729581a] delete test11 file changed, 0 insertions(+), 0 deletions(-)delete mode 100644 test1
root@hecs-95072:~/gitcode# git status
On branch master
nothing to commit, working tree clean

分支管理

分支管理是Git的最重要的功能之一,就像两个平行宇宙,你正在学习Git,另一个平行宇宙的你在学习Redis,两者互不干扰,但在一个时间点重合,这时的你既学会了Git又学会了Redis。

刚刚版本回退的图里面已经知道,每次提交,Git都会把它们串成一条时间线,一个时间线就是一个分支,master分支就是主分支。

HEAD是指向master的master指向提交,所以HEAD指向的就是当前分支。

创建分支

可以通过git branch dev创建一个dev分支,用git branch命令查看当前本地所有分支

*表示当前HEAD指向的分支是master分支,这时我们查看目录结构就可以看到新的分支

切换分支

我们可以切换到dev分支下进行开发,使用git checkout命令

这时HEAD就指向了dev分支上,下图便于理解:

我们可以在dev分支上进行操作并提交,再回到master分支上看看结果是不是一样

可以看到master分支上的内容并没有变化,可以看看dev和master分支指向,发现两者指向是不同的:

是因为我们在dev分支上提交的,切换到master分支后,master分支此刻的提交点并没有改变,HEAD此时指向的是master分支,如图所示:

合并分支

我们要在master分支上看到新的提交,就需要将dev分支合并到master分支上:

git merge命令用于合并指定分支到当前分支,合并后,master就能看到dev分支提交的内容了

删除分支

合并冲突

当我们想合并分支时,并不是每次都会成功,比如下面这个例子:

root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突aaa  //修改代码
root@hecs-95072:~/gitcode# git add ReadMe 
root@hecs-95072:~/gitcode# git commit -m "测试合并冲突"
[dev d1b0845] 测试合并冲突1 file changed, 1 insertion(+), 1 deletion(-)
root@hecs-95072:~/gitcode# git checkout master
Switched to branch 'master'
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突111
root@hecs-95072:~/gitcode# vim ReadMe 
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突bbb  //此时master也进行修改
root@hecs-95072:~/gitcode# git merge dev
Updating d35e425..d1b0845
error: Your local changes to the following files would be overwritten by merge:ReadMe
Please commit your changes or stash them before you merge.
Aborting

这时合并就会有冲突,如下图所示:

这时就要手动调整冲突代码,并再次提交修正后的结果

这时冲突就解决完成,此时状态变为:

分支管理策略

 我们在合并分支时,如果顺利,Git会采用Fast forward模式,删除分支后,查看分支历史,看不到分支信息,不知道最新提交的是合并进来的还是正常提交的。

但在合并冲突部分,我们会进行一次新的提交,这种不是Fast forward模式,这样的好处是,可以从分支历史看出分支信息,下图可以看到master是由其他分支合并得到的:

其实Git支持我们不使用这个模式,那么就会在merge时生成一个新的commit,这样从分支历史上就可以看出分支信息。

首先创建分支test,切换到此分支,修改ReadMe文件,并提交一个新的commit

切回master分支,合并两个分支

这里加上了 --no-ff参数,表示禁用Fast forward模式,因为禁用后会创建一个新的commit,所以要带上-m参数,写上本次描述。

 本次普通合并的状态为:

分支策略 

在平时开发中,我们应该按照几个基本原则进行分支管理;

首先,master分支是非常稳定的,最好仅用来发布新版本,不能在上面干活,干活都在其他分支上,到时候将其他分支合并到master上,在master上发布新版本。

bug分支

加入我们在test分支上进行开发,开发到一半,发现master分支上有bug需要解决。在Git中,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

当我们test分支工作区的代码写了一半,还无法提交怎么办?Git提供了git stash命令,可以将当前工作区信息进行储藏,被储藏的内容可以在某个时刻恢复出来。

此时就可以看到,执行完git stash命令后,用git status查看工作区就是干净的,接下来就可以安心处理bug。

root@hecs-95072:~/gitcode# git checkout -b bug                         //创建bug分支
Switched to a new branch 'bug'
root@hecs-95072:~/gitcode# vim ReadMe 
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突aaa
测试分支策略 假设修复完毕                                                       //假设修复完毕
root@hecs-95072:~/gitcode# git add ReadMe                          //重新add和commit
root@hecs-95072:~/gitcode# git commit -m "修复bug"
[bug 7bef88b] 修复bug
 1 file changed, 1 insertion(+), 1 deletion(-)
root@hecs-95072:~/gitcode# git checkout master
Switched to branch 'master'
root@hecs-95072:~/gitcode# git merge --no-ff -m "merge bug branch" bug
Merge made by the 'ort' strategy.
 ReadMe | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突aaa
测试分支策略 假设修复完毕
root@hecs-95072:~/gitcode# git branch -d bug                             //删除bug分支
Deleted branch bug (was 7bef88b).

此时,bug修复完毕,再回到test分支继续敲代码,可以看看刚刚的代码跑哪去了

我们可以通过git stash pop或者git stash apply命令来恢复,主要区别是前者恢复同时会把stash删了,后者不会。

但此时test分支并不能看见修复bug的代码,因为合并操作会冲突,我们最好在自己分支上合并master,再让master去合并自己分支,这样即便在解决冲突时出现错误,也不会影响master分支。(此处就不展示了)

删除临时分支

当我们需要添加实验性质代码时,为了不影响主代码,可以新建一个分支,称为feature分支,在上面开发,合并,最后删除。

但如果写到一半,这个分支不要了,用传统的git branch -d 命令删除是不行的,需要用到 git branch -D命令

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/24728.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构秘籍(一)线性数据结构

1.数组 数组&#xff08;Array&#xff09;是一种很常见的数据结构。它由相同类型的元素&#xff08;element&#xff09;组成&#xff0c;并且是使用一块连续的内存来存储。 我们直接可以利用元素的索引&#xff08;index&#xff09;计算出该元素对应的存储地址。 数组的特…

WiFi IEEE 802.11协议精读:IEEE 802.11-2007,6,MAC service definition MAC服务定义

继续精读IEEE 802.11-2007 6&#xff0c;MAC service definition MAC服务定义 6.1 MAC服务概述 6.1.1 数据服务 此服务为对等逻辑链路控制&#xff08;LLC&#xff09;实体提供交换MAC服务数据单元&#xff08;MSDU&#xff09;的能力。为支持此服务&#xff0c;本地媒体访…

QT基于mmap文件映射机制实现的内存池方法总结

在现代计算机系统中&#xff0c;高效的内存管理对于程序性能有着至关重要的影响。尤其是在处理大量数据或频繁分配和释放小块内存的应用场景下&#xff0c;传统的内存分配方式&#xff08;如malloc和free&#xff09;可能会导致显著的性能开销和内存碎片化问题。为了克服这些问…

车载DoIP诊断框架 --- 连接 DoIP ECU/车辆的故障排除

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

0—QT ui界面一览

2025.2.26&#xff0c;感谢gpt4 1.控件盒子 1. Layouts&#xff08;布局&#xff09; 布局控件用于组织界面上的控件&#xff0c;确保它们的位置和排列方式合理。 Vertical Layout&#xff08;垂直布局&#xff09; &#xff1a;将控件按垂直方向排列。 建议&#xff1a;适…

普中单片机-51TFT-LCD显示屏(1.8寸 STM32)

普中官方论坛&#xff1a; http://www.prechin.cn/gongsixinwen/208.html 普中科技-各型号开发板资料链接&#xff1a;https://www.bilibili.com/read/cv23681775/?spm_id_from333.999.0.0 27-TFTLCD显示实验_哔哩哔哩_bilibili 2.程序烧录 2.1设置彩屏驱动 3.实验效果

嵌入式开发工程师笔试面试指南-Linux系统移植

1 Linux内核启动流程 引导加载阶段 计算机通电后&#xff0c;首先由 BIOS 或 UEFI 进行初始化&#xff0c;完成硬件自检等操作。 找到可启动设备&#xff0c;读取其第一个扇区的 MBR&#xff0c;MBR 中的引导加载程序&#xff08;如 GRUB&#xff09;被加载到内存并运行。 内…

图扑数字孪生:解锁压缩空气储能管控新高度

​在能源转型的关键时期&#xff0c;压缩空气储能凭借其独特优势&#xff0c;成为解决可再生能源间歇性问题、保障可靠能源供应的重要技术。图扑软件&#xff08;Hightopo&#xff09;充分发挥其在 Web 2D&3D 可视化领域的技术专长&#xff0c;打造出先进的数字孪生压缩空气…

Redis 高可用性:如何让你的缓存一直在线,稳定运行?

&#x1f3af; 引言&#xff1a;Redis的高可用性为啥这么重要&#xff1f; 在现代高可用系统中&#xff0c;Redis 是一款不可或缺的分布式缓存与数据库系统。无论是提升访问速度&#xff0c;还是实现数据的高效持久化&#xff0c;Redis 都能轻松搞定。可是&#xff0c;当你把 …

AI 编码 2.0 分析、思考与探索实践:从 Cursor Composer 到 AutoDev Sketch

在周末的公司【AI4SE 效能革命与实践&#xff1a;软件研发的未来已来】直播里&#xff0c;我分享了《AI编码工具 2.0 从 Cursor 到 AutoDev Composer》主题演讲&#xff0c;分享了 AI 编码工具 2.0 的核心、我们的思考、以及我们的 AI 编码工具 2.0 探索实践。 在这篇文章中&am…

Qt Creator + CMake 构建教程

此教程基于: Qt 6.7.4Qt Creator 15.0.1CMake 3.26.4 Qt 6 以下的版本使用 CMake 构建可能会存在一些问题. 目录 新建窗体工程更新翻译添加资源软件部署(Deploy) 此教程描述了如何一步步在 Qt Creator 中使用 CMake 构建应用程序工程. 涉及 新建窗体工程, 更新翻译, 添加资源, …

锂电池保护板测试仪:电池安全的守护者与创新驱动力

在新能源产业蓬勃发展的今天&#xff0c;锂电池以其高能量密度、长循环寿命和环保特性&#xff0c;成为电动汽车、无人机、便携式电子设备等领域不可或缺的能量来源。然而&#xff0c;锂电池的安全性和稳定性一直是行业关注的焦点。为了确保锂电池在各种应用场景下的可靠运行&a…

岳阳市美术馆预约平台(小程序论文源码调试讲解)

第4章 系统设计 一个成功设计的系统在内容上必定是丰富的&#xff0c;在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值&#xff0c;吸引更多的访问者访问系统&#xff0c;以及让来访用户可以花费更多时间停留在系统上&#xff0c;则表明该系统设计得比较专…

【Java】I/O 流篇 —— 转换流与序列化流

目录 转换流原理InputStreamReader 转换输入流构造方法代码示例 OutputStreamWriter 转换输出流构造方法代码示例 练习 序列化流序列化流反序列化流**serialVersionUID**基本概念作用使用方式transient 关键字注意事项 转换流 原理 转换流属于字符流&#xff0c;是字符流和字节…

Mac 版 本地部署deepseek ➕ RAGflow 知识库搭建流程分享(附问题解决方法)

安装&#xff1a; 1、首先按照此视频的流程一步一步进行安装&#xff1a;(macos版&#xff09;ragflowdeepseek 私域知识库搭建流程分享_哔哩哔哩_bilibili 2、RAGflow 官网文档指南&#xff1a;https://ragflow.io 3、RAGflow 下载地址&#xff1a;https://github.com/infi…

计算机三级网络技术备考

#subtotal 1Mbps1024kb128KB12.8M/s #1024B1KB 1024KB1MB 1024MB1GB #路由器的5G信号和平常的波长不同&#xff08;5G的穿墙性能差&#xff09; #局域网LAN&#xff08;一公里内——构成集线机、交换机、同轴电缆&#xff09; #城域网MAN&#xff08;几公里到几十公里——光…

IDEA 2024.1 最新永久可用(亲测有效)

今年idea发布了2024.1版本&#xff0c;这个版本带来了一系列令人兴奋的新功能和改进。最引人注目的是集成了更先进的 AI 助手&#xff0c;它现在能够提供更复杂的代码辅助功能&#xff0c;如代码自动补全、智能代码审查等&#xff0c;极大地提升了开发效率。此外&#xff0c;用…

30 分钟从零开始入门 CSS

前言 最近也是在复习&#xff0c;把之前没写的博客补起来&#xff0c;之前给大家介绍了 html&#xff0c;现在是 CSS 咯。 30分钟从零开始入门拿下 HTML_html教程-CSDN博客 一、CSS简介&#xff1a;给网页“化妆”的神器 CSS&#xff08;层叠样式表&#xff09;就像“化妆“&a…

Game Maker 0.11更新:构建社交竞速游戏并增强玩家互动

在这三部分系列中&#xff0c;我们将介绍如何实现Game Maker 0.11中一些最激动人心的新功能。 欢迎来到我们系列文章的第一篇&#xff0c;重点介绍了The Sandbox Game Maker 0.11更新中的新特性。 The Sandbox Game Maker 0.11是一个多功能工具&#xff0c;帮助创作者通过游戏…

软件供应链安全工具链研究系列——RASP自适应威胁免疫平台(上篇)

1.1 基本能力 RASP是一种安全防护技术&#xff0c;运行在程序执行期间&#xff0c;使程序能够自我监控和识别有害的输入和行为。也就是说一个程序如果注入或者引入了RASP技术&#xff0c;那么RASP就和这个程序融为一体&#xff0c;使应用程序具备了自我防护的能力&#xff0c;…