idea如何集成git可参考:idea集成git的实战指南(图文并茂)
idea常见问题解决方案可参考:IDEA常见问题解决方案及使用技巧
本文主要讲解idea中git操作的常见问题及使用技巧。
1、smart checkout和force checkout
如果使用git进行代码版本管理,每当我们切换分支时,idea常常会出现弹框,让我们选择smart checkout和force checkout,这是因为我们在前一个分支修改了代码,但没有commit。那这2个选项有什么区别呢?
-
smart checkout选项:会把冲突的这部分内容带到目的分支(如果你没有点进窗口的那些文件处理冲突的话)
-
force checkout选项:不会把冲突的这部分内容带到目的分支,如果直接 force checkout 会丢失当前分支的未提交的改动!就算你再切换回来该分支也找不到了,所以一定要慎重哦。
正确操作: 可以先手动stash在本地,这样本地工作区就被暂存起来了,等在另外一个分支干完活,回来之后再unstash回来。
- 切换分支之前,在项目上点鼠标右键选择 Git --> Stash Changes 保存该分支下的改动。
- 切换回来后,Git --> Unstash Changes 恢复之前的改动。
2、将当前分支的部分代码合并到目标分支
开发代码在develop分⽀,现在要将部分代码合到 feature 分⽀。
- ⾸先,在idea右下⾓点击分支名,在展开的列表中选中要切换的分支 feature,点左键选择 checkout,切换到 feature 分⽀。
- 点击右下⾓的 feature,在展开的列表中找到 Local Branches,⿏标左键选中 develop 分⽀,在弹出的列表中,选择 compare with feature,表示将 develop 分支和 feature 分支进行比较。
- 选择要合并的⽂件,右键点击展开菜单,可以选择compare功能进行比较,也可以通过 Cherry-Pick将选中文件的内容拉到当前分支重新进行commit。按此方式依次处理需要合并的文件。
- 这样就把代码合并到 feature 分⽀的本地仓库了,然后再进⾏commit,push操作就把代码提交到 feature 分⽀的远程仓库了。
也可以直接在git的log日志中双击选择源分支,找到对应的提交记录,在需要合并的文件上右键,选择 Cherry-Pick,这样就将选中文件的内容拉到当前分支了。
Cherry-Pick的使用场景:在某个分支提交了公共功能的代码,其他分支也需要,但是不能够把分支进行合并。
Cherry-Pick的作用:假设当前所在分支为B,可以在Version Control的Log中选择在A分支单个commit或者多个commit的内容,会将选中的内容拉到B分支重新进行commit,之后记得push上去,就完成了公共功能代码的拉取。
3、git stash暂存代码
git stash 命令的作用就是将目前还不想提交的但是已经修改的内容进行保存至堆栈中,后续可以在某个分支上恢复出堆栈中的内容;git stash 作用的范围包括工作区和暂存区中的内容,没有提交的内容都会保存至堆栈中。
使用场景:假如线上突然出现 bug,我们需要先切换到 master 分支,但当前分支的代码没有提交,直接切换分支,会将当前分支的新增的代码也会增加到 master 分支,而代码此时又不能commit ,这时候可以使用 git stash。
3.1 使用 git stash 暂存代码
使用 git stash 暂存代码,会把暂存区和工作区的改动保存起来。
在idea中,项目上鼠标右键选择 git -> stash Changes…
点击 stash Changes…,弹窗。
添加备注信息,选择 CREATE STASH。当前工作区内的代码被恢复成了未修改之前的样子;这时候我们就可以切换到其他分支了。
3.2 代码暂存还原
当我们在其他分支干完活后,再切换回来当前分支,这时候需要将暂存的代码恢复回来。在idea中,项目上鼠标右键选择 git -> Unstash Changes…
点击 Unstash Changes…,弹窗。
选择之前保存的内容,同时勾选 Pop stash(还原完成后,会自动删除这个 stash,不勾选则不会删除这个 stash,具体选择看情况),点击 Pop Stash 按钮,工作区之前写的代码就会恢复回来。
4、git merge合并操作
4.1 远程与本地分支合并
A分支的代码合并到B分支上:
- 切换到本地B分支。
- 选中远程A分支,merge into current。
- 通过上述步骤后,会将远端A的代码合并到本地的B分支上。
- 如果有冲突,会在本地显示,自己解决冲突后,提交到B远端分支。
- 检查无错误后,push到远端B分支上。完成合并。
4.2 远程分支合并
如何将 “远程swagger分支” 合并到 “远程 master分支” 上,大概流程如下:
- 首先将 “本地swagger分支” 上的更改 PUSH到 “远程的 swagger分支” 上。
- 再切换当前分支,将 “本地swagger分支” 切换到 “本地master分支” 上。
- 将 “远程swagger分支” Merge合并到 “本地master分支” 上。
- 在 “本地master分支” 分支上测试无误,将 “本地master分支” PUSH到 “远程mester分支” 上。
5、IDEA遇到 pull 冲突的几种解决方法
关于commit和pull的先后顺序分2类,这2种情况都遇到过代码冲突:
- pull -> commit -> push
- commit -> pull -> push
5.1 忽略本地修改,强制拉取远程到本地
如果有冲突的是项目中的文档目录,看的时候可能多了些标注,现在远程文档更新,本地的版本已无用,可以忽略本地修改强拉。
git fetch --all
git reset --hard origin/dev
git pull
5.2 未commit先pull的处理
未commit先pull,视本地修改量选择revert或stash。
场景:同事有新提交,我没有pull -> 修改了文件 -> pull -> 提示有冲突。
5.2.1 本地修改量小
如果本地修改量小,例如只修改了一行,可以按照以下流程:
revert(把自己的代码取消) -> 重新pull -> 在最新代码上修改[pull确认最新] -> commit&push
5.2.2 本地修改量大,冲突较多
本地修改量大,冲突较多时,有两种处理方式:
方式1: stash save(把自己的代码隐藏存起来) -> 重新pull -> stash pop(把存起来的隐藏的代码取回来 ) -> 代码文件会显示冲突 -> 右键选择edit conficts,解决后点击编辑页面的 mark as resolved-> commit&push
方式2: stash save(把自己的代码隐藏存起来) -> 重新pull -> stash pop(把存起来的隐藏的代码取回来 ) -> 代码文件会显示冲突 -> 右键选择resolve conflict -> 打开文件解决冲突 ->commit&push
5.2.3 采取直接merge的方法
commit后pull显示冲突 -> 手动merge解决冲突 -> 重新commit -> push
5.3 已commit未push的的处理
已commit未push,视本地修改量选择reset或直接merge。
场景:同事有新提交,我没有pull -> 修改了文件 -> commit -> pull -> 提示有冲突。
5.3.1 本地修改量小
本地修改量小,直接回退到未提交的版本(可选择是否保存本地修改),可以按照以下流程:
reset(回退到未修改之前,选hard模式,把自己的更改取消) -> 重新pull -> 在最新代码上修改[pull确认最新] -> commit&push
5.3.2 修改量大,merge
本地修改量大,直接merge,再提交(目前常用)。
commit后pull显示冲突 -> 手动merge解决冲突 -> 重新commit -> push
6、git merge 和 git rebase的区别
6.1 git rebase 的使用
rebase 翻译为变基,他的作用和 merge 很相似,用于把一个分支的修改合并到当前分支上。变基实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。
- Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。
下图介绍了经过 rebase 前后提交历史的变化情况。
现在我们来用一个例子来解释一下上面的过程。
假设我们现在有2条分支,一个为 master ,一个为 feature/1,他们都基于初始的一个提交add readme进行检出分支,之后,master分支增加了3.js,和4.js的文件,分别进行了2次提交,feature/1也增加了1.js和2.js的文件,分别对应以下2条提交记录。
master 分支如下图:
feature/1分支如下图:
结合起来看是这样的:
此时,切换到 feature/1 分支下,执行 git rebase master ,成功之后,通过 log 查看记录。如下图所示:可以看到先是逐个应用了 mater 分支的更改,然后以 master 分支最后的提交作为基点,再逐个应用 feature/1的每个更改。
所以,我们的提交记录就会非常清晰,没有分叉,上面演示的是比较顺利的情况,但是大部分情况下,rebase 的过程中会产生冲突的,此时,就需要手动解决冲突,然后使用git add 、git rebase --continue的方式来处理冲突,完成 rebase,如果不想要某次 rebase 的结果,那么需要使用 git rebase --skip来跳过这次 rebase。
6.2 git merge 和 git rebase 的区别
不同于 git rebase的是,git merge 在不是 fast-forward(快速合并)的情况下,会产生一条额外的合并记录,类似Merge branch xxx into xxx的一条提交信息。
- 在解决冲突的时候,用 merge 只需要解决一次冲突即可,简单粗暴,而用 rebase 的时候 ,需要一次又一次的解决冲突。
6.3 git rebase 交互模式
在开发中,常会遇到在一个分支上产生了很多的无效的提交,这种情况下使用 rebase 的交互式模式可以把已经发生的多次提交压缩成一次提交,得到了一个干净的提交历史,例如某个分支的提交历史情况如下:
进入交互式模式的方式是执行:
git rebase -i <base-commit>
参数base-commit就是指明操作的基点提交对象,基于这个基点进行 rebase 的操作,对于上述提交历史的例子,我们要把最后的一个提交对象(ac18084)之前的提交压缩成一次提交,我们需要执行的命令格式是:
git rebase -i ac18084
此时会进入一个 vim 的交互式页面,编辑器列出的信息像下列这样。
想要合并这一堆更改,我们要使用 squash 策略进行合并,即把当前的 commit 和它的上一个 commit 内容进行合并, 大概可以表示为下面这样。
pick ... ...
s ... ...
s ... ...
s ... ...
修改文件后 按下:然后wq保存退出,此时又会弹出一个编辑页面,这个页面是用来编辑提交的信息,修改为feat: 更正,最后保存一下,接着使用git branch查看提交的 commit 信息,rebase 后的提交记录如下图所示,是不是清爽了很多?rebase 操作可以让我们的提交历史变得更加清晰。
特别注意,只能在自己使用的 feature 分支上进行 rebase 操作,不允许在集成分支上进行 rebase,因为这种操作会修改集成分支的历史记录。
评论区