当前位置:   article > 正文

git clone 一部分_git日常使用和常见的命令

restore和add的区别

实际上git使用越来越普及了,当然如果你还是把它当作svn来使用,或者就是只是通过一些图形化工具上几个按钮点一点就失去很多git自身有魅力的地方。

首先对照svn或者其他上一代的版本管理工具,我们修改文件不再有“这个文件要不要lock的问题”,要知道之前曾经工作一个单位,通过版本管理工具修改文件不仅要把文件锁上不让别人修改之外,还要把自己的电话信息放进去,这样别人要改的时候,就会打电话给你“放开那个文件”。

git强调一个“repository”仓库的概念,别小瞧这个概念,你本地拉下代码的同时你也会创建一个本地仓库,这个仓库和大家共用的那个本质上区别不大。也就是代码服务器有的你都有,这也就是分布式的好处,你不在围绕服务器上的那个代码仓库唯命是从,你甚至可以和小伙伴的仓库进行合作。

代码合并和冲突解决:

版本冲突这个你用什么样的版本工具都会遇到,解决的方式也是各种各样。但是这里有一个中心思想就是,就是要保证线上的master稳定版没有问题,不要“带病上岗”。

一. 阿里云上的云效做法:

做一个需求来一条新分支出来,然后在上边做需求。这时候做完后提交,实际上会云效再拉一条新的分支,你要和别人的分支合并到这个分支上,然后发不到不同环境,如果是线上环境的就会把这个给分支合并到master分支(当然前提是你已经在测试环境分支的分支上都通过测试,或者说除了线上环境以外都测试过了没问题才可以发到线上。)。如何出现冲突基本是在测试环境,这时候发布不成功,云效会提醒你怎么做

大概的步骤:

(1)切换分支到合并的分支

(2)git status看一下什么问题,一般来说都是文件冲突

(3)处理冲突文件

(4)提交

这里有个比较坑爹的就是,在云效发布的过程中,解决冲突后最好是去发布界面点击一下“解决冲突”,官方的说法你如果重新部署或者发布可能会出现循环报错,就是你以为改好了,但是你发布还是爆出原来的那个问题,然后你去修改,不断的往复。

二. 还有一个就是我的一个同事的做法也挺有意思的:

(从这个同事身上我学到了不少git的相关知识,文章最后一部分我还会把他的总结部分贴出来分享一下)

他的做法就是自己本地两个仓库,一个是自己开发的,一个是对应master(当然这个master对应的是服务器master一致的),提交文件的时候,把开发的合并到另一个仓库上,如果能通过说明没啥问题,然后提交到开发版本分支,然后开发版本分支再合并master分支。

中间出现冲突一可能是在本地两个仓库(开发仓库,稳定版本仓库),这个其实就是告诉你那些文件要注意要解决,本地通不过,线上服务器也不能通过

还有一个就是合并开发分支的时候,记住不能直接合并到maste分支(即使我们用旧的版本管理工具,也要求每个环境不同的分支,一步一步的合并上去,开发分支----测试环境分支---准线上环境---线上环境)

00ecc5e39137487fb1d496379bfd9f16.png

git常见命令:

实际上clone代码下来,本地git设置这些看一些git文档基本是第一页第二页就有的,这里会挑一些,不是很常用,但是遇到问题在终端查看解决问题都会用上比较有用的

git状态

git status   

查看工作目录状态,这是最频繁的使用的一个命令,到底有什么问题,为什么切换不了分支?到底是什么文件有冲突?一查便知,以下是我这边测试某个目录的的文件情况

67fe1ecb94dd94bc6c164937e442aee8.png

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之后会清空暂存区,然后把暂存区的文件送到版本库里面

47b2fcad0bb451f7fb911d379fa8a0dd.png

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,它会让代码更纯净,不和别的分支混在一起,可以参看下图来比较:

e3fb277b7846c9b86e0944220ff85fa9.png

写了这么多,发现可视化工具极大地方便了我们,但有时候也会屏蔽了一些细节和实现,命令行模式可以帮助我们在遇到问题去分析,不要会比命令行的优势,git提示也足够详细,对我们git的使用有很多帮助。

下面是对我启发很大一个同事的分享的部分:借助同事的一句话,代码要有洁癖,希望代码管理也能有自己的小小的洁癖。

git 工作流规范

前言

  1. 本文讲述的是团队使用git管理代码,协同开发的工作流。

因此假定大家已具备git基础知识和技能。如需巩固基础可参考连接:Git简明教程

  1. 本文是我个人的经验总结,尚需大家探讨约定。


中心思想
这套方案的预设背景是:

  1. 人的思维不可靠,而机器没有目的性。
  2. 团队协同开发时,代码容易变动,合并时容易冲突


因此中心思想就是:代码管理要有“洁癖”
具体方向:

  1. 人只在接近人的思维上操作,而尽可能不操作到具体代码。具体代码的变动交给git处理
  2. 保持不同质量的代码的隔离,避免产生混乱。
  3. 使用能简化git分叉的操作方式,保持分支的清晰易懂。


具体方案



代码仓库及分支约定

  • 公共主仓库:以项目为单位,团队开发的代码主仓库
    • master:稳定的主分支,只接收来自dev的经过测试的上限的代码
    • dev:开发主分支,只接收经过review的合并请求
  • 个人仓库:各个开发者自行维护,与公共仓库隔离
    • orgin/dev:用于接收本地commit,向公共主分支发起合并请求
    • dev:用于本地开发代码,可以用其他名字


以下是总示意图:

00ecc5e39137487fb1d496379bfd9f16.png


准备工作

  1. 每个项目建立对应的主仓库

比如23 Android App的主仓库: git@code.aliyun.com:bdd/23app_android.git

  1. 每个开发人员,在公共仓库上fork出自己的仓库
    比如我fork出自己的仓库 git@code.aliyun.com:wangkewei/23app_android.git
  2. 克隆自己的仓库到本地


git clone git@code.aliyun.com:wangkewei/23app_android.git

  1. 关键的一步:将公共仓库添加为上游仓库(upstream)


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的
提交
以下要求不是强制的,做不到也一样可以开发。但是,养成好习惯会在无形中受益。

  • 尽可能以独立小需求点为提交,避免一个需求分散在不同commit,也避免一个commit里有多个小需求。尤其要注意,别把开发到一半的跑不通的代码作为提交。(开发到一半的代码用stash,这个后面会补充)

这样可以灵活应对产品改需求,以及灵活划分什么需求在这个版本,什么需求放下个版本。

  • 避免没有任何信息的提交。commit信息应当描述清楚对应的需求点,可以提到改动的类。更好的方式是结合需求管理系统,将对应需求的链接贴上,这样核对需求的时候跳转链接查看详细信息以及更新的信息,非常方便。


rebase
rebase 很关键,保持代码分支清晰整洁尤其靠这个命令
从checkout之后开发一定过了一段时间,此时主仓库很有可能有新的代码。
rebase的含义是:
dev分支从主分支的A节点 checkout,后来主分支进化到了A1
B rebase A 是指,从A那个节点开始,所有dev的更新,先暂存。将节点更新到A1,然后再将dev的更新重新提交。

e3fb277b7846c9b86e0944220ff85fa9.png


注意:rebase是会改变历史基线的,执行rebase一定注意,只能是自己的分支rebase公共分支,严禁公共分支rebase自己的分支!公共分支只接受合并请求
合并请求
首先push自己的代码到远程仓库
git push origin #push自己的代码到远程仓库
然后在代码管理平台发起合并请求

  • 发起合并请求的代码,应当是自测过,相对稳定的代码,禁止合并跑不通的代码。通常是提测版本时各自发起合并请求。
  • 团队开发时,合并请求必须由主管或其他的开发者review。发现自己看不到的问题。
  • 注意,如果合并请求有冲突,建议重新rebase 到本地,解决了再提交。
  • 合并通过后,通知到其他开发人员fetch、rebase


提测与发布
确认版本需求的合并请求均已合并后,向持续集成环境(比如jenkins)发起打包,提测
测试反馈有问题,修复代码、rebase、push、合并请求。
提测通过,将代码发布到master分支,并打上tag
其他
遇到冲突怎么办
设计工作流的关键就在于更好的处理冲突的问题:
首先,如果做好前面说的以独立小需求点为提交,那么冲突的可能性就会降低
其次,这一步冲突的解决发生在本地自己的分支,不会影响主仓库,可以在冲突得到妥善解决之后,再提交。
并且,如果所有开发人员都使用了rebase解决冲突,那么每个开发人员处理的冲突,都是自己代码和主分支的冲突,自己的业务相对熟悉,能够处理。
开发到一半遇到有bug反馈,怎么办

  1. 使用git stash,将所有工作状态暂存。
  2. checkout fix分支,将fix强制reset到需要重现bug的commit,检查定位问题。
  3. 修复问题,commit修复代码
  4. 转到dev分支,然后cherry-pick这个修复代码,再push、合并请求
  5. 回到开发到一半的分支,unstash你开发到一半的代码。


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。
规范回顾

  • upstream/master,只接收来自upstream/dev的,发布上线的代码。
  • upstream/dev,只接收合并请求,合并请求应当是自测、review过的。禁止拿跑不通的代码提交合并请求
  • 关联upstream仓库,可以pull代码,禁止直接push
  • git reset --hard 是丢弃现有信息,完全更新到指定状态,适用于新建的分支,跳转无负担。
  • git revert 是提交反向变动,只在代码已经合并到公共仓库还需要撤销的时候才使用revert
  • git commit
    • 尽可能一个小需求一个commit,便于追溯、调整,也便于解决冲突
    • 避免没有信息的commit,应当简要描述变动点,最好带上需求链接
  • git rebase有利于简化历史方便阅读。只能是自己的分支rebase公共分支,禁止公共分支rebase个人分支。
  • git cherry-pick 是将某个commit摘取到当前分支来,适合厘清需求点,准备合并请求
  • git stash/unstash 将开发到一半的代码暂存,适用于中断处理其他问题,然后恢复现场。
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号