赞
踩
实际上git使用越来越普及了,当然如果你还是把它当作svn来使用,或者就是只是通过一些图形化工具上几个按钮点一点就失去很多git自身有魅力的地方。
首先对照svn或者其他上一代的版本管理工具,我们修改文件不再有“这个文件要不要lock的问题”,要知道之前曾经工作一个单位,通过版本管理工具修改文件不仅要把文件锁上不让别人修改之外,还要把自己的电话信息放进去,这样别人要改的时候,就会打电话给你“放开那个文件”。
git强调一个“repository”仓库的概念,别小瞧这个概念,你本地拉下代码的同时你也会创建一个本地仓库,这个仓库和大家共用的那个本质上区别不大。也就是代码服务器有的你都有,这也就是分布式的好处,你不在围绕服务器上的那个代码仓库唯命是从,你甚至可以和小伙伴的仓库进行合作。
代码合并和冲突解决:
版本冲突这个你用什么样的版本工具都会遇到,解决的方式也是各种各样。但是这里有一个中心思想就是,就是要保证线上的master稳定版没有问题,不要“带病上岗”。
一. 阿里云上的云效做法:
做一个需求来一条新分支出来,然后在上边做需求。这时候做完后提交,实际上会云效再拉一条新的分支,你要和别人的分支合并到这个分支上,然后发不到不同环境,如果是线上环境的就会把这个给分支合并到master分支(当然前提是你已经在测试环境分支的分支上都通过测试,或者说除了线上环境以外都测试过了没问题才可以发到线上。)。如何出现冲突基本是在测试环境,这时候发布不成功,云效会提醒你怎么做
大概的步骤:
(1)切换分支到合并的分支
(2)git status看一下什么问题,一般来说都是文件冲突
(3)处理冲突文件
(4)提交
这里有个比较坑爹的就是,在云效发布的过程中,解决冲突后最好是去发布界面点击一下“解决冲突”,官方的说法你如果重新部署或者发布可能会出现循环报错,就是你以为改好了,但是你发布还是爆出原来的那个问题,然后你去修改,不断的往复。
二. 还有一个就是我的一个同事的做法也挺有意思的:
(从这个同事身上我学到了不少git的相关知识,文章最后一部分我还会把他的总结部分贴出来分享一下)
他的做法就是自己本地两个仓库,一个是自己开发的,一个是对应master(当然这个master对应的是服务器master一致的),提交文件的时候,把开发的合并到另一个仓库上,如果能通过说明没啥问题,然后提交到开发版本分支,然后开发版本分支再合并master分支。
中间出现冲突一可能是在本地两个仓库(开发仓库,稳定版本仓库),这个其实就是告诉你那些文件要注意要解决,本地通不过,线上服务器也不能通过
还有一个就是合并开发分支的时候,记住不能直接合并到maste分支(即使我们用旧的版本管理工具,也要求每个环境不同的分支,一步一步的合并上去,开发分支----测试环境分支---准线上环境---线上环境)
git常见命令:
实际上clone代码下来,本地git设置这些看一些git文档基本是第一页第二页就有的,这里会挑一些,不是很常用,但是遇到问题在终端查看解决问题都会用上比较有用的
git状态
git status
查看工作目录状态,这是最频繁的使用的一个命令,到底有什么问题,为什么切换不了分支?到底是什么文件有冲突?一查便知,以下是我这边测试某个目录的的文件情况
git 分支操作
查看当前分支:
git branch
查看全部分支:
git branch -a
(这个和linux命令很像 a == all ,当然Linux的la 实际上是list -all 的别名而已)
切换分支:git switch 分支名 (我们经常会遇到origin/master这种,你要知道这是啥意思,origin你可以理解为主机名,master才是分支的名字,所以切换的时候要注意 switch后面接分支名)
还要注意一点有的时候切换分支时候不能成功切换的提示,又一次我没注意发现自己已经在切换的分支上,这就很囧,查看提示消息很重要的。
git比较差异
不使用可视化工具比较差异,使用命令行来查看差异也是非常的不错,甚至效果会更佳,没有那些“花里胡哨”的东西,而且git的提示也是非常好也非常的详细,有的可视化工具只是单单报个错,要不然是不明显要不然是不突出不详细,命令行相比这些工具反而还有自己的优势。
git diff filename
工作目录和暂存区比较差异(工作目录好理解,就是你现在修改的代码所在目录,暂存区这个概念我要)
git diff branch filename
这里分支对比,也是从工作目录来和别的分支做对比
git diff --cached <commit> <filename>
这里是暂存区和git仓库比较,这里的commit不是“commit”这个词,对应的是commit的版本号,版本号 版本号(重要事情说三遍,不要填commit这个单词,也不要不知道该填什么),查看下面的git log来命令部分来获取版本号(实际上版本号很长,你实际上给一部分他自己也会去匹配对应的commit)
git diff <commit> <filename>
工作目录和git仓库对比
再来个例子
git diff 815a7b05905315d879d pages/hire/hire/hire.js
git diff <commit> <commit>
这里是git仓库的两次提交的差异比较,同理<commit>对应的是版本号
暂存区:
(这里暂存区概念搞懂了,可以帮助你理解清楚不少东西,甚至对git的结构,操作流程有进一步的认识)
这里还有一个概念就是:工作区(工作目录) 暂存区 分支(origin/master origin/dev等),里面的暂存区是个什么东西?
注意一下我红色标出的部分,这个很多文档会谈到暂存取,但是标出来的太少,我就直接自己截了个图自己给标出来。
我们创建,或者修改文件,都会通过add操作添加进去,那添加到哪里呢?实际上添加到的地方就是版本库里面的暂存区stage里面,commit之后会清空暂存区,然后把暂存区的文件送到版本库里面
git日志
关于日志其实也很重要,你看一下提交了啥,具体对比的话就是SourceTree上的history,没有日志你怎么知道具体都提交了啥。
git 查看历史版本
git log
这个是查看前X个版本的日志
git log -x
同理,某个文件前X个提交的日志
git log -x filename
这一条是针对第一条,git log现实的东西太多,做了简化。只显示查看历史所有版本信息,只包含版本号和记录描述
git log --pretty=oneline
合并到分支
以合并到master为例子
第一步你要把你当前分支都add进暂存区,然后暂存区commit提交到分支,清空暂存区。
git add .
git commit -m ‘dev'
git push -u origin dev
第二部切换要合并的分支,比如说我们切换到master分支,然后一定要pull一下最新的代码,我专门把这个步骤加粗一下:
git checkout master
git pull origin master
第三步合并代码:
git merge dev
第四步:查看git状态,没有问题直接合并
git status
这一步查看状态就是看看又没有冲突,为提交,暂存区还有东西等问题,没有问题就可以直接解决了
git push origin master
git add 和 git restore的区别与使用
这俩命令你git status经常会遇到,为什么会提示这两个问题,就是你工作目录文件改变了,git问你“你是否要保存修改还是放弃修改?”,实际上这两个命令就是你对该文件的选择,git add就是你要保留修改,把他送到暂存区里。git restore就是放弃修改改回原来的情况
这俩命令作用相反,但是用法一样
git add filename
git restore filename
git reset 和git rebase的区别与使用,以及我建议rebase替代reset的原因
最开始我遇到问题,想回到之前的情况直接操作可视化工具,SourceTree提示就是reset还原,当时觉得挺好的,还原源文件。后来听同事分享,实际上reset会有一个分支版本切换的问题,最好的方式是应该回溯到某一个一版本,也就是利用rebase,它会让代码更纯净,不和别的分支混在一起,可以参看下图来比较:
写了这么多,发现可视化工具极大地方便了我们,但有时候也会屏蔽了一些细节和实现,命令行模式可以帮助我们在遇到问题去分析,不要会比命令行的优势,git提示也足够详细,对我们git的使用有很多帮助。
下面是对我启发很大一个同事的分享的部分:借助同事的一句话,代码要有洁癖,希望代码管理也能有自己的小小的洁癖。
git 工作流规范
前言
因此假定大家已具备git基础知识和技能。如需巩固基础可参考连接:Git简明教程
中心思想
这套方案的预设背景是:
因此中心思想就是:代码管理要有“洁癖”
具体方向:
具体方案
代码仓库及分支约定
以下是总示意图:
准备工作
比如23 Android App的主仓库: git@code.aliyun.com:bdd/23app_android.git
git clone git@code.aliyun.com:wangkewei/23app_android.git
git remote add upstream git@code.aliyun.com:bdd/23app_android.git
这样,每个开发人员的代码,在自己的本地和远程仓库之间可以按自己的想法操作,而不会影响到主仓库
同时又与主仓库建立了关联,注意这个关联仅限于更新本地代码,而禁止push。
日常开发
更新 -> commit -> rebase -> push -> MR(合并请求)
更新
首先保证基于主仓库的稳定commit开始开发,通常是每个版本的最终上线commit、或者提测commit
涉及到的操作可能有:
git fetch --all #更新远程分支信息到本地(包括origin和upstream) git checkout -b dev_v1.1 #创建v1.1分支 git reset --hard <commit_id> #将代码强制更新到稳定的commit:
注意,git reset --hard是丢弃现有的全部信息,完全更新到对应commit
执行前一定要想清楚,这个分支上的东西是否可以丢弃。这里的场景是一个新分支,执行这个命令是OK的
提交
以下要求不是强制的,做不到也一样可以开发。但是,养成好习惯会在无形中受益。
这样可以灵活应对产品改需求,以及灵活划分什么需求在这个版本,什么需求放下个版本。
rebase
rebase 很关键,保持代码分支清晰整洁尤其靠这个命令
从checkout之后开发一定过了一段时间,此时主仓库很有可能有新的代码。
rebase的含义是:
dev分支从主分支的A节点 checkout,后来主分支进化到了A1
B rebase A 是指,从A那个节点开始,所有dev的更新,先暂存。将节点更新到A1,然后再将dev的更新重新提交。
注意:rebase是会改变历史基线的,执行rebase一定注意,只能是自己的分支rebase公共分支,严禁公共分支rebase自己的分支!公共分支只接受合并请求
合并请求
首先push自己的代码到远程仓库
git push origin #push自己的代码到远程仓库
然后在代码管理平台发起合并请求
提测与发布
确认版本需求的合并请求均已合并后,向持续集成环境(比如jenkins)发起打包,提测
测试反馈有问题,修复代码、rebase、push、合并请求。
提测通过,将代码发布到master分支,并打上tag
其他
遇到冲突怎么办
设计工作流的关键就在于更好的处理冲突的问题:
首先,如果做好前面说的以独立小需求点为提交,那么冲突的可能性就会降低
其次,这一步冲突的解决发生在本地自己的分支,不会影响主仓库,可以在冲突得到妥善解决之后,再提交。
并且,如果所有开发人员都使用了rebase解决冲突,那么每个开发人员处理的冲突,都是自己代码和主分支的冲突,自己的业务相对熟悉,能够处理。
开发到一半遇到有bug反馈,怎么办
revert和reset是有区别的
revert是针对所有的改动,生成反向的改动,因此在历史记录里是多了一条反向操作。这会增加git历史的阅读难度。
reset是将状态指针跳转到其他地方。
reset --hard 是丢弃现有所有的改动,将代码完全更新到指定commit
reset --soft 是保留现在的代码不变,而对比的HEAD跳转到指定commit,执行后可以将代码变动做成整个提交
通常对于后悔的提交,只要是还没合并到主仓库,我建议大家使用reset代替revert。
git checkout -b tmp #创建新分支来保留新代码 git checkout dev #切换到准备提交的分支 git reset --hard <commit-id> #reset到希望回退的点 git cherry-pick <commit-ids> #排除后悔的commit,将其他的commit合进来 git push --force origin #提交代码,如果远程仓库已有,需要额外增加--force参数
revert适用的场景:代码已经合并到了公共仓库了,这时候reset会篡改公共仓库的历史。我们约定了公共仓库只接收合并请求。因此这时候使用revert。
规范回顾
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。