关山难越,谁悲失路之人;萍水相逢,尽是他乡之客。
百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程教程 > 技术文章 > 正文

恕我直言,在座的各位根本不会写 Java!

guanshanw 2023-09-29 21:39 13 浏览 0 评论

导语

自 2013 年毕业后,今年已经是我工作的第 4 个年头了,总在做 Java 相关的工作,终于有时间坐下来,写一篇关于 Java 写法的一篇文章,来探讨一下如果你真的是一个 Java 程序员,那你真的会写 Java 吗?

恕我直言,在座的各位根本不会写 Java!

笔者是一个务实的程序员,故本文绝非扯淡文章,文中内容都是干货,望读者看后,能有所收获。

文章核心

其实,本不想把标题写的那么恐怖,只是发现很多人干了几年 Java 以后,都自认为是一个不错的 Java 程序员了,可以拿着上万的工资都处宣扬自己了,写这篇文章的目的并不是嘲讽和我一样做 Java 的同行们,只是希望读者看到此篇文章后,可以和我一样,心平气和的争取做一个优秀的程序员。

由于一直从事移动互联网相关工作,Java 开发中经常和移动端打交道或者做一些后端的工作,所以本篇文章更可能涉及和移动端的交互或者与后端的交互方式,笔者希望以自身的一些学习经验或者开发经验,可以带动认真阅读本篇文章的读者们,让大家对 Java 有一个更好的态度去学习它,它不只是一个赚钱的工具而已。

笔者身边有很多与笔者年龄相仿或年龄更大的朋友或同事,经常有人问我:“你现在还在学习吗?我觉得没什么好学的,这些东西都差不多”,我总是回答只要有时间,我就要看一会书,这个时候,大家都会露出一副不屑的眼神或笑容。其实,非常能理解身边朋友或同事的看法,以目前状态来讲,大多都是工作至少 5 年的程序员了,对于公司大大小小的业务需要,以目前的知识储备来讲,都可以轻松应对,“没有什么好学的”其实这句话没有多大的问题,但是,如果你对编程还有一点点兴趣,只是不知道如何努力或改进,希望本篇文章可以帮到你。

本文不是一个吹嘘的文章,不会讲很多高深的架构,相反,会讲解很多基础的问题和写法问题,如果读者自认为基础问题和写法问题都是不是问题,那请忽略这篇文章,节省出时间去做一些有意义的事情。

开发工具

不知道有多少”老”程序员还在使用 Eclipse,这些程序员们要不就是因循守旧,要不就是根本就不知道其他好的开发工具的存在,Eclipse 吃内存卡顿的现象以及各种偶然莫名异常的出现,都告知我们是时候寻找新的开发工具了。

根本就不想多解释要换什么样的 IDE,如果你想成为一个优秀的 Java 程序员,请更换 IntelliJ IDEA。使用 IDEA 的好处,请搜索谷歌。

更换 IDE 不在我本文的重点内容中,所以不想用太多的篇幅去写为什么更换IDE。在这里,我只能告诉你,更换 IDE 只为了更好、更快的写好 Java 代码。原因略。

别告诉我快捷键不好用,请尝试新事物。

bean

bean 使我们使用最多的模型之一,我将以大篇幅去讲解 bean,希望读者好好体会。

根据很多 Java 程序员的”经验”来看,一个数据库表则对应着一个 domain 对象,所以很多程序员在写代码时,包名则使用:com.xxx.domain ,这样写好像已经成为了行业的一种约束,数据库映射对象就应该是 domain。但是你错了,domain 是一个领域对象,往往我们再做传统 Java 软件 Web 开发中,这些 domain 都是贫血模型,是没有行为的,或是没有足够的领域模型的行为的,所以,以这个理论来讲,这些 domain 都应该是一个普通的 entity 对象,并非领域对象,所以请把包名改为:com.xxx.entity。

如果你还不理解我说的话,请看一下 Vaughn Vernon 出的一本叫做《IMPLEMENTING DOMAIN-DRIVEN DESIGN》(实现领域驱动设计)这本书,书中讲解了贫血模型与领域模型的区别,相信你会受益匪浅。

数据传输我们应该使用 DTO 对象作为传输对象,这是我们所约定的,因为很长时间我一直都在做移动端 API 设计的工作,有很多人告诉我,他们认为只有给手机端传输数据的时候(input or output),这些对象成为 DTO 对象。请注意!这种理解是错误的,只要是用于网络传输的对象,我们都认为他们可以当做是 DTO 对象,比如电商平台中,用户进行下单,下单后的数据,订单会发到 OMS 或者 ERP 系统,这些对接的返回值以及入参也叫 DTO 对象。

我们约定某对象如果是 DTO 对象,就将名称改为 XXDTO,比如订单下发OMS:OMSOrderInputDTO。

正如我们所知,DTO 为系统与外界交互的模型对象,那么肯定会有一个步骤是将 DTO 对象转化为 BO 对象或者是普通的 entity 对象,让 service 层去处理。

场景

比如添加会员操作,由于用于演示,我只考虑用户的一些简单数据,当后台管理员点击添加用户时,只需要传过来用户的姓名和年龄就可以了,后端接受到数据后,将添加创建时间和更新时间和默认密码三个字段,然后保存数据库。

()

{

UserService userService;

{

User user = User();

user.setUsername(userInputDTO.getUsername());

user.setAge(userInputDTO.getAge());

userService.addUser(user);

}

}

我们只关注一下上述代码中

User user = User();

user.setUsername(userInputDTO.getUsername());

user.setAge(userInputDTO.getAge());

DTO.getAge());

请使用工具

上边的代码,从逻辑上讲,是没有问题的,只是这种写法让我很厌烦,例子中只有两个字段,如果有 20 个字段,我们要如何做呢?一个一个进行 set 数据吗?当然,如果你这么做了,肯定不会有什么问题,但是,这肯定不是一个最优的做法。

网上有很多工具,支持浅拷贝或深拷贝的 Utils。举个例子,我们可以使用 org.springframework.beans.BeanUtils#copy

{

User user = User();

BeanUtils.copyProperties(userInputDTO,user);

userService.addUser(user);

}

rvice.addUser(user);

}

BeanUtils.copyProperties 是一个浅拷贝方法,复制属性时,我们只需要把 DTO 对象和要转化的对象两个的属性值设置为一样的名称,并且保证一样的类型就可以了。如果你在做 DTO 转化的时候一直使用 set 进行属性赋值,那么请尝试这种方式简化代码,让代码更加清晰!

转化的语义

上边的转化过程,读者看后肯定觉得

User user = User();

BeanUtils.copyProperties(userInputDTO,user);

anUtils.copyProperties(userInputDTO,user);

虽然这段代码很

{

User user = convertFor(userInputDTO);

userService.addUser(user);

}

{

User user = User();

BeanUtils.copyProperties(userInputDTO,user);

user;

}

pyProperties(userInputDTO,u

user = convertFor(userInputDTO);

userService.addUser(user);

的放到一个方法中,比如:

user = convertFor(userInputDTO);

userService.addUser(user);

这两段代码都没有暴露实现,都是在讲如何在同一个方法中,做一组相同层次的语义操作,而不是暴露具体的实现。

如上所述,是一种重构方式,读者可以参考 Martin Fowler 的《Refactoring Imporving the Design of Existing Code》(重构 改善既有代码的设计) 这本书中的 Extract Method 重构方式。

抽象接口定义

当实际工作中,完成了几个 API 的 DTO 转化时,我们会发现,这样的操作有很多很

<,> {

;

}

r 这个方法的语义将产生变化,它将是一个实现类。

看一下抽象后的接口:

<,> {

{

{

User user = User();

BeanUtils.copyProperties(userInputDTO,user);

user;

}

}

()

{

UserService userService;

{

User user = UserInputDTOConvert().convert(userInputDTO);

userService.addUser(user);

}

{

User user = UserInputDTOConvert().convert(userInputDTO);

userService.addUser(user);

}

}

;

}

}

review code

如果你是一个优秀的 Java 程序员,我相信你应该

{

User user = UserInputDTOConvert().convert(userInputDTO);

User saveUserResult = userService.addUser(user);

UserOutputDTO result = UserOutDTOConvert().convertToUser(saveUserResult);

ert(userInputDTO);

User saveUserResult = userService.addUser(user);

UserOutputDTO result = UserOutDTOConvert().convertToUser(saveUserResult);

result;

ult);

result;

}

}

这样你的 API 才更健全。

不知道在看完这段代码之后,读者有是否发现还有其他问题的存在,作为一个优秀的 Java 程序

{

String username;

age;

{

username;

}

{

.username = username;

}

{

age;

}

{

.age = age;

}

{

UserInputDTOConvert userInputDTOConvert = UserInputDTOConvert();

User convert = userInputDTOConvert.convert();

convert;

}

<,> {

{

User user =

user = new UserInputDTOConvert().convert(userInputDTO);

saveUserResult = userService.addUser(user);

user = userInputDTO.convertToUser();

saveUs

User();

BeanUtils.copyProperties(userInputDTO,user);

user;

}

}

user = new UserInputDTOConvert().convert(userInputDTO);

saveUserResult = userService.addUser(user);

user = userInputDTO.convertToUser();

saveUserResult = userService.addUs

nvertToUser();

saveUserResult = userService.addUser(user);

er(user);

我们再 DTO 对象中添加了转

<, > <, > {

;

;

}

,这中 Convert 并不是业务级别上的接口定义,它只是用于普通 bean 之间转化属性值的普

<,> {

{

User user = User();

BeanUtils.copyProperties(userInputDTO,user);

<, > {

{

User user = User();

BeanUtils.copyProperties(userInputDTO,user);

user;

}

{

UserInputDTO userInputDTO = UserInputDTO();

BeanUtils.

, > {

{

User use

{

User use

{

String username;

age;

{

username;

}

{

.username = username;

}

{

age;

}

{

.age = age;

}

{

UserDTOConvert userDTOConvert = UserDTOConvert();

User convert = userDTOConvert.convert();

convert;

}

{

UserDTOConvert userDTOConvert = UserDTOConvert();

UserDTO convert = userDTOConvert.reverse().convert(user);

convert;

}

<, > {

{

User user = User();

BeanUtils.copyProperties(userDTO,user);

user;

}

{

User user = userDTO.convertToUser();

User saveResultUser = userService.addUser(user);

<, > {

r);

<, > {

> {

<, > {

{

User user = User();

BeanUtils.copyProperties(userDTO,user);

user;

}

{

User user = userDTO.convertToUser();

User saveResultUser = userService.addUser(user);

UserDTO result = userDTO.convertFor(saveResu

ce.addUser(user);

UserDTO result = userDTO.convertFor(

TO result = userDTO.convertFor(

<, > {

{

User user = User();

BeanUtils.copyProperties(userDTO,user);

user;

}

{

Ass

user;

}

{

AssertionError();

AssertionError();

}

}

);

}

}

看一下 doBackward 方法,直接抛出了一个断言异常,而不是业务异常,这段代码告诉代码的调用者,这个方法不是准你调用的,如果你调用,我就”断言”你调用错误了。

关于异常处理的更详细介

{

String username;

age;

UserDTO addUser( UserDTO userDTO){

User user = userDTO.convertToUser();

User saveResultUser = userService.addUser(user);

UserDTO result = userDTO.convertFor(saveResultUser);

result;

}

你为什还要验证?

其实答案是这样的,我从不相信任

{

checkDTOParams(bindingResult);

User user = userDTO.convertToUser();

User saveResultUser = userService.addUser(user);

UserDTO result = userDTO.convertFor(saveResultUser);

re

addUser( UserDTO userDTO){

User user = userDTO.convertToUser();

User saveResultUser = userService.addUser(user);

UserDTO result =

serDTO.convertToUser();

User

User);

serDTO.convertToUser();

Use

rtToUser();

User

r

{

checkDTOParams(bindingResult);

User user = user

{

checkDTOParams(bindingResult);

User user = userDTO.convertToUser();

User saveResultUser

serDTO.convertToUser();

User saveResultUser = userService.addUse

= userService.addUse

{

String username;

age;

{

UserDTOConvert userDTOConvert = UserDTOConvert();

User convert = userDTOConvert.convert();

convert;

}

{

UserDTOConvert userDTOConvert = UserDTOConvert();

UserDTO convert = userDTOConvert.reverse().convert(user);

convert;

}

<, > {

{

User user = User();

BeanUtil

String username;

age;

{

UserDTOConvert us

String username;

age;

{

UserDTOConvert userDTOConv

{

UserDTOConvert userDTOConvert = UserDTOConvert()

ert = UserDTOConvert()

{

String name;

age;

{

name;

}

{

.name = name;

{

User user = User();

BeanUtils

{

;

Student student = Stud

{

User user = User();

BeanUtils

AssertionError(

{

User user = User();

Bea

er user = User();

BeanUtils

nUtils

(chain =

AssertionError();

}

}

}

{

AssertionError();

}

AssertionError();

}

}

}

);

}

}

}

看到了吧,烦人的 Getter

{

String name;

age;

{

name;

}

{

.name = name;

;

}

{

age;

}

name;

}

{

.name = name;

;

}

{

age;

}

{

;

}

}

.name =

Student stud

{

{

{

Student student = Student()

.set

Student student = Student()

.setAge()

.setNam

t()

.setAge()

.setName();

e();

相信合理使用这样的链式代

age;

}

(staticName = )

age;

}

age;

}

age;

}

age;

}

这样就完成了一个对于 bean 来讲很友好的链式操作。

静态构造方法

静态构造方法的语义和简化程度真的高于直接去 new 一个对象。比如 new 一个 List 对象,过去的使用是这样的:

<String

(chain = )

(staticName = )

{

String name;

age;

}

去产生 List,这样的语义是不是要比直接 new 一个子类来的更直接一些呢,答案是肯定的,再比如如果有一个工具类叫做 Maps,那你是否想到了创建 Map 的方法呢:

HashMap<, > objectObjectHashMap = Maps.newHashMap();

好了,如果你理解了我说的语义,那么,你已经向成为 Java 程序员更近了一步了。

再回过头来看刚刚的 Student,很多时候,我们去写 Student 这个 bean 的时候,他会有一些必输字段,比如 Student 中的 name 字段,一般处理的方式是将 name 字段

{

String name;

age;

{

name;

}

{

.name = name;

}

{

age;

}

{

.age = age;

}

{

Builder();

}

{

String name;

age;

{

.name = name;

;

}

{

.age = age;

;

}

{

Student student = Student();

student.setAge(age);

student.setName(name);

student;

}

{

String name;

age;

}

nt.().setAge();

这样来写代码,真的很简洁,并且可读性很强。

使用 builder

Builder 模式我不想再多解释了,读者可以看一下《Head First》(设计模式) 的建造者模式。

今天其实要说的是一种变种的 builder 模式,那就是构建 bean 的 builder 模式,其实主要的思想是带着大家一起看一下 lombok 给我们带来了什么。

看一下 S

{

RestTemplate restTemplate;

{

.restTemplate = restTemplate;

}

}

{

RestTemplate restTemplate;

{

(restTemplate);

.restTemplate = restTemplate;

}

<T>

{

RestResponseDTO<T> restResponseDTO = RestResponseDTO<T>();

ResponseEntity<T> tResponseEntity;

{

tResponseEntity = restTemplate.postForEntity(url, request, responseType, uriVariables);

restResponseDTO.setData(tResponseEntity.getBody());

restResponseDTO.setMessage(tResponseEntity.getStatusCode()

{

.restTemplate = restTemplate;

}

}

restRes

{

.restTemplate = restTemplate;

}

{

.restTemplate = restTempla

{

.restTemplate = restTemplate;

}

= restTemplate;

}

}

}

然后再

{

RestTemplate restTemplate;

{

.restTemplate = restTemplate;

}

<T> {

restTemplate.getForObject(url,responseType,uriVariables);

}

<T> {

restTemplate.getForObject(url,responseType,uriVariables);

}

<T> {

restTemplate.getForObject(url,responseType);

}

<T>

{

RestTemplate restTemplate;

{

.restTempla

{

RestTemplate restTemplate;

{

.restTemplate = restTemplate;

}

<T>

.restTemplate = restTemplate;

}

<T>

{

{

restTemplate.getForOb

{

restTemplate.getForObject(

ject(

DISTRIBUTION_TIME_SPLIT_TIME = ().withTime(,,,);

private Date calculateDistributionTimeByOrderCreateTime(Date orderCreateTime){

orderCreateDateTime = (orderCreateTime);

Date tomorrow = orderCreateDateTime.plusDays().toDate();

Date theDayAfterTomorrow = orderCreateDateTime.plusDays().toDate();

orderCreateDateTime.isAfter(DISTRIBUTION_TIME_SPLIT_TIME) ? wrapDistributionTime(theDayAfterTomorrow) : wrapDistributionTime(tomorrow);

}

private Date wrapDistributionTime(Date distributionTime){

currentDistributionDateTime = (distributionTime);

plusOneDay = currentDistributionDateTime.plusDays();

boolean isSunday = (DateTimeConstants.SUNDAY == currentDistributionDateTime.getDayOfWeek());

isSunday ? plusOneDay.toDate() : currentDistributionDateTime.toDate() ;

}

程序员吧。

重构

项目需求

项目开发阶段,有一个关于下单发货的需求:如果今天下午 3 点前

DISTRIBUTION_TIME_SPLIT_TIME = ().withTime(,,,);

private Date calculateDistributionTimeByOrderCreateTime(Date orderCreateTime){

orderCreateDateTime = (orderCreateTime);

Date tomorrow = orderCreateDateTime.plusDays().toDate();

Date theDayAfterTomorrow = orderCreateDateTime.plusDays().toDate();

orderCreateDateTime.isAfter(DISTRIBUTION_TIME_SPLIT_TIME) ? wrapDistributionTime(theDayAfterTomorrow) : wrapDistributionTime(tomorrow);

}

private Date wrapDistributionTime(Date distributionTime){

currentDistributionDateTime = (distributionTime);

plusOneDay

ibutionTime(Date distributionTime){

currentDistributionDateTime = (distributionTime);

plusOneDay = currentDistributionDateTime.plusDays();

boolean isSunday = (DateTimeConstants.SUNDAY == currentDistribution

lusOneDay = currentDistributionDateTime.plusDays();

boolean isSunday = (DateTimeConstants.SUNDAY == currentDistributionDateTime.getDayOfWeek());

isSunday ?

butionDateTime.getDayOfWeek());

isSunday ? plusOneDay.toDate() : cur

y ? plusOneDay.toDate() : currentDistributionDateTime.toDat

currentDistributionDateTime.toDate() ;

}

Date() ;

}

读这段代码的时候,你会发现,我将判断和有可能出现的不同结果都当做一个变量,最终做一个三目运算符的方式进行返回,这样的优雅和可读性显而易见,当然这样的代码不是一蹴而就的,我优化了 3 遍产生的以上代码。读者可根据自己的代码和我写的代码进行对比。

提高方法

如果你做了 3 年+的程序员,我相信像如上这样的需求,你很轻松就能完成,但是如果你想做一个会写 Java 的程序员,就好好的思考和重构代码吧。

写代码就如同写字一样,同样的字,大家都会写,但是写出来是否好看就不一定了。如果想把程序写好,就要不断的思考和重构,敢于尝试,敢于创新,不要因循守旧,一定要做一个优秀的 Java 程序员。

提高代码水平最好的方法就是有条理的重构!(注意:是有条理的重构)

设计模式就是工具,而不是提现你是否是高水平程序员的一个指标。

我经常会看到某一个程序员兴奋的大喊,哪个程序哪个点我用到了设计模式,写的多么多么优秀,多么多么好。我仔细去翻阅的时候,却发现有很多是过度设计的。

业务驱动技术 or 技术驱动业务

业务驱动技术 or 技术驱动业务 ?其实这是一个一直在争论的话题,但是很多人不这么认为,我觉得就是大家不愿意承认罢了。我来和大家大概分析一下作为一个 Java 程序员,我们应该如何判断自己所处于的位置.

业务驱动技术:如果你所在的项目是一个收益很小或者甚至没有收益的项目,请不要搞其他创新的东西,不要驱动业务要如何如何做,而是要熟知业务现在的痛点是什么?如何才能帮助业务盈利或者让项目更好,更顺利的进行。

技术驱动业务:如果你所在的项目是一个很牛的项目,比如淘宝这类的项目,我可以在满足业务需求的情况下,和业务沟通,使用什么样的技术能更好的帮助业务创造收益,比如说下单的时候要进队列,可能几分钟之后订单状态才能处理完成,但是会让用户有更流畅的体验,赚取更多的访问流量,那么我相信业务愿意被技术驱动,会同意订单的延迟问题,这样便是技术驱动业务。

我相信大部分人还都处于业务驱动技术的方向吧。

所以你既然不能驱动业务,那就请拥抱业务变化吧。

代码设计

一直在做 Java 后端的项目,经常会有一些变动,我相信大家也都遇到过。

比如当我们写一段代码的时候,我们考虑将需求映射成代码的状态模式,突然有一天,状态模式里边又添加了很多行为变化的东西,这时候你就挠头了,你硬生生的将状态模式中添加过多行为和变化。

慢慢的你会发现这些状态模式,其实更像是一簇算法,应该使用策略模式,这时你应该已经晕头转向了。

说了这么多,我的意思是,只要你觉得合理,就请将状态模式改为策略模式吧,所有的模式并不是凭空想象出来的,都是基于重构。

Java 编程中没有银弹,请拥抱业务变化,一直思考重构,你就有一个更好的代码设计!

你真的优秀吗?

真不好意思,我取了一个这么无聊的标题。

国外流行一种编程方式,叫做结对编程,我相信国内很多公司都没有这么做,我就不在讲述结对编程带来的好处了,其实就是一边 code review,一边互相提高的一个过程。既然做不到这个,那如何让自己活在自己的世界中不断提高呢?

“平时开发的时候,做出的代码总认为是正确的,而且写法是完美的。”,我相信这是大部分人的心声,还回到刚刚的问题,如何在自己的世界中不断提高呢?

答案就是:

  1. 多看成熟框架的源码
  2. 多回头看自己的代码
  3. 勤于重构

你真的优秀吗?如果你每周都完成了学习源码,回头看自己代码,然后勤于重构,我认为你就真的很优秀了。

即使也许你只是刚刚入门,但是一直坚持,你就是一个真的会写java代码的程序员了。

技能

不想多讨论 UML 相关的知识,但是我觉得你如果真的会写 Java,请先学会表达自己,UML 就是你说话的语言,做一名优秀的 Java 程序员,请至少学会这两种 UML 图:

  1. 类图
  2. 时序图

我认为保持代码的简洁和可读性是代码的最基本保证,如果有一天为了程序的效率而降低了这两点,我认为是可以谅解的,除此之外,没有任何理由可以让你任意挥霍你的代码。

  1. 读者可以看一下 Robert C. Martin 出版的《Clean Code》(代码整洁之道) 这本书
  2. 可以参考美团文章聊聊 clean code();
  3. 也可以看一下阿里的 Java 编码规范()。

无论如何,请保持你的代码的整洁。

这点其实和会写 Java 没有关系,但是 Linux 很多时候确实承载运行 Java 的容器,请学好 Linux 的基础命令。

  1. 参考鸟哥的《Linux私房菜》

总结

Java 是一个大体系,今天讨论并未涉及框架和架构相关知识,只是讨论如何写好代码。

本文从写 Java 程序的小方面一直写到大方面,来阐述了如何才能写好 Java 程序,并告诉读者们如何才能提高自身的编码水平。

我希望看到这篇文章的各位都能做一个优秀的 Java 程序员。

相关推荐

七条简单命令让您玩转Git
七条简单命令让您玩转Git

凭借着出色的协作能力、快速部署效果与代码构建辅助作用,Git已经得到越来越多企业用户的青睐。除了用于开发商业及消费级应用之外,众多科学及政府机构也开始尝试使用这...

2023-10-07 12:14 guanshanw

基本完整的关于Git分支branch的操作
基本完整的关于Git分支branch的操作

Git使用背景项目中要用到dev或者其他分支开发完代码,需要将该分支合并到master的需求操作步骤下面以dev名称为lex为分支名为例来操作一遍客户端操作:...

2023-10-07 12:14 guanshanw

Git 进阶(合并与变基)
Git 进阶(合并与变基)

在Git中整合来自不同分支的修改主要有两种方法:合并(merge)以及变基(rebase)合并(merge)merge流程图merge的原理是找到这两个分...

2023-10-07 12:13 guanshanw

Git学习笔记 003 Git进阶功能 part5 合并(第一部分)

合并(merge)是很常用的操作。尤其是一个庞大的很多人参与开发的企业级应用。一般会设定一个主分支,和多个副分支。在副分支开发完成后,合并到主分支中。始终保持主分支是一个完整的,稳定的最新状态的分支。...

非标题党,三张图帮你理解git merge和git rebase的区别
非标题党,三张图帮你理解git merge和git rebase的区别

初始场景:基于正常的开发分支修改几个小bug,然后在合并到开发分支上。gitmergegitcheckoutfeaturegitmergeho...

2023-10-07 12:13 guanshanw

git 初次使用(01)
git 初次使用(01)

先从github上克隆代码下来:使用vscode克隆代码如下图,填写上github仓库地址:vscode有时候克隆代码速度比较慢,可以用命令行方式克隆gitc...

2023-10-07 12:12 guanshanw

Git 远程操作

4.Git远程操作命令说明gitremote远程版本库操作gitfetch从远程获取版本库gitpull下载远程代码并合并gitpush上传远程代码并合并4.1远程版本库操作gitre...

Git常用命令-总结
Git常用命令-总结

创建git用户$gitconfig--globaluser.name"YourName"$gitconfig--globaluser.em...

2023-10-07 12:12 guanshanw

git中删除从别人clone下来项目的git信息,并修改为自己的分支

如果你从别人的Git存储库中克隆了一个项目,并想要删除与该存储库相关的Git信息,并将其修改为你自己的分支,则可以执行以下步骤:使用gitclone命令克隆存储库:gitclone<u...

git系列-回滚和放弃本地修改

回滚历史提交就是reset的功能。这种情况是已经提交远程仓库,需要回滚到之前的提交。gitreset--hardcommitId//注:强制提交后,当前版本后面的提交版本将会删掉!gi...

GIT使用小技巧大全
GIT使用小技巧大全

在大型软件工程的开发过程中,版本控制是无法绕过去的;目前来说,最火的版本控制软件就是GIT了。早两年SVN比较火,不过被大神linus喷了几次后,就日落西山了,...

2023-10-07 12:11 guanshanw

git相关命令-上
git相关命令-上

这些命令都是看了文档后,个人觉得比较有用的一些,展示给大家。回到远程仓库的状态抛弃本地所有的修改,回到远程仓库的状态。gitfetch--all&...

2023-10-07 12:10 guanshanw

Git命令行接口:掌握Git的必备技能
Git命令行接口:掌握Git的必备技能

Git是一款强大的分布式版本控制工具,它支持命令行界面操作。熟练掌握Git命令行接口,是开发者使用Git的必备技能之一。在这篇文章中,我们将介绍Git命令行接口...

2023-10-07 12:10 guanshanw

Git命令详解
Git命令详解

相信各位小伙伴们应该都对git有一些了解,毕竟作为代码管理的神器,就算不是IT行业的小伙伴肯定也或多或少的听说过一些。今天就来和小伙伴们分享一下自己总结的常用命...

2023-10-07 12:10 guanshanw

工作7年收集到的git命令
工作7年收集到的git命令

概念git中的术语解释:仓库也叫版本库(repository)stage:暂存区,add后会存到暂存区,commit后提交到版本库git安装linux...

2023-10-07 12:10 guanshanw

取消回复欢迎 发表评论: