江湖道

庙堂,江湖,学术!

返回顶部

了解Git,这一篇就够了

作为一个7年经验的程序员,不该来总结这么基础的东西。但是人总是在高估自己的水平,本周在做一个代码集成的工作时,在git上犯了迷糊,导致很简单的集成,愣是做了两天,费劲不说,还浪费时间。思考了下,根本原因还是基础不牢。在一个行业做上7年,基本上应该是资深了吧?但是细节上到底能深究多少呢?所以还是脚踏实地的来。不在乎基础不基础了,开始吧!把喜欢的事情做到极致,便能产生价值。

0. 前序

版本控制

什么是版本控制呢?官方话是这样说的:版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理。

如果项目一个人一气呵成,并且不需要迭代的话,也不需要什么版本控制了,但是这是不可能的。其实版本控制是在时间维度上实现代码迭代的可追溯性,空间上多人协作,实现代码质量的并行管理。

what-is-vcs

git正是一种版本控制系统。

1.git 介绍

版本控制系统大的维度上可分为两种:一种是分布式,一种是中心式;

git是分布式的结构,另一个系统SVN则是中心式;

中心式结构的版本控制系统是只有一个中心,这个“中心”就是一个特别的服务器,它是一个中央仓库,每个开发者从这个中央仓库下载最新版的项目到本地、然后开发、然后上传给中央仓库。

中心式系统特别依赖这个中心,如果本地与中心的连接出问题、或中心本身出了问题,都可能影响到项目开发。而 Git 理论上是没有中心的,每一个设备都有本地仓库,任何一个设备的本地仓库出问题对其他设备都没有影响。而且,每一个设备都可以创建分支,Git 强大的分支管理也是它的价值所在。

clip_image0002

1.1 git的前世今生

讲过故事:

在1991-2002这十余年时间,版本控制软件已经出现,像CVS,SVN等。然而linux之父linus是坚定反对使用CVS和SVN。

2002年到2005年,linus顶着开源社区精英们的口诛笔伐,选择了一个商业版本控制系统BitKeeper作为linux内核的代码管理工具。BitKeeper不同于CVS和SVN等集中式版本控制工具,而是一款分布式版本控制工具。

分布式版本控制系统最大的反传统之处在于,可以不需要集中式的版本库,每个人都工作在通过克隆建立的本地版本库中。也就是说每一个人都拥有一个完整的版本库,查看提交日志,提交、创建里程碑和分支、合并分支、回退等所有操作都直接在本地完成而不需要网络连接。

2005年4月,Andrew Tridgell(Samba的作者)试图对BitKeeper进行反破解,以开发一个能与BitKeeper交互的源码工具。这激怒了BitKeeper软件的所有者BitMover公司,要求回收对linux社区免费试用BitKeeper的授权。

迫不得已,linus选择了自己开发一个分布式的版本控制工具替代BitKeeper。

历时2个多月在linux内核2.6.12发布时,Git诞生了。完成原形设计后,在2005年7月,linus退身,将git的维护交给了一个Git的主要贡献者Junior C Hamano,直到现在。

git官网:https://git-scm.com/

来翻译一段话:

image

Git是一个免费开源的分布式版本控制系统,被设计是为了快速高效的处理项目从小到大的每一件事。

Git是一个容易学习并且有一个极小的空间承载轻量快速的性能。它以廉价的本地分支,方便的暂存区,以及多线程的工作流等性能,远远超过SCM的工具像Subversion,CVS,Perforce和ClearCase等工具。

四级没过,见笑。

1.2 git与 SVN对比

前面以了解git是分布式的设计,svn是中心式设计,接下来继续对比两者管理方式的异同。

1583984290430

代码管理:

Git是对分布式管理:

(1)每一个人的电脑都有一个版本库,对网络依赖性不大,因为版本库就在自己电脑上(本地库)。
(2)中央服务器是用来交换大家修改的内容(远程库)
(3)即使中央服务器宕机了,也可以立即从本地库中恢复代码。

clip_image00001102

SVN是集中式管理:

(1)版本库是集中式存放在中央服务器的,每次必须联网获取新的代码,工作完成之后再推送到中央服务器。
(2)这个的弊端就是必须联网,局域网内还可以,如果是互联网的话,在带宽不够的情况下上传一份大文件,就会很慢,体验很差。

clip_image0212101

存储方式:

clip_image00001001

clip_image00001

1.3 git核心

Git 最核心的一个概念就是工作流。

工作区(Workspace)是电脑中实际的目录。
暂存区(Index)类似于缓存区域,临时保存你的改动。
仓库区(Repository),分为本地仓库和远程仓库。

通常提交代码分为几步:

git add从工作区提交到暂存区

git commit从暂存区提交到本地仓库

git push或git commit从本地仓库提交到远程仓库

一般来说,记住以下命令,便可进行日常工作了,但不止于此。

clip_image00001012

2 git的安装与配置

一般linux系统的发现版只要不是min版本,基本都有git工具,若没有再网络环境下可yum安装。但是安装的版本可能不是滞后。这里我们介绍源码安装与配置。

此次安装使用的是Anolis 8.4的系统,关于Anolis系统有兴趣了解的可以在龙蜥社区了解。Centos 8停服后,国内包括阿里在内的一些企业成立龙蜥社区,扛起了开源操作系统的大旗。目前社区活跃,真是很感谢业界优秀的人和优秀的企业为业界提供了方便。本次安装,没想到会如此顺利,据官方文档说明,Anolis 8.4已完全兼容Centos 8的生态,已支持海光、飞腾、兆芯、鲲鹏服务器。https://www.yuque.com/anolis-docs/manual/release-notes-8.4

不聊了,干正事!

2.1 git安装

Git的官方网站:http://git-scm.com/
源码包下载地址:https://mirrors.edge.kernel.org/pub/software/scm/git/

2.1.1 配置git服务器

服务器环境:

image

安装软件及依赖:

  1 [root@localhost ~]# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel -y
  2 [root@localhost ~]# yum install -y git 
  3 [root@localhost ~]# rpm -aq |grep git
  4 libertas-usb8388-firmware-20220210-107.git6342082c.an8.noarch
  5 dracut-049-201.git20220131.an8.x86_64
  6 crontabs-1.11-17.20190603git.an8.noarch
  7 git-core-2.39.3-1.0.1.an8.x86_64
  8 git-2.39.3-1.0.1.an8.x86_64
  9 dracut-network-049-201.git20220131.an8.x86_64
 10 dracut-squash-049-201.git20220131.an8.x86_64
 11 crypto-policies-20211116-1.gitae470d6.an8.noarch
 12 libnsl2-1.2.0-2.20180605git4a062cf.el8.x86_64
 13 git-core-doc-2.39.3-1.0.1.an8.noarch
 14 net-tools-2.0-0.52.20160912git.an8.x86_64
 15 dracut-config-rescue-049-201.git20220131.an8.x86_64
 16 linux-firmware-20220210-107.git6342082c.an8.noarch
 17 crypto-policies-scripts-20211116-1.gitae470d6.an8.noarch

(3)创建用户及用户组

  1 [root@localhost ~]# groupadd git
  2 [root@localhost ~]# useradd git -g git

(4)初始化Git仓库

  1 [root@localhost ~]#  cd /home/
  2 [root@localhost home]# mkdir gitrepo
  3 [root@localhost home]# chown -R git:git gitrepo/
  4 [root@localhost home]# cd gitrepo/
  5 [root@localhost gitrepo]# git init --bare runoob.git
  6 提示:使用 'master' 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中
  7 提示:配置使用初始分支名,并消除这条警告,请执行:
  8 提示:
  9 提示:	git config --global init.defaultBranch <名称>
 10 提示:
 11 提示:除了 'master' 之外,通常选定的名字有 'main'、'trunk' 和 'development'。
 12 提示:可以通过以下命令重命名刚创建的分支:
 13 提示:
 14 提示:	git branch -m <name>
 15 已初始化空的 Git 仓库于 /home/gitrepo/runoob.git/
 16 [root@localhost gitrepo]# chown -R git:git runoob.git/
 17 [root@localhost gitrepo]# ll
 18 总用量 0
 19 drwxr-xr-x 7 git git 119 6月  10 16:48 runoob.git
克隆官方的仓库到本地仓库,作为自己的仓库(当然也可以自己创建)用于测试功能。
  1 [root@localhost gitrepo]# git clone https://github.com/jenkins-docs/simple-java-maven-app.git
  2 正克隆到 'simple-java-maven-app'...
  3 remote: Enumerating objects: 151, done.
  4 remote: Total 151 (delta 0), reused 0 (delta 0), pack-reused 151
  5 接收对象中: 100% (151/151), 23.90 KiB | 126.00 KiB/s, 完成.
  6 处理 delta 中: 100% (41/41), 完成.
  7 [root@localhost gitrepo]# ll
  8 总用量 0
  9 drwxr-xr-x 7 git  git  119 6月  10 16:48 runoob.git
 10 drwxr-xr-x 5 root root 116 6月  10 16:52 simple-java-maven-app

这个其实已经配置好了一个git仓库。实际上git是分布式的,用以上方法搭建的仓库拉取推送代码是没有问题的,不过git还有些衍生的客户端程序,可以给我们开发工作提供便利,例如TortoiseGit。

提示:该部分内容纯属了解即可,实际开发中我们的IDE工具比他好用多了,但是如果在win上做打包集成的话,还是有用的。不就结了,讲讲吧!

2.2 安装git客户端

我就在windows上安装了,其他操作系统参考官网:https://git-scm.com/downloads

windows安装git不在赘述,点点点就行

安装完成后生成公钥:

下载git客户端安装好后右键选择Git GUI Here->Help->Show SSH Key

image

就能得到私钥和公钥:

image

2.3 TortoiseGit安装与配置

TortoiseGit简称tgit,中文名海龟git,海龟git只支持window系统。

支持各种语言,包括简体中文(Chinese,simplified:zh_CN).

下载:http://download.tortoisegit.org/tgit/

安装没有什么技术含量,略了。

2.3.1 基础配置

(1)首先,请选定一个存放Git项目的目录,方便管理,例如:E:\DevPro,然后在资源管理中打开。

(2)在空白处点击鼠标右键,选择--》TortoiseGit--》Settings,然后可以看见配置界面:

(3)选中General,在右边的language中选择中文,不够选自动升级的复选框,可能还需要指定Git.exe文件的路径,完成后点击应用,确定关闭对话框。

(4)在此点击鼠标右键,可以看到弹出菜单中已经变成中文

以上两步的前提是要安装汉化包。

(5)配置右键菜单,在设置对话框中,点击右边的“右键菜单”,然后在右边将所有的复选框都去掉,这样右键菜单显得比较干净:

image

(6)设置记住密码

密码会用明文保存在C:\users\Administrator.git-credentials这种文件中,请小心使用。

进入设置,点击右边的Git标签,可以发现,右边可以配置用户的名字与Email信息。

[credential]
Helper = store

完成后保存。

点击“编辑全局.git/config(0)”按钮,会使用记事本打开全局的配置文件,在全局配置文件中,在后面加上下面内容

2.3.2 秘钥转换

image

image

image

image

image

image

2.3.3 客户端对接私有仓库

将客户端的秘钥写入服务端:

复制git客户端生成的公钥:

image

在服务端:

  1 [root@localhost ~]# cd /etc/ssh
  2 [root@localhost ssh]# vim sshd_config
  3 注释掉下面的三个 (没有的忽略)
  4 RSAAuthentication yes
  5 PubkeyAuthentication yes
  6 AuthorizedKeysFile .ssh/authorized_keys
  7 
  8 保存并重启 sshd 服务:
  9 [root@localhost ssh]# systemctl restart sshd
 10 
 11 [root@localhost ~]# cd /home/git
 12 [root@localhost git]# mkdir .ssh
 13 [root@localhost git]# chown -R git:git .ssh/
 14 [root@localhost git]# chmod 700 .ssh
 15 [root@localhost .ssh]# touch authorized_keys
 16 [root@localhost .ssh]# chmod 600 authorized_keys
 17 [root@localhost .ssh]# chown -R git:git authorized_keys
 18 [root@localhost .ssh]# systemctl restart sshd
image

在tgit上配置:

image

image

从服务端数据拉取成功。

3. Git 实战

前面我们安装了git,并且以我们搭建的本地git仓库为中心,配置tgit客户端。接下来,重点看git的使用

3.1 Git初始化

查看版本号

  1 [root@localhost .ssh]# git --version
  2 git version 2.39.3

再配置tgit的时候,我们也发现了git的配置是层次化的,有系统文件,全局文件,用户文件,项目文件,并依次递进,后面的配置会覆盖前面的配置。

Local:当前项目有效(工作目录/.git/config)
Global 当前用户有效(用户目录/.gitconfig)
System 所有用户有效(Git目录/etc/gitconfig)

(1)告诉Git当前的用户的姓名和邮件地址,配置的用户名和邮箱地址将在版本库提交时用到。

1 [anliu@localhost ~]$ git config --global user.name "anliu" 2 [anliu@localhost ~]$ git config --global user.email anliu@163.com 3 [anliu@localhost ~]$ ll 4 总用量 0 5 [anliu@localhost ~]$ ls -a 6 . .. .bash_logout .bash_profile .bashrc .gitconfig 7 [anliu@localhost ~]$ ll 8 总用量 0 9 [anliu@localhost ~]$ cat .gitconfig 10 [user] 11 name = anliu 12 email = anliu@163.com

只在当前用户下生效。

(2)设置一些Git别名,以便于可以使用更为简洁的子命令。

  1 [root@localhost ~]# git config --system alias.st status 
  2 [root@localhost ~]# git config --system alias.ci commit
  3 [root@localhost ~]# cat /etc/gitconfig 
  4 [alias]
  5 	st = status
  6 	ci = commit
  7 [root@localhost ~]# 

这个会全局生效。

(3)给simple-java-maven-app仓库配置代理。

  1   1 [root@localhost simple-java-maven-app]# git config --local http.proxy 'http://192.168.163.111:8000'
  2   2 [root@localhost simple-java-maven-app]# git config --local https.proxy 'http://192.168.163.111:8000'
  3   3 [root@localhost .git]# pwd
  4   4 /home/gitrepo/simple-java-maven-app/.git
  5   5 [root@localhost .git]# cat config 
  6   6 [core]
  7   7 	repositoryformatversion = 0
  8   8 	filemode = true
  9   9 	bare = false
 10  10 	logallrefupdates = true
 11  11 [remote "origin"]
 12  12 	url = https://github.com/jenkins-docs/simple-java-maven-app.git
 13  13 	fetch = +refs/heads/*:refs/remotes/origin/*
 14  14 [branch "master"]
 15  15 	remote = origin
 16  16 	merge = refs/heads/master
 17  17 [http]
 18  18 	proxy = http://192.168.163.111:8000
 19  19 [https]
 20  20 	proxy = http://192.168.163.111:8000
 21 

当然这个之后对当前项目生效。

或者不用命令,直接修改配置文件,效果一样样的。

3.2 版本库创建

创建一个新的工作目录,进入该目录后,执行git init 创建版本库。

  1 [anliu@localhost ~]$  mkdir workspace
  2 [anliu@localhost ~]$ cd workspace/
  3 [anliu@localhost workspace]$ mkdir dome
  4 [anliu@localhost workspace]$  cd dome/
  5 [anliu@localhost dome]$ ls
  6 [anliu@localhost dome]$ git init
  7 提示:使用 'master' 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中
  8 提示:配置使用初始分支名,并消除这条警告,请执行:
  9 提示:
 10 提示:	git config --global init.defaultBranch <名称>
 11 提示:
 12 提示:除了 'master' 之外,通常选定的名字有 'main'、'trunk' 和 'development'。
 13 提示:可以通过以下命令重命名刚创建的分支:
 14 提示:
 15 提示:	git branch -m <name>
 16 已初始化空的 Git 仓库于 /home/anliu/workspace/dome/.git/
 17 [anliu@localhost dome]$ ls -a
 18 .  ..  .git
 19 [anliu@localhost dome]$

这个.git目录就是git版本库(又叫仓库,repository)。

.git版本库所在的目录/home/giter/workspace/demo,叫做工作区。

3.3 版本管理

clip_image0cxx02

Git 的工作就是创建和保存你的项目的快照及与之后的快照进行对比。

(1)git add

git add 命令可将该文件添加到缓存,如我们添加以下两个文件:

  1 [anliu@localhost dome]$ vim hello.py
  2 [anliu@localhost dome]$ vim README
  3 [anliu@localhost dome]$ ll
  4 总用量 8
  5 -rw-rw-r-- 1 anliu anliu 15 6月  10 22:52 hello.py
  6 -rw-rw-r-- 1 anliu anliu 24 6月  10 22:52 README
  7 [anliu@localhost dome]$ git status
  8 位于分支 master
  9 
 10 尚无提交
 11 
 12 未跟踪的文件:
 13   (使用 "git add <文件>..." 以包含要提交的内容)
 14 	README
 15 	hello.py
 16 
 17 提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
 18 [anliu@localhost dome]$ git add
 19 没有指定文件,也没有文件被添加。
 20 提示:也许您想要执行 'git add .'?
 21 提示:运行下面的命令来关闭本消息
 22 提示:"git config advice.addEmptyPathspec false"
 23 [anliu@localhost dome]$ git add -A
 24 [anliu@localhost dome]$ ll
 25 总用量 8
 26 -rw-rw-r-- 1 anliu anliu 15 6月  10 22:52 hello.py
 27 -rw-rw-r-- 1 anliu anliu 24 6月  10 22:52 README
 28 [anliu@localhost dome]$ git status
 29 位于分支 master
 30 
 31 尚无提交
 32 
 33 要提交的变更:
 34   (使用 "git rm --cached <文件>..." 以取消暂存)
 35 	新文件:   README
 36 	新文件:   hello.py
 37 
 38 [anliu@localhost dome]$ vim hello.py
 39 [anliu@localhost dome]$ git status
 40 位于分支 master
 41 
 42 尚无提交
 43 
 44 要提交的变更:
 45   (使用 "git rm --cached <文件>..." 以取消暂存)
 46 	新文件:   README
 47 	新文件:   hello.py
 48 
 49 尚未暂存以备提交的变更:
 50   (使用 "git add <文件>..." 更新要提交的内容)
 51   (使用 "git restore <文件>..." 丢弃工作区的改动)
 52 	修改:     hello.py
 53 [anliu@localhost dome]$ git restore hello.py
 54 [anliu@localhost dome]$ git status
 55 位于分支 master
 56 
 57 尚无提交
 58 
 59 要提交的变更:
 60   (使用 "git rm --cached <文件>..." 以取消暂存)
 61 	新文件:   README
 62 	新文件:   hello.py

(2)git status

git status 以查看在你上次提交之后是否有修改。

-s 参数以获得简短的结果输出。

image

(3)git diff

执行 git diff 来查看执行 git status 的结果的详细信息。

git diff 命令显示已写入缓存与已修改但尚未写入缓存的改动的区别。

尚未缓存的改动:git diff
查看已缓存的改动: git diff --cached
显示摘要而非整个 diff:git diff –stat

  1 [anliu@localhost dome]$ git status  -s
  2 A  README
  3 A  hello.py
  4 [anliu@localhost dome]$ git diff
  5 [anliu@localhost dome]$ vim hello.py
  6 [anliu@localhost dome]$ git status  -s
  7 A  README
  8 AM hello.py
  9 [anliu@localhost dome]$ git diff
 10 diff --git a/hello.py b/hello.py
 11 index c875119..3129f84 100644
 12 --- a/hello.py
 13 +++ b/hello.py
 14 @@ -1,2 +1,3 @@
 15  import os
 16  print("hellp")
 17 +print("os.path")
 18 [anliu@localhost dome]$ git diff --cached
 19 diff --git a/README b/README
 20 new file mode 100644
 21 index 0000000..30473c5
 22 --- /dev/null
 23 +++ b/README
 24 @@ -0,0 +1 @@
 25 +This is a test of dome.
 26 diff --git a/hello.py b/hello.py
 27 new file mode 100644
 28 index 0000000..c875119
 29 --- /dev/null
 30 +++ b/hello.py
 31 @@ -0,0 +1,2 @@
 32 +import os
 33 +print("hellp")
 34 [anliu@localhost dome]$ git diff --stat
 35  hello.py | 1 +
 36  1 file changed, 1 insertion(+)
 37 [anliu@localhost dome]$

(4)git commit

使用 git add 命令将想要快照的内容写入缓存区, 而执行 git commit 将缓存区内容添加到仓库中。

Git 为你的每一个提交都记录你的名字与电子邮箱地址,所以第一步需要配置用户名和邮箱地址。

  1 [anliu@localhost dome]$ git config --global user.name 'anliu'
  2 [anliu@localhost dome]$ git config --global user.email test@anliu.com
  1 [anliu@localhost dome]$ vim hello.py
  2 [anliu@localhost dome]$ git status -s
  3 A  README
  4 AM hello.py
  5 [anliu@localhost dome]$ git commit -m "v1.0"
  6 [master(根提交) 60047fd] v1.0
  7  2 files changed, 3 insertions(+)
  8  create mode 100644 README
  9  create mode 100644 hello.py
 10 [anliu@localhost dome]$ git status -s
 11  M hello.py

如果你没有设置 -m 选项,Git 会尝试为你打开一个编辑器以填写提交信息。 如果 Git 在你对它的配置中找不到相关信息,默认会打开 vim。

(5)git reset HEAD

git reset HEAD 命令用于取消已缓存的内容。

我们先改动文件 README 文件,内容如下:

  1 [anliu@localhost dome]$ git status -s
  2  M README
  3  M hello.py
  4 [anliu@localhost dome]$ git add .
  5 [anliu@localhost dome]$ git status -s
  6 M  README
  7 M  hello.py
  8 [anliu@localhost dome]$ git reset HEAD
  9 重置后取消暂存的变更:
 10 M	README
 11 M	hello.py
 12 [anliu@localhost dome]$ git status -s
 13  M README
 14  M hello.py
 15 [anliu@localhost dome]$

(6)git rm

如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 Changes not staged for commit 的提示。

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除,然后提交。可以用以下命令完成此项工作

git rm <file>

如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f

git rm -f <file>

如果把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 --cached 选项即可

git rm --cached <file>

如我们删除 hello.php文件:

$ git rm hello.php 
rm 'hello.php'
$ ls
README

不从工作区中删除文件:

$ git rm --cached README 
rm 'README'
$ ls
README

可以递归删除,即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件:

git rm –r * 

进入某个目录中,执行此语句,会删除该目录下的所有文件和子目录。

(7)git mv

git mv 命令用于移动或重命名一个文件、目录、软连接。

我们先把刚移除的 README 添加回来:

git add README 

然后对其重名:

git mv README README.md
ls
README.md


posted @ 2023-06-03 16:00  大江东流水  阅读(55)  评论(0编辑  收藏  举报