# IDEA中使用Git

# Git基本操作

首先我们入职一家公司,上司一般会给你一个Gitlab链接,让你拉代码,我们会用到git pull,然后熟悉之后在写代码会用到git add等等操作。

image-20210705222900660

# git add

当我们新建一个类或者文件时,IDEA一般会自动弹出如下提示,其作用和git add相同。

image-20210705223348846

但如果你没有点击或者是跳过了,你可以看到新增的文件是红色的。

image-20210705223649265

此时你可以右键选择git add操作,操作之后就会变成绿色

image-20210705223732766

image-20210705223822079

# git commit

在add文件之后,我们需要提交文件。git和svn的区别就是,git提交是相当于把代码提交到本地仓库,并没有提交到远端分支上面去。

右键选择commit

image-20210705224356178

填写提交记录,一般来说新功能以feat开头,修复bug以fix开头。

image-20210705224439412

可以看到提交之后文件颜色变为黑色。

image-20210705224719335

通过alt+9或者View打开git控制台,可以看到最新的提交记录。

image-20210705225131128

# git push

上面commit代码之后,我们需要把本地代码推送到远程分支上。

image-20210705225320940

push之后我们可以去gitlab查看记录。

image-20210705225506607

# git pull

从远程获取最新版本并merge到本地。在主项目上面右键操作git pull。

image-20210705225833664

或者是在上方,看个人喜好。

image-20210705230041838

# git fetch

从远程获取最新版本到本地,不会自动merge,并且拉取当前项目的所有分支的的提交。

image-20210705231245143

在使用git fetch之后可以看到最新的其他人的提交记录,而且是2个master分支和feat_branch分支的提交记录,而我们本地的代码是没有变化的。

我们双击不同分支的提交记录,可以看到对应的差别。

image-20210705231644070

image-20210705231707335

# git merge

上面说到,git fetch是不会merge的,需要我们自己合并。

image-20210705231955961

选择对应的分支。

image-20210705232859390

通过上面的操作,可以理解git pull,fetch,merge的关系。

image-20210705234017636

git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。

git pull 则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决,遇到冲突,解决冲突。

# git rebase

rebase(变基),官方解释比较干燥,很么意思呢,简单来说就是用于把另一个分支的修改合并到当前分支

dev分支是我基于master分支拉取的新的分支。

image-20210705234712272

image-20210705235823030

在这之前master分支有过4次提交记录,此时master和dev分支都在C4节点上。

image-20210705235650524

然后我们在dev分支生成2个commit,master分支也生成2个commit,通过git控制台查看日志。

image-20210706000747500

此时,2个分支处于分叉状态。

image-20210706001409471

我们在master分支rebase dev分支

image-20210706001933077

在rebase的过程中,可能会出现冲突, 在这种情况,Git会停止rebase并会让你去解决冲突,在解决完冲突后,在push到远端仓库。

image-20210706001648569

image-20210706002145875

此时我们在控制台也可以看到master分支变成了一条直线。

image-20210706002605453

image-20210706002841045

当然,在实际开发中rebase尽量的少用,因为会把别人的提交记录冲掉,如果到时候别人的代码有问题,但是最新的commit记录又是你的,你懂的。

# git revert

在多人开发的过程中,我们有时会出现错误提交的情况,此时我们希望能撤销提交操作,让程序回到提交前的样子。

revert 用来回滚某个 commit,但是保留了前面或者后面的版本。比如我们commit了3个版本C1,C2,C3,

但后面发现版本C2有bug,想要撤销C2,但又不想影响撤销C3的提交,就可以用 git revert 命令来操作,同时生成新的版本C4,C4版本里会保留C3的提交,但撤销了C2的提交。

commit3次

image-20210706185528305

在C2版本右键revert

image-20210706185743908

合并C1,C3版本提交

image-20210706190230524

image-20210706190259897

日志记录

image-20210706190353598

# git reset

回退到某个版本的所有commit。如commit了3版本C1,C2,C3,如果需要回退到C1,可以使用reset。

reset的作用是修改HEAD的位置,即将HEAD指向的位置改变为之前存在的某个版本。

HEAD:使用git的每次提交,Git都会自动把它们串成一条时间线,这条时间线就是一个分支。如果没有新建分支,那么只有一条时间线,即只有一个分支,在Git里,这个分支叫主分支,即master分支。有一个HEAD指针指向当前分支(只有一个分支的情况下会指向master,而master是指向最新提交)。每个版本都会有自己的版本信息,如特有的版本号、版本名等。如下图,假设只有一个分支: image-20210706191016749

三次提交记录

image-20210706191244520

image-20210706191525548

image-20210706192052493

代码变为C1版本,但这个时候远端仓库的代码并没有回退。

image-20210706192112680

远端仓库,如果需要修改可再次push或者重新拉取分支即可。

image-20210706192753697

# 常见的使用场景

上面讲了很多git操作,其实大部分同学都知道,但在不理想情况下,还是会出现很多问题,比如修改提交记录,多分支合并,代码冲突等等。

# git rebase修改提交记录

假如在某次提交代码太快,还是用的上次的commit信息,或者是描述有问题,但是又commit了(只commit没有push

image-20210707111234621

此时看commit记录是不对的

image-20210707111503195

image-20210707111608063

通过rebase操作修改,选择对应的提交记录,点击Reword

image-20210707112200907

修改后在点击 Start Rebasing

image-20210707112336791

可以看到commit信息就修改过来了,此时再去push到远端仓库即可

image-20210707112516371

上面的操作针对的是commit操作,并不是commit&push操作,也就是说修改的是本地的提交记录。

为什么会有这种情况?

现在很多公司都有代码检查,比如阿里的,或者是check-style,对应gitlab也是可以对commit信息做限制的,即commit信息未按照指定格式,你执行commit&push操作,只会commit到本地,而不会push到远端。比如我之前的公司commit信息的格式为:

bugid:xxx   或者   featid:xxx
1

上面的冒号规定是英文的,但我手速太快,写成了中文的冒号,此时就不能push上去,所以需要修改之后再次push即可。

当然,还有个最简单的办法,右键commit的记录,会直接弹出一个修改框。

image-20210707135321383

修改点击ok即可

image-20210707135348411

那就有人问了,那如果是代码检查不通过怎么办?我是需要修改代码再次commit的,那我同一个功能,就因为代码检查提交2次,日志看起来也比较冗余。看下面👇

# git rebase合并多次提交记录

因为多次重复commit,代码功能不变,但因为小问题,比如代码检查出直接使用魔幻数字

等,需要把多次commit合并为一个,或者是初始的commit记录。

假如此时有3次commit记录(未push)

image-20210707113956268

使用rebase选中3次commit记录点击 Squash

image-20210707114242352

image-20210707114454976

再看提交记录,发现合为了一个commit记录,然后再push代码就可以了

image-20210707114543124

注意:不要去rebase别人的代码

# cherry-pick获取指定的commit

在多分支代码版本的情况下,经常遇到一个分支的代码转移到另外一个分支。常见的就是2个版本,一个开发版dev,和一个定版master(或者release),作为开发者,必定是在dev分支上开发新功能并且测试通过之后才会合并得到master分支上去,这就涉及到如何合并过去,因为这期间可能有其他人也提交了代码,如果用merge会把一个分支的所有代码变动都提交上去,大概离会产生冲突,那我自己合自己的代码就行了。

假如我在dev开发了一个功能,此时我在dev分支上,在IDEA走下角可以看到

image-20210707115816853

在代码测试通过之后需要上线,此时需要把代码更新到定版,即dev--->master

首先我们可以在IDEA上切换到master分支

image-20210707134656332

此时可以看到master分支也有commit记录,并且代码也过来了,然后再push上去就可以了

image-20210707134917671

# git stash临时保存和回复修改

当正在dev分支上开发某个项目,这时项目中出现一个bug,需要紧急修复,但是正在开发的内容只完成一半,还不想提交,这时可以用git stash命令将修改的内容保存至堆栈区,然后顺利切换到hotfix分支进行bug修复,修复完成后,再次切回到dev分支,从堆栈中恢复(UnStash)刚刚保存的内容。

还有就是在分支之间切换过程中,本应该在dev分支开发的内容,却在master上进行了开发,需要重新切回到dev分支上进行开发,可以用git stash将内容保存至堆栈中,切回到dev分支后,再次恢复内容即可。

假如我现在因为新功能新增了几个class类或者修改了文件,但是本来要在dev分支开发的,结果却在master分支开发了,当我想切换回dev分支的时候确报错了。

image-20210707140605858

此时我们只需要stash,把本地改动保存起来即可。

image-20210707140656829

然后再切换到dev分支,点击UnStash

image-20210707140923669

应用即可

image-20210707141034991

stash还可以用来解决冲突,一般来说,每天上班的第一件事就是pull代码,但有的时候忘记了,直接开始开发,但是别人有commit代码,也就是说相当于你本地的代码是落后版本的,当你写完代码再去pull发现可能会有冲突,文件要是过多,修改的也多不可能去一个个的ctrl+z,所以就可以暂存本地,保持代码的干净,在去pull,然后再回复即可。

# 总结

Git现在基本上是必会的知识点,如果记不住命令,那就可以使用工具,不只是IDEA,还有很多的git GUI可以使用,如TortoiseGit,SourceTree,GitHub for Desktop等,但不管什么工具,主要在于多用,熟能生巧。

# 参考