Git 一篇文章搞懂git (万字长文)

索引

  • 一. Git初识
      • 1.提出问题
      • 2.什么是版本控制器
      • 3.git安装
  • 二. git本地仓库基本操作
      • 1.Git本地仓库相关命令
      • 2.认识工作区,暂存区,版本库
      • 3.第一次Git追踪管理文件
      • 4.**有关于打印提交日志的命令**
      • 5.验证.git文件的指针指向
      • 6.Git管理的再理解——修改
      • 7.版本回退
      • 8.撤销修改
          • 1.情况一 对于工作区的代码,还没有add
          • 2.情况二:已经add,但没有commit
          • 3.情况三: 已经add 和commit
          • 4.删除版本库中已经提交的文件
      • 9.分支管理
          • 1.理解分支
          • 2.创建分支
          • 3.合并分支
          • 4.删除分支
          • 5.合并冲突
          • 6.合并分支策略
            • 1.ff模式
            • 1.非ff模式
          • 7.分支策略
            • 1.bug分支
            • 2.删除临时分支
  • 三.Git远程操作
      • 1.新建远程仓库
      • 2.克隆仓库
          • 1.使用HTTPS克隆
          • 1.使用SSH协议克隆
      • 3.向本地仓库的修改推送到远程仓库
      • 4.拉取远程仓库
      • 5.配置忽略文件
      • 6.标签管理
          • 1.创建标签
          • 2.推送标签
          • 3.展示标签信息
          • 4.删除标签

Git 一篇文章搞懂git (万字长文)_第1张图片

一. Git初识

1.提出问题

假设我们设计一个文档,以提交的次数记录版本号
“文档V1”
“文档V2”
“文档V3”

“文档V8”
随着文档的修改,有可能客户需要的反而是V2甚至是V1,因此,随着版本数量不断增多,无法记得版本与版本之间修改了什么,所以产生了 版本控制器

2.什么是版本控制器

所谓的版本控制器,就是可以让我们知道每一个文件的历史,以及它的发展过程的系统。
记录工程的每一次改动和版本迭代的一个管理系统,也便于多人协同。
目前最主流的版本控制器是 Git,Git可以控制电脑上所有格式的文件,例如excel,dwg等,对于我们而言,Git最重要的就是管理软件开发项目中的源码文件。

注意:
所有版本控制系统,包括Git,只能跟踪文本文件的改动,eg:txt文件,网页,所有的程序代码等,版本控制系统可以告诉你每次的改动,比如在第3行家里一个单词“hello”,或者在第7行删了一个单词“Linux”,但是图片视频等二进制文件,虽然也能由版本控制系统管理,但是无法跟踪文件的变化,只能判断出文件是否发生了变化,具体发生的改变是无法知道的。

3.git安装

我的平台是centos 7.9 安装git

sudo yum -y install git

二. git本地仓库基本操作

查看git安装的版本

git --version

1.Git本地仓库相关命令

仓库是进行版本控制的一个文件目录。

创建Git本地仓库的命令 ,该命令需要再文件目录下执行

git init

Git 一篇文章搞懂git (万字长文)_第2张图片

.git隐藏目录是Git跟踪仓库管理的,不要手动修改这个目录里面的文件,不然就全乱了

.git文件的细节如下
在这里插入图片描述
配置用户名和e-mail地址

git config user.name “zhang-juntong”
git config user.email “[email protected]
此时配置的时候该机器下的该Git仓库
如果需要配置该机器下的所有Git仓库的用户名和e-mail
git config --global user.name “zhang-juntong”
git config --global user.email “[email protected]

注意:执行上述命令都需要在仓库里

查看配置命令

git config -l

Git 一篇文章搞懂git (万字长文)_第3张图片
删除对应的配置命令

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

2.认识工作区,暂存区,版本库

如果在当前目录下再创建一个文件text.txt .然后我们能直接用Git来管理该文件吗?
在这里插入图片描述
不能!

工作区: 是在电脑上写的代码或者文件的目录
暂存区: 也叫做stage或index,一般放在.git 目录下的index文件(.git/index)中
版本库: 也叫repository ,工作区有一个影藏目录.git ,他不算工作区,而是Git的版本库。这个版本库中的所有文件都可以被Git管理,每个文件的修改删除,Git都能追踪,同时也可以便于在将来某个时刻还原。

下面这个图展示了工作区,暂存区和版本库之间的关系
Git 一篇文章搞懂git (万字长文)_第4张图片
git add 将文件从工作区提交到暂存区
git commit 将文件从暂存区提交到版本区
Git 一篇文章搞懂git (万字长文)_第5张图片
Git 一篇文章搞懂git (万字长文)_第6张图片

3.第一次Git追踪管理文件

Git 一篇文章搞懂git (万字长文)_第7张图片
也可以多次add 然后一次性commit

4.有关于打印提交日志的命令

git log
Git 一篇文章搞懂git (万字长文)_第8张图片
上述的commit ID 是经过哈希出来的值,可以定位到每次的提交,还有谁提交的和提交的细节

git log --pretty=oneline打印出一行漂亮的日志
在这里插入图片描述

5.验证.git文件的指针指向

Git 一篇文章搞懂git (万字长文)_第9张图片

6.Git管理的再理解——修改

Git比其他版本控制系统设计的优秀实际上因为Git跟踪并管理的是修改而不是文件内容本身

Git 一篇文章搞懂git (万字长文)_第10张图片

7.版本回退

如果有一天你发现之前的工作出现了很大的问题,需要在某个特定历史版本重新开始,这个时候就需要版本回退的功能。
命令

git reset [–soft | --mixed | --hard ] [HEAD]
--mixed 为默认选项,使用时不带参数默认为该选项 工作区不变,暂存区和版本库回退到某个指定版本
--soft 参数 对于工作区和暂存区不变,只将版本库回退到某个指定版本
--hard 工作区,暂存区和版本库都回退到某个版本
HEAD说明 可直接写成commit ID 表示指定退回版本
HEAD 表示当前版本(这个当前版本指的是版本库的版本,因为工作区和暂存区有可能和版本库中是不一样的)
HEAD^ 上一个版本
HEAD^^ 上上一个版本
依次类推.......
还可以用~数字表示:
HEAD~0 表示当前版本
HEAD~1 表示上一个版本
依次类推........

需要注意的是,hard参数慎用,因为如果有新功能的代码正在工作区,用–hard之后还未add的代码就找不到了

Git 一篇文章搞懂git (万字长文)_第11张图片
验证 --soft
Git 一篇文章搞懂git (万字长文)_第12张图片
验证 --mixed
Git 一篇文章搞懂git (万字长文)_第13张图片
--hard
Git 一篇文章搞懂git (万字长文)_第14张图片
上述用git log 查看时发现没有了最后修改的版本commit id 了,这个时候还可以用

git reflog 记录每一条提交命令
Git 一篇文章搞懂git (万字长文)_第15张图片

8.撤销修改

如果我们在工作区中写了很长时间的代码。越写越写不下去,觉得自己写的很垃圾,想要恢复上一个版本,有下列几种情况
撤销的目的是为了不影响远程仓库的代码,将本地仓库的代码推送到远程仓库需要push操作,所以下列撤销的条件都建立在没有push的前提下

1.情况一 对于工作区的代码,还没有add

可以直接考虑人工删除,但是不推荐,因为有时候开发了两三天,手动人工删除,有可能会导致出现新的语法错误。

git checkout – filename
Git 一篇文章搞懂git (万字长文)_第16张图片

2.情况二:已经add,但没有commit

git resest

上述的git reset默认参数是--mixed 将暂存区的内容退回为指定的版本,此时我们先将暂存区的内容回退,再用上面的checkout 命令即可将工作区也回退
Git 一篇文章搞懂git (万字长文)_第17张图片

3.情况三: 已经add 和commit

跟上述一样

git reset --hard HEAD^

即可,不过多赘述

4.删除版本库中已经提交的文件

可以现在工作区中删除,然后再add 和 commit 即可
也可以先git rm filename 再 commit 其中 git rm filename 的作用是将文件从暂存区和工作区中删除
Git 一篇文章搞懂git (万字长文)_第18张图片

9.分支管理

1.理解分支

什么是分支?
假设我有一个分身,十天之内,一个学习数据结构一个学习操作系统,那么十天之后,我算是既学会了数据结构又学会了操作系统。
在版本回退中,每次提交,Git都会把他们串成一条时间线,这条时间线就可以理解成一个分支,截止到目前为止,只有一条时间线,在Git里,这个分支叫做主分支即master 分支。
HEAD 严格来说不是指向提交的,而是指向master, master才是指向提交的,所以HEAD指向的就是当前分支
Git 一篇文章搞懂git (万字长文)_第19张图片
每提交一次,master分支都会向前移一步,这样,随着你不断提交,master分支的线也越来越长,而HEAD只要一直指向master分支即可指向当前分支
在这里插入图片描述

2.创建分支

查看当前本地所有分支

git branch

新建分支

git branch dev
Git 一篇文章搞懂git (万字长文)_第20张图片

3.合并分支

Git 一篇文章搞懂git (万字长文)_第21张图片
Git 一篇文章搞懂git (万字长文)_第22张图片

4.删除分支

合并完成后,分支对于我们来说就没有用了,因此dev分支就可以被删除掉了,注意如果当前正处于某分支下就不能删除当前分支。
git branch -d dev
Git 一篇文章搞懂git (万字长文)_第23张图片
此时的状态如下所示。
Git 一篇文章搞懂git (万字长文)_第24张图片
由于分支的创建,合并和删除非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

5.合并冲突

实际合并分支的时候,并不是想合并就合并的,有时候可 能会有代码冲突。

Git 一篇文章搞懂git (万字长文)_第25张图片

6.合并分支策略

上述的合并第一次合并没有冲突,第二次合并有冲突,两次合并分别对应了git的两种合并模式。分别时fast forward模式和非fast forward模式

1.ff模式

Git 一篇文章搞懂git (万字长文)_第26张图片
在这种Fast forward模式下,删除分支后,查看分支历史时,会丢掉分支信息,看不出来是最新提交是merge进来的还是正常提交的

1.非ff模式

上述合并冲突的状态如下所示
Git 一篇文章搞懂git (万字长文)_第27张图片
此时在删除分支之后是可以查看分支信息的,因为分支dev指向的并不是合并后的最新提交,而是指向其分支的最新提交
合并的时候增加这个--no--ff
Git 一篇文章搞懂git (万字长文)_第28张图片
该合并其实跟上述例子中的ff模式是一样的,都是没有冲突的,但是此时却可以通过git log 看出历史分支信息

7.分支策略

实际开发中,我们要遵循一下结果基本原则进行分支管理

首先:maste分支应该是稳定的,仅用来发布新版本,不能直接在master上修改代码,因此,修改的部分要在dev上,也就是说,dev分支是不稳定的,例如发布1.1版本,将dev分支上的代码合并到master上,然后在master分支上发布1.0版本,而我们开发人员就可以在dev分支上写代码了。因此,团队合作看起来就像下面一样的

Git 一篇文章搞懂git (万字长文)_第29张图片
下面列举几个具体的分支管理

1.bug分支

场景描述
假设我们正在dev分支上开发,开发到一半,突然master分支上有bug,此时我们不能直接在master分支上进行代码的修改,避免产生更大的bug,因此在Git中,每个bug都得有一个新的临时分支来进行修复,修复后合并再删除临时分支。
Git 一篇文章搞懂git (万字长文)_第30张图片

此时master已经合并了修改后的分支,dev指向的是开发分支。此时合并masterdev时,一定会有合并冲突,由于master主分支上放的是稳定版本的分支,所以此时我们要切换到dev开发分支然后并合并master分支,然后再切换回master分支再合并,此时就不会有合并冲突了。
Git 一篇文章搞懂git (万字长文)_第31张图片
Git 一篇文章搞懂git (万字长文)_第32张图片
合并dev状态图如下所示
Git 一篇文章搞懂git (万字长文)_第33张图片

2.删除临时分支

之前提到过的删除分支是
git branch -d xxx
但这个命令只能删除已经合并的分支,并不能删除已经提交但是未被master合并过的分支

场景: 产品经理需要添加一个功能,此时我们在master基础上创建一个新分支 dev2,开发了三天之后就被产品经理叫停了,此时dev2上的分支都被add 和 commit了 ,但是未合并,此时我们要删除分支的话只能用git branch -D xxx

场景模拟如下
Git 一篇文章搞懂git (万字长文)_第34张图片

三.Git远程操作

上述所说的所有内容(工作区,暂存区,版本库等等),都是在本地!也就是在自己的计算机上,而我们的Git是一个分布式版本控制系统!,什么意思?
简单理解为,我们每个人的电脑都是一个完整的版本库,这样在工作的时候就不需要联网了,因为版本库就是在自己的电脑上。而当一个人电脑坏掉了,可以从另外一个人那直接复制即可,在实际开发中,通常由一台充当中央服务器的电脑,这个服务器的作用仅仅是用来方便大家交换大家的修改,我们可以将新开发的功能推送(push)到这个中央服务器,同样也可以从中央服务器中pull(拉取)代码。
由于gitub是国外的网站,速度很慢,我用码云来托管

1.新建远程仓库

Git 一篇文章搞懂git (万字长文)_第35张图片
Git 一篇文章搞懂git (万字长文)_第36张图片
Git 一篇文章搞懂git (万字长文)_第37张图片

Git 一篇文章搞懂git (万字长文)_第38张图片

2.克隆仓库

1.使用HTTPS克隆

git clone XXXXXXX链接
Git 一篇文章搞懂git (万字长文)_第39张图片
需要注意的时候克隆远程仓库的时候不能在任意一个本地仓库执行,也就是说不能在上述的gitcode仓库中执行
进入远程仓库,观察一下远程仓库发现和码云上的仓库完全一致
Git 一篇文章搞懂git (万字长文)_第40张图片
状态图如下所示
Git 一篇文章搞懂git (万字长文)_第41张图片
查看远程仓库
git remote
查看详细信息git remote -v
Git 一篇文章搞懂git (万字长文)_第42张图片

1.使用SSH协议克隆

1.将本地服务器的公钥放到Git服务器上进行管理

Git 一篇文章搞懂git (万字长文)_第43张图片

此时再Git上公钥数为0

Git 一篇文章搞懂git (万字长文)_第44张图片

上述错误中由于我们没有添加公钥到远端仓库中,服务器拒接了我们的clone连接,需要我们进行如下设置:
在⽤⼾主⽬录下,看看有没有.ssh⽬录,如果有,再看看这个⽬录下有没有
id_rsa 和 id_rsa.pub 这两个⽂件,如果已经有了,可直接跳到下⼀步。如果没有,需要创建
SSH Key:
创建好了公钥再将公钥添加到Git服务器上,再克隆链接即可

Git 一篇文章搞懂git (万字长文)_第45张图片

3.向本地仓库的修改推送到远程仓库

上述的操作add是将工作区的文件转移到暂存区,而commit是将暂存区的内容转移到版本库,操作完后都是在本地仓库中的,将本地版本库中的内容转移到远程仓库需要push,注意的是,本地仓库推送到远程仓库是分支与分支的联系,将本地分支上的某个内容推送到远程分支上
推送之前,需要注意的是我们本地Git配置的用户名和邮箱和gitee配置的一致,如何配置,我在前面已经赘述过了。

下面是我的配置,和我自身gitee的仓库是一致的

git config -l
user.email=2016982259@qq.com
user.name=zhang-juntong
push.default=matching
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=git@gitee.com:zhang-juntong/git-learning.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master

git push <远程主机名> <本地分支名>:<远程分支名>
#如果本地分支名和远程分支名相同,则可以省略冒号:
git push <远程主机名> <本地分支名>

必须先add commit 然后才能push

git add .
[zjt@VM-12-12-centos git-learning]$ git commit -m"测试能否推送到远程仓库"
[master 88fb68c] 测试能否推送到远程仓库
 1 file changed, 6 insertions(+)
 create mode 100644 test.cc
[zjt@VM-12-12-centos git-learning]$ git push origin master 
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 390 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.4]
To git@gitee.com:zhang-juntong/git-learning.git
   5715613..88fb68c  master -> master

Git 一篇文章搞懂git (万字长文)_第46张图片
推送成功,由于我们使用的是SSH协议,是不用每一次推送都输入密码的,方便了我们推送操作,如果我们用的是HTTPS协议,必须每次输入用户名和密码,很麻烦。
这里需要提一下,我们克隆仓库的时候,本地的master 和远程的master是默认直接连接的

[zjt@VM-12-12-centos git-learning]$ git remote -v
origin	git@gitee.com:zhang-juntong/git-learning.git (fetch)
origin	git@gitee.com:zhang-juntong/git-learning.git (push)

此时表示有推送和拉取权限。

4.拉取远程仓库

多人协同开发时,有时远程仓库的版本比本地仓库版本新,此时需要我们拉取远程仓库。
我先直接在gitee仓库上修改,然后再拉取.

git pull <远程主机名> <远程分支名>:<本地分支名>
#如果远程分支是与当前分支合并,则冒号后面的部分可以省略
git pull <远程主机名><远程分支名>

Git 一篇文章搞懂git (万字长文)_第47张图片

5.配置忽略文件

在日常开发中,我们有些文件不想或者不应该提交到远端,比如保存了数据库密码的配置文件,此时我们可以在Git工作区的目录下创建一个特殊的.gitignore文件,然后将需要忽略的文件名填进去,Git就会忽略这些文件

下面是我.gitignore初步内容

#可以直接些文件名 也可以直接*.so 表示忽略所有以.so结尾的文件
*.so
*.ini

先将.gitignore文件提交之后,再创建两个文件,分别是.so 和 .txt文件,发现能提交的此时只有.txt文件
Git 一篇文章搞懂git (万字长文)_第48张图片
当然也可以强制提交被忽略的文件

git add -f a.so 强制提交

Git 一篇文章搞懂git (万字长文)_第49张图片
Git 一篇文章搞懂git (万字长文)_第50张图片

也可以在.gitignore文件中操作
Git 一篇文章搞懂git (万字长文)_第51张图片
实际开发中可能文件太多,因此我们需要知道查询文件是如何被忽略的

[zjt@VM-12-12-centos git-learning]$ git check-ignore -v d.so
.gitignore:2:*.so	d.so

6.标签管理

标签tag是对某次commit的一个标识,相当于起了一个别名,例如,在项目发布某个版本的时候,针对最后一次commit起一个v1.0这样的表示来标识里程碑的意义。相较于难记住的commit id ,tag很好的解决了这个问题,因为其一定给人一个让人记住且有意义的名字,当我们需要回退到某个重要版本时,直接使用标签就能很快定位到。

1.创建标签

创建标签 git tag [name]
查看标签 git tag
默认标签是打在最新提交的commit上的,如果要指定commit ,我们需要找到历史的commit id 然后接在tag 后面

[zjt@VM-12-12-centos git-learning]$ git tag v1.0
[zjt@VM-12-12-centos git-learning]$ git tag
v1.0
[zjt@VM-12-12-centos git-learning]$ cat .git/refs/tags/v1.0 
009df55b9a9811e909f6da7e313d0c3b5b61378c

Git 一篇文章搞懂git (万字长文)_第52张图片
发现此时标签指向的commit就是我们最新的commit

也可以对某个提交打上标签,不加commit id 默认对最新的提交打标签

[zjt@VM-12-12-centos git-learning]$ git tag v0.1 cacaf126803ca548bdfacdf697cb76229b062a75
[zjt@VM-12-12-centos git-learning]$ git tag
v0.1
v1.0

也可以对创建的标签添加备注信息,同理,后面不加commit id默认就是最新提交

[zjt@VM-12-12-centos git-learning]$ git tag -a v0.5 -m"测试标签备注 v0.5" 88fb68c
2.推送标签

推送标签

推送部分标签 git push origin v1.0
推送所有标签 git push origin --tags

[zjt@VM-12-12-centos git-learning]$ git push origin v1.0 v0.1  
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.4]
To git@gitee.com:zhang-juntong/git-learning.git
 * [new tag]         v1.0 -> v1.0
 * [new tag]         v0.1 -> v0.1

Git 一篇文章搞懂git (万字长文)_第53张图片

3.展示标签信息

git show [tag_name]

Git 一篇文章搞懂git (万字长文)_第54张图片

4.删除标签

Git 一篇文章搞懂git (万字长文)_第55张图片
Git 一篇文章搞懂git (万字长文)_第56张图片
可以看到是删除成功了

你可能感兴趣的:(git,github)