乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

Linux常用指令集

发表于 2020-01-20

常用指令集介绍如下:

  1. 访问源列表中的每个网址,并读取软件列表,然后保存在我们的电脑上
1
sudo apt-get update
  1. 安装可以更新的软件
1
sudo apt-get upgrade
  1. 编辑sources文件
1
sudo edit /etc/apt/sources.list
  1. 拷贝文件
1
sudo cp /etc/apt/sources.list  /etc/apt/sources.list_save
  1. 安装指定软件
1
sudo apt-get install [软件名称]
  1. 将sources.list文件中的archive.ubuntu.com全部替换成mirrors.ustc.edu.cn
1
sudo sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
  1. 只查看文件的第100行到第200行
1
sed -n ‘100,200p’+文件
  1. 删除第二到第五行
1
sed '2,5d'+文件
  1. 删除包含”My”的行到包含”You”的行之间的行
1
sed 'My/,/You/d'+文件
  1. 删除包含”My”的行到第十行的内容
1
sed '/My/,10d'+文件
  1. 设置文件可读可写可执行
1
sudo chmod 777 /etc/apt/sources.list
  1. 查看当前系统版本
1
cat /proc/version
  1. 查看当前ip地址
1
ifconfig

或者

1
ip addr
  1. 连续创建目录
1
mkdir -p ~/python ~/python/myapp
  1. 查看端口是否开启
1
netstat -na |grep [端口号]
  1. 查看当前用户
1
whoami

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

可能是把Docker的概念讲的最清楚的一篇文章

发表于 2020-01-20

【编者的话】本文只是对Docker的概念做了较为详细的介绍,并不涉及一些像Docker环境的安装以及Docker的一些常见操作和命令。

Docker是世界领先的软件容器平台,所以想要搞懂Docker的概念我们必须先从容器开始说起。如果你想和更多Docker技术专家交流,可以加我微信liyingjiese,备注『加群』。群里每周都有全球各大公司的最佳实践以及行业最新动态。

先从认识容器开始

什么是容器?

先来看看容器较为官方的解释:

一句话概括容器:容器就是将软件打包成标准化单元,以用于开发、交付和部署。

  • 容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。
  • 容器化软件适用于基于Linux和Windows的应用,在任何环境中都能够始终如一地运行。
  • 容器赋予了软件独立性,使其免受外在环境差异(例如,开发和预演环境的差异)的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突。

再来看看容器较为通俗的解释:

如果需要通俗的描述容器的话,我觉得容器就是一个存放东西的地方,就像书包可以装各种文具、衣柜可以放各种衣服、鞋架可以放各种鞋子一样。我们现在所说的容器存放的东西可能更偏向于应用比如网站、程序甚至是系统环境。

图解物理机、虚拟机与容器

关于虚拟机与容器的对比在后面会详细介绍到,这里只是通过网上的图片加深大家对于物理机、虚拟机与容器这三者的理解。

物理机:

虚拟机:

容器:

通过上面这三张抽象图,我们大概可以通过类比概括出: 容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。

相信通过上面的解释大家对于容器这个既陌生又熟悉的概念有了一个初步的认识,下面我们就来谈谈Docker的一些概念。

再来谈谈Docker的一些概念

什么是Docker

说实话关于Docker是什么并太好说,下面我通过四点向你说明Docker到底是个什么东西。

  • Docker是世界领先的软件容器平台。
  • Docker使用Google公司推出的Go语言进行开发实现,基于Linux内核的cgroup,namespace,以及AUFS类的UnionFS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。 由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。Docke最初实现是基于LXC。
  • Docker能够自动执行重复性任务,例如搭建和配置开发环境,从而解放了开发人员以便他们专注在真正重要的事情上:构建杰出的软件。
  • 用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。

Docker思想

  • 集装箱
  • 标准化: ①运输方式、②存储方式、 ③API接口
  • 隔离

Docker容器的特点

  • 轻量,在一台机器上运行的多个Docker容器可以共享这台机器的操作系统内核;它们能够迅速启动,只需占用很少的计算和内存资源。镜像是通过文件系统层进行构造的,并共享一些公共文件。这样就能尽量降低磁盘用量,并能更快地下载镜像。
  • 标准,Docker容器基于开放式标准,能够在所有主流Linux版本、Microsoft Windows以及包括VM、裸机服务器和云在内的任何基础设施上运行。
  • 安全,Docker赋予应用的隔离性不仅限于彼此隔离,还独立于底层的基础设施。Docker默认提供最强的隔离,因此应用出现问题,也只是单个容器的问题,而不会波及到整台机器。

为什么要用Docker

  • Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现“这段代码在我机器上没问题啊”这类问题;——一致的运行环境
  • 可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。——更快速的启动时间
  • 避免公用的服务器,资源会容易受到其他用户的影响。——隔离性
  • 善于处理集中爆发的服务器使用压力;——弹性伸缩,快速扩展
  • 可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。——迁移方便
  • 使用Docker可以通过定制应用镜像来实现持续集成、持续交付、部署。——持续交付和部署

每当说起容器,我们不得不将其与虚拟机做一个比较。

容器 VS 虚拟机

简单来说: 容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。

两者对比图

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

容器与虚拟机 (VM) 总结

  • 容器是一个应用层抽象,用于将代码和依赖资源打包在一起。 多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行 。与虚拟机相比, 容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动 。
  • 虚拟机(VM)是一个物理硬件层抽象,用于将一台服务器变成多台服务器。 管理程序允许多个VM在一台机器上运行。每个VM都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此占用大量空间。而且VM启动也十分缓慢 。

通过Docker官网,我们知道了这么多Docker的优势,但是大家也没有必要完全否定虚拟机技术,因为两者有不同的使用场景。虚拟机更擅长于彻底隔离整个运行环境。例如,云服务提供商通常采用虚拟机技术隔离不同的用户。而Docker通常用于隔离不同的应用 ,例如前端,后端以及数据库。

容器与虚拟机(VM)两者是可以共存的

就我而言,对于两者无所谓谁会取代谁,而是两者可以和谐共存。

Docker中非常重要的三个基本概念,理解了这三个概念,就理解了 Docker 的整个生命周期。

Docker基本概念

Docker包括三个基本概念:

  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

镜像(Image)——一个特殊的文件系统

操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载root文件系统为其提供用户空间支持。而Docker镜像(Image),就相当于是一个root文件系统。

Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。

Docker设计时,就充分利用Union FS的技术,将其设计为分层存储的架构。 镜像实际是由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

容器(Container)——镜像运行时的实体

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

按照Docker最佳实践的要求,容器不应该向其存储层内写入任何数据 ,容器存储层要保持无状态化。所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此, 使用数据卷后,容器可以随意删除、重新run,数据却不会丢失。

仓库(Repository)——集中存放镜像文件的地方

镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry就是这样的服务。

一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。所以说:镜像仓库是Docker用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。

这里补充一下Docker Registry公开服务和私有Docker Registry的概念:

Docker Registry公开服务是开放给用户使用、允许用户管理镜像的Registry服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

最常使用的Registry公开服务是官方的Docker Hub ,这也是默认的Registry,并拥有大量的高质量的官方镜像,网址为:hub.docker.com/ 。在国内访问Docker Hub可能会比较慢国内也有一些云服务商提供类似于Docker Hub的公开服务。

除了使用公开服务外,用户还可以在本地搭建私有Docker Registry 。Docker官方提供了Docker Registry镜像,可以直接使用做为私有Registry服务。开源的Docker Registry镜像只提供了Docker Registry API的服务端实现,足以支持Docker命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。

最后谈谈:Build,Ship,and Run

如果你搜索Docker官网,会发现如下的字样:“Docker - Build, Ship, and Run Any App, Anywhere”。那么Build,Ship,and Run到底是在干什么呢?

  • Build(构建镜像):镜像就像是集装箱包括文件以及运行环境等等资源。
  • Ship(运输镜像):主机和仓库间运输,这里的仓库就像是超级码头一样。
  • Run (运行镜像):运行的镜像就是一个容器,容器就是运行程序的地方。

Docker运行过程也就是去仓库把镜像拉到本地,然后用一条命令把镜像运行起来变成容器。所以,我们也常常将Docker称为码头工人或码头装卸工,这和Docker的中文翻译搬运工人如出一辙。

总结

本文主要把Docker中的一些常见概念做了详细的阐述,但是并不涉及Docker的安装、镜像的使用、容器的操作等内容。这部分东西,希望读者自己可以通过阅读书籍与官方文档的形式掌握。

本文转载自:https://mp.weixin.qq.com/s/xSbYTJmLuqsyYEDEIsndZw

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

轻量级组件化插件 告别传统组件化累赘和编译过慢

发表于 2020-01-20

framework-plugin 组件化架构插件

Github

优势

  • 轻量级组件框架
  • 即插即用
  • 使用json文件动态配置, 减少同步时间

使用

  1. 在项目的 build.gradle 中添加:
1
2
3
4
5
6
7
8
9
buildscript {
repositories {
...
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.github.songjianzaina:framework-plugin:1.0.6-alpha'
}
}
  1. 在宿主module中使用插件
1
apply plugin: 'framework-plugin'
  1. 同步工程,等待文件夹自动生成

配置

你可以在build.gradle中配置插件的几个属性,如果不设置,所有的属性都使用默认值

1
2
3
4
5
frame{
subDirName "androidModule"//子模块目录 App默认androidModule Lib默认androidLib
jsonName "androidModule"//子模块json文件名 默认同上

}

工程效果图:

以上标红目录在应用插件后皆自动生成 无需手动创建

更新历史

版本号 功能点 链接
1.0.0 初步实现架构文件自动生成 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v7qfftdb-1627370867510)(https://api.bintray.com/packages/songjianzaina/insoan/framework-plugin/images/download.svg?version=1.0.0)]
1.0.1 增加全局文件夹以及全局libs [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXeFHBcf-1627370867512)(https://api.bintray.com/packages/songjianzaina/insoan/framework-plugin/images/download.svg?version=1.0.1)]
1.0.2 增加子模块目录名和配置文件名自定义配置 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ur648Ij1-1627370867513)(https://api.bintray.com/packages/songjianzaina/insoan/framework-plugin/images/download.svg?version=1.0.2)]
1.0.3 优化清单文件合并 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p285dTfB-1627370867514)(https://api.bintray.com/packages/songjianzaina/insoan/framework-plugin/images/download.svg?version=1.0.3)]
1.0.4 增加Activity自动注册清单文件 (还未完善) [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IKpgb7YM-1627370867514)(https://api.bintray.com/packages/songjianzaina/insoan/framework-plugin/images/download.svg?version=1.0.4)]
1.0.5 1.升级gradle依赖至4.0.0
2.新增values目录下attr和styles文件的自动生成
3.解决子模块libs目录so库无法引用的问题
4.优化插件加载方式 提升构建速度
5.移除多余log
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-66UCHd9Z-1627370867515)(https://api.bintray.com/packages/songjianzaina/insoan/framework-plugin/images/download.svg?version=1.0.5)]

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

如何利用百度文库上传付费文档,实现持续收益

发表于 2020-01-12

最近有一个很火的概念,称之为“个人商业模式”!所谓个人商业模式,就是个人出售时间的方式,我们每个为生活奔走忙碌的人都有自己的商业模式。本质上都是在出售自己的时间在赚钱!

“个人商业模式”一般情况有以下三种。

1、一份时间出售一次。

比如每天工作8小时,为老板打工,即出售自己的时间为老板打工,这八小时只能为我们带来一次收入!这是第一种商业模式,即一次时间出售一次。

2、一份时间出售多次。

持续收益,躺着赚钱。比如作家出了一本书,然后进行出版吗,畅销5年。那么作家在睡觉的时候都会有人为我的书籍付费。这就是第二种商业模式。即一份时间出售多次。

3、购买别人的时间,再卖出去。

比如作为一个老板,招聘了5个员工,员工为老板打工。其实就是老板在买下员工的时间,然后再卖出去!

我们大多数人都是第一种商业模式,赚的钱都是辛苦钱。如果我们想赚更多的钱,就要学会第二种商业模式,即躺着也能有收入。

那么今天就有一个躺着也能有收入的点子,小编想要分享给大家,希望能帮助到你们!

这个点子被大多数人给疏忽了,其实就是利用百度文库上传付费文档项目,“搬砖”赚钱,尤其是在这个知识付费的年代显得更有优势!

接下来为大家分析一下项目的具体操作!

一、项目简介。

百度相信很多朋友都知道,他是百度发布的供网友在线分享文档的平台。

有很多为了学习,查资料的伙伴都会时不时的上百度文库搜寻查找相关资料。搜着搜着,搜到很多,有免费的,有付费的,但一般写的好的,都需要下载券,也不贵,两块钱就可以了,如果找到我们适合的,说不定我们就直接买了。

可是钱都到哪里去了?百度文库的文档由百度用户上传,需要经过百度的审核才能发布。

没错,钱都到上传者手中去了!一篇文章一块两块,中国用户这么多,如果是多个文档呢?想必就会越多,并且文档长久都有效!

我们看下面这个账号

付费文档有10元,15元,5元,大多数都是5元,已经有接近6万次的下载,即使是除去一半的免费文档,也有3万次的下载量,一篇5元,也有15万元左右的收益。并且是重复多次收益。用户躺着睡觉也有收益!

通过研究多个百度文库用户的账号,我发现了他们的赚钱套路,一般都是先给免费的看,然后看到后面就需要付费。

这个项目就是,在百度文库(道客巴巴、豆丁网也是一样的)成为认证用户,上传你的资料,并设置合理的价格,来钱就是这么简单,借助平台自身流量,不需你做太多的推广。

第二步、项目具体操作

1、注册账号。

这个按照规则去做就可以了。

2、上传文档。

建议伙伴们先了解百度文库上传的规则,否则上传不通过的话,就白做了哦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

!![](https://gitee.com/songjianzaina/SavePicGoPic/raw/master/img/u=2179562780,1282340770&fm=173&app=25&f=JPEG)

另外再上传文档的时候给大家分享几个技巧。

1. 页眉可以设置信息。设置的信息可以用来打造个人ip!

2. 标题和描述都可以布局出现需要优化的长尾关键词,有助于文档的排名,让更多的人看到!

3. 文档的开头、中间、结尾都可以适当的出现需要优化的关键词!

4. 排版干净利落,层次分明!

三、那么上传的内容从哪里获得呢?

文档上传内容是有讲究的,只有你的文档有价值了,才会有人付费下载你的上传的文档的,所以上传一些干货才是能赚钱的法宝。

#### 干货去哪里找?有两种方法。

1、伙伴们可以去资源整合网上找。

2、如果不想出钱的话就自个去整理,自己去生产原创干货内容。但注意一定得是干货,否则上传上去不会翻出什么花来哦~

其实整个项目都很简单,只是被大多数人给忽略掉了,看的上的伙伴可以去尝试一下,这样长期下来也算是一笔财富!

一次付出,躺着也有收入,虽然一次不多,但是积少成多嘛

1
2

不仅仅是上传到百度文库,豆丁网,道客巴巴我们都可以操作哦

关于“个人商业模式”,说白了就是赚钱的事。我觉得我们都应该去思考自己的商业模式以及如何打造更好的商业模式!

因为持续收益才是我们实现财务自由的唯一方式!

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

dom4j解析XML常用方法

发表于 2020-01-08

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//读取xml
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
// 获取根节点
Element root = document.getRootElement();
// 获取孩子节点
Iterator<Element> it1 = root.elementIterator();
// 获取属性
Iterator<Attribute> attributes = ele.attributeIterator();
/*
以上两个获取孩子节点和属性都是获取迭代器, 通过it.hasnext()方法可以遍历得到所有的节点和属性.
*/
// 获取节点名
ele.getName()
// 获取节点值
ele.getText()
// 获取属性名
ele.getBName
// 获取属性值
ele.getValue()
// 设置文本
ele.setText("张三");
//设置属性
ele.addAttribute("show", "yes");
//添加注释
ele.addComment("This is a test for dom4j ")
// 删除子节点
ele.remove(element);

创建XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class CreateXML {
public static void main(String[] args) throws Exception {
// 创建文档对象
Document document = DocumentHelper.createDocument();

// 创建根节点
Element root = document.addElement("root");

// 添加节点信息
Element auther1 = root.addElement("auther")
.addAttribute("name", "Tom") // 属性
.addAttribute("loation", "UK")
.addText("Tom Wang"); // 节点内容

Element auther2 = root.addElement("auther")
.addAttribute("name", "Ted")
.addAttribute("loation", "USA")
.addText("Ted Chen");

// 输出到xml文件
FileWriter out = new FileWriter("src/new.xml");
document.write(out);
out.close();
}
}

输出的内容为

1
2
3
4
5
6
<!--new.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<root>
<auther name="Tom" loation="UK">Tom Wang</auther>
<auther name="Ted" loation="USA">Ted Chen</auther>
</root>

修改XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 创建xml解析器对象reader
SAXReader reader = new SAXReader();
// 加载xml文件, 获取document对象
Document document = reader.read("src/test_xml/first.xml");
//选定节点属性集 xpath写法
List arrList = document.selectNodes("/books/book/@show")
Iterator arrIter = arrList.iterator();

//选定节点集
List list = document.selectNodes("/books/book/title")
Iterator texIter = list.iterator();
//修改节点属性
while (arrIter.hasNext()) {
Attribute attribute = (Attribute) iter.next();
if (attribute.getValue().equals("yes"))
attribute.setValue("no");
}
//修改节点文本内容
while (texIter.hasNext()) {
Element element = (Element) iter.next();
element.setText("xxx")
}

字符串转XML

1
2
String text = "<members> <member>sitinspring</member> </members>";      
Document document = DocumentHelper.parseText(text);

XML转字符串

1
2
3
4
5
6
// 创建xml解析器对象reader
SAXReader reader = new SAXReader();
// 加载xml文件, 获取document对象
Document document = reader.read("src/test_xml/first.xml");
//xml转换成字符串
String memberXmlText=document.asXML();

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Git Submodule的介绍与使用

发表于 2020-01-04

场景复现

公司有10个项目正在开发, 以后会陆陆续续增加新项目, 而这些项目都用到公共的一些类库, 如果你是技术负责人, 你会选择哪个方案?

方案一: 将公共类库依次拷贝至10个项目中 (不推荐 一旦类库需要修改, 你需要修改不只10遍)

方案二: 将公共类库封装成第三方框架, 放在公共仓库, 每个项目各自引入,(使用方便, 但是不方便修改源代码 不推荐)

方案三: 将公共类库源代码放在公有仓库, 每个项目下分别clone, ( 方便修改类库代码, 也方便同步修改,但是主工程项目会将类库代码并入主工程提交, 两个仓库独立性不够, 有时候我可能只想先pull没有类库的代码, 这个时候就不方便了)

引出Git Submodule

为了增加公共类库与主项目的独立性, Git 给大家提供了子模块功能 允许你将一个 Git 仓库作为另一个 Git 仓库的子目录 , 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立

开始使用

添加子模块

1
git submodule add <仓库地址> <本地路径>//如果不指定本地路径 默认放在当前目录下

将子模块代码同步至远程仓库

进入到子模块目录下, 指定分支:

1
git checkout master //这里以master分支为例

然后

1
2
git commit -am "修改类库"
git push

从远程仓库更新代码

在父模块目录下执行以下命令:

1
git submodule update --remote

或者

直接进入到子模块目录下:

1
git pull

两者效果都是一样的

除此之外还可以使用以下指令对多个子模块进行批量更新:

1
git submodule foreach --recursive git pull

或者

1
git pull --recurse-submodules

注意:如果你的子模块内部也包含了一个子模块, 你可以使用:

1
git submodule foreach git submodule update

进行遍历更新

删除子模块

  1. 首先执行以下命令移除子模块引用:

    1
    git submodule deinit <submodule_path>

    其中,<submodule_path> 是子模块的相对路径或URL。这将取消子模块的连接,并使其变回普通的目录。

  2. 执行以下命令来从 .gitmodules 文件中移除子模块的记录:

    1
    git rm --cached <submodule_path>

    同样,<submodule_path> 是子模块的相对路径或 URL。该命令会将子模块的相关配置从Git仓库中移除。

  3. 执行以下命令删除子模块的相关目录和文件

    1
    2
    git rm <submodule_path>
    rm <submodule_path>

移动子模块

要将 Git 中的子模块移动到另一个目录,可以按照以下步骤进行操作:

  1. 进入包含子模块的 Git 仓库的根目录。

  2. 执行以下命令来修改子模块的路径:

    1
    git mv <current_submodule_path> <new_submodule_path>

    其中,<current_submodule_path> 是当前子模块的路径,<new_submodule_path> 是你想要将子模块移动到的新路径。该命令会将子模块在 Git 仓库中的路径更改为新路径。

  3. 修改包含子模块的父项目中 .gitmodules 文件中子模块的路径记录。打开该文件,并将与子模块相关的路径修改为新的路径。

  4. 提交代码变更:

    1
    2
    git add .gitmodules
    git commit -m "Move submodule to new directory"
  5. 更新子模块引用:

    1
    git submodule sync --recursive

    这将使父项目更新其对子模块的引用,以适应新的路径。

  6. 执行以下命令来完成子模块路径的更新:

    1
    git submodule update --init --recursive

    该命令会更新父项目中的子模块路径,并将子模块检出到新的目录中。

将本地仓库添加为子模块

如果你的本地已经有了一个仓库,并希望将其设置为某个项目的子模块,而不重新下载该仓库,可以按照以下步骤操作:

  1. 在父项目的根目录下打开命令行工具。

  2. 使用 git submodule add 命令添加子模块,但是在这里我们指定本地路径作为子模块的位置而不是远程仓库的URL。例如:

    1
    git submodule add /path/to/local/repo path/to/submodule

    将 /path/to/local/repo替换为你本地仓库的实际路径,path/to/submodule 替换为你希望子模块存放的相对路径(相对于父项目的根目录)。

  3. 接下来将子模块的引用地址改为远程仓库地址

    进入父项目的根目录,在命令行工具中执行以下命令来修改子模块的引用地址:

    1
    git submodule set-url <submodule_path> <remote_repository_url>

    其中 <submodule_path> 是子模块所在的路径(相对于父项目的根目录),<remote_repository_url>是子模块的远程仓库地址

  1. 运行上述命令后,Git 会将本地仓库的当前状态作为子模块的初始状态,而无需重新下载。

注意: git submodule set-url是``Git 2.25以上版本才有的功能, 使用前需要先检查一下您当前的git版本

工程克隆

团队开发的时候, 进来一个新的成员, 他首次clone项目的时候, 并不会将子模块一并clone进来

这个时候, 需要先初始化子模块:

1
2
3
4
5
# 用来初始化本地配置文件
git submodule init
# 从该项目中抓取所有数据并检出父项目中列出的合适的提交(指定的提交)。
git submodule update
(以上两条命令也可以合并成一条组合命令:git submodule update --init --recursive)

或者直接:

1
2
# clone 父仓库的时候加上 --recursive,会自动初始化并更新仓库中的每一个子模块
git clone --recursive https://gitee.com/xiaomumaozi/SubModule_Test.git

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用计算器进行开方的两种方法

发表于 2020-01-04

生活中很少使用到开方运算, 前段时间为了计算理财复合收益率, 运用到了这一块的内容, 在这里做个记录

场景复现

比如64需要进行开6次方的操作, 计算器该如何操作呢?

第一种

第二种

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Git如何删除某次commit

发表于 2020-01-03

在团队开发的时候, 经常会出现某次commit导致整个项目出现无法名状的错误, 这个时候, 最好的解决办法就是删除错误的commit

场景复现一

1.假设有2个提交记录

1
2
3
4
5
6
7
8
9
10
11
12
13
commit def5adef853da4cc05752bdb36577c127be71ba5

Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

优化代码

commit f36801544670e00b2f59a28e19017d2786c4085e
Author: xxx
Date: Thu Dec 28 15:59:46 2017 +0800

修复
(END)

2.现在需要回滚到上一次提交

那么 我们可以使用

1
git reset --hard HEAD^

或者

1
git reset --hard HEAD~1

或者

1
git reset --hard f36801544670e00b2f59a28e19017d2786c4085e

3.执行完后 查看日志,就会发现只剩下一个提交了

1
2
3
4
5
6
7
8
git log

commit f36801544670e00b2f59a28e19017d2786c4085e
Author: xxx
Date: Thu Dec 28 15:59:46 2017 +0800

修复
(END)

4.如果这个时候,你突然发现回退版本错了,那么就用git reflog查看提交记录

1
2
3
4
5
6
7
git reflog

f368015 HEAD@{0}: reset: moving to f36801544670e00b2f59a28e19017d2786c4085e
def5ade HEAD@{1}: reset: moving to def5ade
f368015 HEAD@{2}: reset: moving to f36801544670e00b2f59a28e19017d2786c4085e
def5ade HEAD@{3}: commit: 优化代码
f368015 HEAD@{4}: commit (initial): 修复

5.然后找出想要回退的版本,进行回退

1
git reset --hard def5ade

6.如果此时需要同步远程仓库, 需要使用强推

1
git push -f

因为我们本地库HEAD指向的版本比远程库的要旧

由此可见, git reset可以很方便的回滚到指定的历史commit,

但是它的劣势也很明显, 一旦回滚到指定commit, 那么后面提交的commit都会一并删除

*为了保留后面需要的的commit内容, 咱们可以使用另一种指令 *git revert

场景复现二

1.假设有3个提交记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
commit def5adef853da4cc05752bdb36577c127be71ba5

Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

优化代码
commit 853dadef5adef4cc05752bdb36577c127be71ba5

Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

增加文件
commit f36801544670e00b2f59a28e19017d2786c4085e
Author: xxx
Date: Thu Dec 28 15:59:46 2017 +0800

修复
(END)

2.现在我们不需要第二个commit的操作,也就是不需要 增加文件 这个操作

那么, 我们可以使用git revert -n +版本号 命令进行反做

1
git revert -n 853dadef5adef4cc05752bdb36577c127be71ba5

注意: 这里可能会出现冲突,那么需要手动修改冲突的文件, 然后重新add提交

1
2
git add .
git commit -m "重做 增加文件"

3.执行完后 查看日志,会发现原来的commit记录还在,同时新增了一个commit版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
git log

commit 05752def5adef853da4ccbdb36577c127be71ba5
Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

重做 增加文件

commit def5adef853da4cc05752bdb36577c127be71ba5
Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

优化代码
commit 853dadef5adef4cc05752bdb36577c127be71ba5
Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

增加文件
commit f36801544670e00b2f59a28e19017d2786c4085e
Author: xxx
Date: Thu Dec 28 15:59:46 2017 +0800

修复
(END)

4.如果此时需要同步远程仓库

1
git push

使用git revert这种方式既可以清除指定的commit操作, 同时可以保留后面的commit

但是也存在一个让人不舒服的地方, 虽然操作被重写了,但是记录还在, 而且由新增了一个记录,感觉有些冗余

为了解决这个问题, 最后我选择了第三种方式, 也就是使用 git rebase 节点切片

场景复现三

1.假设有3个提交记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
commit def5adef853da4cc05752bdb36577c127be71ba5

Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

优化代码
commit 853dadef5adef4cc05752bdb36577c127be71ba5

Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

增加文件
commit f36801544670e00b2f59a28e19017d2786c4085e
Author: xxx
Date: Thu Dec 28 15:59:46 2017 +0800

修复
(END)

2.现在我们不需要第二个commit的操作,也就是不需要 增加文件 这个操作

假设是master分值那么, 我们可以使用git rebase --onto [startpoint] [endpoint]

1
git rebase --onto master~853dade master~def5ade master

或者

1
git rebase --onto master~2 master~1 master

或者使用

1
git rebase i f368015 /把 需要改动那条 commit 前面的 pick 改成drop 然后, 保存退出即可

3.执行完后 查看日志 指定的commit已被切除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git log

commit def5adef853da4cc05752bdb36577c127be71ba5
Author: xxx
Date: Thu Dec 28 16:01:36 2017 +0800

优化代码

commit f36801544670e00b2f59a28e19017d2786c4085e
Author: xxx
Date: Thu Dec 28 15:59:46 2017 +0800

修复
(END)

4.如果此时需要同步远程仓库

1
git push  -f

要注意的是,这样做会 彻底 删掉那条 commit。唯一的找回方式是通过 git reflog。

5.如果你只是想改下那条 commit 的 author

这样就行:

1
git rebase -i f368015

把 需要改动那条 commit 前面的 pick 改成 edit

然后

1
git commit --amend --author="xxxxxxxx"

然后

1
git rebase --continue

最后保存退出即可

总结

  • git reset

适用场景: 如果想恢复到之前某个提交的版本,且那个版本之后提交的版本我们都不要了,就可以用这种方法。

  • git revert

适用场景: 如果我们想撤销之前的某一版本,但是又想保留该目标版本后面的版本,记录下这整个版本变动流程,就可以用这种方法。

  • git rebase –onto和git rebase i

适用场景: 如果我们想撤销之前的某一版本,但是又想保留该目标版本后面的版本,彻底清除commit记录, 而又不增加新的commit记录, 就可以用这种方法

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

如何将gradle插件发布到插件门户网站

发表于 2019-12-29

Step 1: 创建账户.

点击注册.

注册地址:https://plugins.gradle.org/user/register

Step 2: 生成API key.

Step 3: 将 API key 添加到Gradle 配置中.

拷贝API Key到电脑$USER_HOME/.gradle/gradle.properties文件中,如果电脑没有该文件, 就自行创建一个

$USER_HOME 指的是你的电脑用户名

如果你嫌手动配置api麻烦, 可以使用官方的login task进行自动注册,

image-20210727105738873

执行login task 执行窗口会出现授权链接 点击浏览器打开即可

image-20210727110154697

在此之前需要先应用插件, 往下看:

Step 4: 使用官方插件进行代码的推送.

在你自己的插件工程build.gradle中添加如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 第一步 应用插件
plugins {
id "com.gradle.plugin-publish" version "0.10.1"

}


pluginBundle {
website = 'http://www.gradle.org/'//你自己的插件官网地址
vcsUrl = 'https://github.com/gradle/gradle'//插件版本同步地址 填写你的github地址即可
description = 'Greetings from here!'//插件描述
tags = ['greetings', 'salutations']//标签 便于搜索

plugins {
greetingsPlugin {
version = "1.2" //插件版本号
group = "com.foo.myplugin"//插件包名
displayName = '这里填写在插件官网中显示的名称'
}
}
}

配置完成后,执行 publishPlugins task即可自动上传代码

Step 5: 等待审核.

审核通过后,即可在官网搜索到你的插件, 上面附有插件的使用方法

Step 6: 完成.

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

强制刷新gradle依赖缓存的方法

发表于 2019-12-28

有时候我们需要在不改变版本号的前提下 同步gradle重新从远程更新依赖包

方案一:

修改项目任意一个依赖库版本号,然后同步gradle,同步完成后再改回来

方案二:

执行以下指令强制刷新

1
2
3
4
5
6
Windows:    
gradlew build --refresh-dependencies


Mac:
./gradlew build --refresh-dependencies

本帖附件

点击下载

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…434445…50

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

491 日志
143 标签
RSS
© 2025 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%