Git版本管理在实际开发应用中对代码管理是一个非常且必备的技能 无论是对于个人开发还是团队开发都是一个值得学习的管理方案

前言

Git作为一个版本管理工具 对于程序员来说应该是相当熟悉 无论是对于个人开发者还是对于团队的开发都是必不可少的工具和技能

就比如这个jekyll比博客系统也是通过Git部署到Github上的 对于代码管理国内国外都有比较好的平台和服务

当然最为广泛肯定就是Github了 国内的话Coding的用户也是很多的 无论是对于哪个平台 满足我们的需求的就是最好的

Git安装配置

Git的安装的话其实网上找到自己的环境 下载之后安装就行了

1.基本配置
安装完成后我们需要去进行简单的配置 在终端执行

$ git config

我们可以看到下面的几个flag

  • --global
  • --system
  • --local

其实这三个也就是对应着3个不同的层级吧 对于用户,系统,具体项目

当然我们在自己的开发环境中当然是配置--global`主要就是对我们当然的用户而言 是一个全局性的配置

接着我们配置一下我们的user.nameuser.email这个我们就用我们Github账号的用户名和邮箱

$ git config --global user.name "JellyBean"

这里的用户名填写自己的用户名就行了

接着就是配置user.email

$ git config --global user.email = "gehuachun@outlook.coom"

这里还是填写你自己邮箱账户就可以了

你也可以去查看自己的用户名和邮箱

$ git config --global user.name

这个时候应该就是你之前配置的用户名了

当然其实我们所配置的信息 你也可以直接去Home目录下查看(Windows环境也是一样 因为我们是配置的是global)

$ cat ~/.gitconfig

这个时候你就可以看到刚才你所配置的具体的信息了

这个配置文件里面就是对git的具体的配置 其实对于Git的配置还有很多 具体的等遇到什么样的需求

如果说是对每一个项目的配置 我们在进入项目中执行

$ git init

我们就可以在生成的**.git**目录下的config里面看到对于这个项目的git的具体配置

Git的基本管理流程

在我们开发一个项目时 我们可以在项目里

$ git init

初始化项目的git管理 这样就会在项目里生成对应的**.git**目录 而里面就是具体的配置

在一开始我们可以在Github上新建一个项目仓库 然后我们就可以进行之后的代码上传部署

而在上传之前 我们得明白Git的工作流程

首先我们并不是一次性就提交我们的代码 这边其实可以分成三块 一个就是我们工作的项目块 也就是存放我们编写的代码

在中间会有一个类似缓存区这样的一个区域块 最后才是最后提交的一个HEAD区域 这里就是你最后提交的结果 只有在这个里面才能提交到远程仓库中

开始时我们可以去创建一个文件

$ echo "<?php phpinfo();" >> index.php

这里我们生成了一个index.php的文件
我们去查看一下git状态

$ git status

我们就可以看到git会提示我们有一个文件需要进行跟踪 因为我们还没有加入到缓存区

所以开始我们可以去将代码加入到缓存区

$ git add .

在执行完毕之后我们再去执行git status 就看到已经没有之前的提示 说明git已经跟踪我们刚才所添加的index.php文件了

这里的git add .是将目录下的所有文件全都加入到缓冲区 .起到一个通配符的作用 当然也有* 例如我们需要将src目录下的php文件写入缓存区

$ git add src/*.php

接下来就是写入到HEAD区域块中

$ git commit -m "first commit"

这个也就可以将文件放入到HEAD区域块中 之后我们才可以进行文件上传提交
在提交之前我们需要去加入我们的远程仓库的 这个在创建远程仓库的时候就可以看到

所以这个时候我们就可以提交文件

$ git push origin master

如果不想要每次提交都需要输入密码的话 可以去生成一个ssh key这个对于GithubCoding都是一样的

包括我们在自己的服务器上去部署代码的时候我们也是可以去在服务器里生成对应的key这样加入到Github后我们就可以直接提交而不用输入密码了

其实大概的基本流程就是这样

.gitignore说明

在创建远程仓库时会有这个选择 当然对于每个项目的创建这个.gitignore是不同的 我们自己也可以进行相应的配置

他的作用明义上就是忽略掉不必要的文件 这里的不必要并不是真的不必要

这些文件就是包含一些敏感信息数据的文件 比如Laravel中的.env文件 因为里面包含了很多开发者的私密数据 这些肯定不会暴露给别的人

还有的就是我们可以通过npm install去下载的包文件 以及通过gulp去生成的文件 因为这些文件我们完全可以在部署的时候去生成

不然的话整个项目就太繁重了 上传的效率也不是很高 而且显得很没有必要

Git分支的应用

首先提出这样的一个场景:

我们在项目里面已经上线了部分的功能 我们正在开发其他的功能板块 这个时候你发现自己原先的项目里面出现了一个很明显的Bug

如果这个时候我们去修复这个Bug我们正在开发的功能板块还没有完成所以这个时候我们是不能推送我们的代码的

这个时候的矛盾就是我们需要去修复之前项目里的Bug但是我们又不好把半成品的功能板块推送上去

所以这个时候我们在开发我们新的功能板块时 需要去创建新的分支

$ git branch new-branch

这里我们就创建了一个新的分支new-branch 我们可以通过执行命令查看

$ git branch

这样就会罗列出当前项目里面所有的分支了
我们看到的matser就是当前分支 因为它前面会有一个*号

创建好了分支 我们可以进入我们的分支

$ git checkout new-branch

这样我们就可以进入到刚生成的分支里了 当然我们在创分支时 可以创建并进入该分支

$ git checkout -b new-branch

这个其实就是上面两个步骤的结合

其实这里的分支可以这么理解 就是你上线了项目的部分功能 已经投入使用

那么在线下 你需要去添加新的功能板块时就去创建一个分支 在这个新的分支里去实现功能代码逻辑

一旦之前已经上线的项目出现了Bug那么你s首先在新的分支里去提交增加的文件 然后切换到master分支去修复Bug而不会影响到新的分支
因为新的分支里正在实现新的功能板块还没有完成 并且已经commit

修复完Bug后你就可以去提交以完成当前项目的Bug修复这个不会推送新分支里的代码
之后你完成了新的功能再将新的分支合并master分支 这样再一起推送到远程仓库

这样就不会出现问题了 即使之前的项目出现Bug我们也可以在不影响正在开发的新的功能板块

我们可以去在命令行执行

$ git log

我们会发现只有master分支下的提交信息 而不会有新分支下的提交信息

在完成新的功能板块 切换到mater分支后我们就可以去合并我们新的分支

$ git merge new-branch

在完成新的功能后如果没有什么需要修复更改的我们就可以去删除这个分支

$ git branch -d new-branch

Git合并冲突

我们在合并其他分支时很有可能会同时修改了同一段代码 这样两个分支的代码片段不一致 这样就会产生合并冲突

当我们去合并新分支时

$ git merge new-branch

会给出一个冲突提示 我们可以查看一下冲突的具体情况 如发生冲突在test.txt文件中

$ git diff test.txt

我们就可以看到冲突的具体的情况 而我们需要去手动解决这些冲突 因为两个分支的片段取舍完全取决于我们

修改完冲突之后 我们再去提交推送就可以了

顺便说一下的就是git reset --soft xxxgit reset --hard xxx的区别

xxx是git log显示的每条提交记录的hash值
其中soft和hard的区别就是一个会撤销提交记录 而另一个不仅会撤销提交记录代码数据也会退回到之前的时间点

git stash解决修复Bug

还是这个前提 当你正在专注于功能的开发时 有人突然告诉你要你去修改上线的Bug而这个Bug可能和你正在开发的其他模块相关

Oh No~ 又是这个问题 好吧git stash就可以将我们目前的工作区域暂存起来 这样我们就可以去做其他事 比如去修复下蛋疼的Bug

这个我们还是去创建一个新的分支去开发新的功能模块

这个和我们之前有所不同的是 如果新的分支的内容没有commit 他是会影响到master分支的

我们可以试着在新的分支里去写一些新的代码块 然后我们切换到matser分支 这个时候我们git status去看一下git当前的状态

我们会发现 我们是可以看到在新的分支里面的文件还没有添加到缓存区这样的信息的

所以我们还是切换到新的分支 去执行

$ git stash

这个时候我们可以在新的分支里去查看一下当前的状态

$ git status

我们会发现这里是没有需要commit的内容的 我们再回到mater分支 我们再次执行

$ git status

我们发现也看不到需要提交的内容 这个看起来是不是正是我们所需要的结果

这个时候我们就可以在matser分支里做我们想做的事 比如去修复一下需要修改的Bug

修复完后 我们还得去新的分支继续我们的工作 我们需要去拿回我们之前stash的内容

这个理解起来大概就是你正在办公桌忙着今天的工作 突然经理过来有给你一个新的紧急任务 没办法 这个任务十分紧急

你还是得马上去处理 所以我们只得把手上的工作先放到一边 先把经理交给我们的事先解决 解决完成之后

好嘛 今天的工作还没做完 我们又得重新拿起今天的工作任务再拿过来开始做

当然在拿回我们今天的工作任务时 会有和git stash相反的操作 就是git stash applygit stash pop

这两者之间的区别就是我们可以通过执行

$ git stash list

当然如果是git stash apply 我们是可以看到stash的一条记录 这条记录包含了一个stash id标记着每条stash记录

但是如果是执行git stash pop的话不仅会拿回我们stash的数据 还会将这条stash记录删除

这个有点像数据结构里面的栈的toppop的区别 一个是只是返回数据 一个不仅返回数据而且会删除掉栈顶元素
哈哈 这样理解起来还是可以接受的吧 😆

当然如果你只是执行git stash apply后想删除掉那条stash记录的话 我们去drop掉那条记录

$ git stash drop

所以这个时候你去执行git stash list是看不到之前的那条记录的

git rebase的应用

首先我们在master分支里去git add提交下信息然后去生成一个新的分支

$ git checkout -b new-branch

我们在切换到新的分支后 我们去执行

$ git log

这样的话我们是可以看到在master上的提交信息的 如果这个时候我们在新的分支上修改和增加代码

我们去提交后 我们再次git log这样一来我们会多出一条信息

切换到master分支 我们像往常一样merge新的分支 再去执行git log

我们会看到会多出一条merge的信息 这实际上是因为我们在中途新增加了一条新的分支 所以我们才会有这么一条merge信息

往往团队成员多的时候 我们想整个开发过程就像在一条历史线上 每一个commit都在一个时间轴上 这样也可以保证了提交记录的整洁

git 发布版本

我们正开发第三方插件供别人使用时 我们可能过程在别人提出的issue后对扩展包进行改进或者功能的增加 那么我们会针对过程发布应用
包的版本也就是tag

我们在执行git push后将自己的代码提交到仓库 这个时候我们的代码已经可以使用 难么我们可以就可以为现在的代码提供一个版本也就是打上一个标签

push完成之后 我们再去执行:

$ git tag 1.0 -a

执行完毕后会我们就可以在vim里去写我们这次的commit message(发布说明) 添加完毕之后再去执行:

$ git push --tags

这样一来我们就把我们这次的版本推送上去了 也就是1.0的版本 后期再有改善的话还是这样 这样就很清楚这个扩展包的还是生命流程

如果需要删除一个tag的话 我们需要将本地和远程的tag都删除掉
首先我们可以查看一下本地当前分支的tag情况

$ git tag

接着如果我们需要删除其中的一个1.0的tag时

$ git tag -d 1.0

删除远程的tag的话(可以理解为推送一个空的tag):

$  git push origin --delete tag 1.0

这样我们就删除了tag1.0的这个分支了

必要时也可以去选择适应哪一个版本的包