我们在日常使用Git的过程中,经常会遇到一些意想不到的情况。如果处理不当,可能会出现代码丢失的错觉。本文将围绕IDEA&Git日常开发中的一些场景,一层层为你拨开迷雾,分析常见错误及其原因,让你不再害怕代码冲突或丢失问题。为了简化问题,本文假设所有团队成员都在同一个分支上进行开发。本文更新操作是指在IDEA中点击菜单VCS-UpdateProject...。1.常用工作流程通常早上去公司打开电脑,先进行更新操作(点击IDEA菜单VCS-UpdateProject...),然后就愉快的开始coding了。编码完成后,通常会进行以下操作:更新操作创建本次提交并推送到远程分支1.1更新操作为了保证Git有一个简洁的提交历史,在提交前需要进行一次更新操作,即,点击IDEAVCS-UpdateProject...中的菜单,或者按Ctrl+T,会弹出如下窗口:在窗口左侧选择UpdateType:Merge:更新时执行合并操作。相当于执行gitfetch&&gitmerge或gitpull--no-rebase。Rebase:更新时进行rebase操作。相当于执行gitfetch&&gitrebase或gitpull--rebase。BranchDefault:在.git/config文件中指定不同分支的更新类型。在窗口右侧选择更新前工作目录(WorkingDirectory)的清理方式:UsingStash:使用gitstash来存储本地修改。UsingShelve:使用IDEA内置的Shelve功能来存储本地修改。通常选择Merge和UsingStash。点击确定后,IDEA执行步骤如下:第一步:使用gitstash存储本地修改第二步:执行gitfetch&&gitmerge拉取远程分支并合并第三步:执行gitstashpoprestorestash有些同学可能比较多习惯先创建本地提交,然后进行更新操作,这会导致Git自动生成合并提交,导致提交历史不够简洁。1.2创建本次提交更新完成后,点击IDEA中的菜单VCS-Commit...创建本次提交。1.3推送远程分支点击VCS-Git-Push...推送到远程分支。二、常见问题分析上述三个步骤中,以步骤2、3发生事故的风险最高。最常见的两种事故是冲突和文件占用。下面分别讨论一下。2.1合并远程分支冲突如果你的本地分支在执行update操作之前已经创建了commit,还没有push到远程分支,那么在步骤2中执行gitmerge的时候很可能会发生冲突,此时关闭上面的冲突窗口,版本控制工具窗口显示如下内容:原来显示分支名的窗口右下角变成了Mergingmaster,表示本地分支master当前处于合并状态。点击左侧红框内的Resolve按钮,再次调出冲突解决窗口。基于IDEA的图形界面手动解决冲突后,IDEA会自动将文件添加到暂存区(添加到暂存区即冲突解决完成),执行final即可完成冲突解决提交。2.2恢复stash冲突在更新操作的第三步执行gitstashpop恢复stash时,stash内容可能与新更新的内容冲突。恢复stash时发生的冲突与上面的合并冲突略有不同。首先,右下角的分支名称没有Merging字样。另外右下角会弹出一个小窗口提示恢复stash失败,告诉大家不用担心,所有的修改都在stash列表里,不会丢失。查看stash列表的方法是点击菜单VCS-Git-UnStashChanges...:选择列表中最上面的一项,然后点击ApplyStash,之前的修改就会回到工作目录。我们继续回到冲突问题,手动解决冲突后执行commit。如果冲突解决过程中出现误操作,可以右键DefaultChangelist-Revert...清除当前工作目录的内容,再次执行ApplyStash,然后重复冲突解决过程。2.3FileOccupancyError在执行第2步gitmerge时,可能会因为文件被占用导致执行失败。比如项目可能会引入一些jar文件。这些jar文件已由JVM在本地动态加载。如果别人更新了jar文件,push到远程分支,你更新的时候就会遇到上面的问题。关注微信公众号「web_resourcec」,回复Java获取2019最新资源。这种错误的解决方法很简单。首先释放文件的占用状态,比如终止本地JVM进程,然后再次点击VCS-Update。在第3步执行gitstashpop时,也会因为文件被占用而执行失败。比如你更新了某个jar文件,当你恢复存储时,可能会因为jar文件被占用而导致恢复失败。对于这种错误,需要先unstash文件,然后手动执行unstash操作。3.先提交还是先更新?这是一个问题!3.1先提交再更新带来的问题3.1.1冲突难处理如果先提交了,但是更新的时候发生了冲突,说明你刚刚创建的提交其实是有问题的,一般是有问题的团队沟通或分工,但不管怎样,别人已经推进了,你的投稿会被拒。即使手动解决了冲突,如果这个commit留在历史中,也会成为隐患。如果别人resetthiscommit继续工作的话,合并其他分支内容时冲突的概率会大大增加,所以最好的处理方式是先undothiscommit(reset--softHEAD~),再updateresolve冲突,最后创建一个新的提交。3.1.2错误的冲突处理方式发生冲突后,可能有同学会想到以下处理方式:清空当前工作区,调整冲突部分的代码,然后重新执行更新操作。上面的处理方式显然是行不通的,因为你调整的代码会先被IDEA存储(stash),然后在更新的第二步还是会发生冲突,而冲突发生的时候你的修改还没有恢复到存储(unstash),这使得您调整后的代码看起来已经消失了,令人困惑。3.1.3Rebase会改写提交历史。如果在IDEA的更新窗口中选择更新类型为Rebase,则相当于手动执行gitfetch&&gitrebase或gitpull--rebase命令。这样做的好处是不会产生自动合并提交,保持提交历史简洁。但是需要注意的是,rebase之后,你本地的提交会被重写。虽然提交信息相同,但是commithash发生了变化,如下图所示:执行如下Rebase命令后,执行结果为:请注意,结果中的v4和v5commit已经被重写。3.2建议提交前更新。如果事先知道会有冲突,相信你不会选择先提交代码,但是冲突是不可避免的,这需要我们养成良好的开发习惯。与其先commit再解决冲突,不如提早解决冲突再commit,这样不仅省去了一次无意义的自动mergecommit,也简化了冲突发生时的处理流程。3.3养成良好习惯为了尽可能避免冲突,建议养成以下开发习惯:编码前更新,提交前更新提交前检查是否有编译错误其他成员更新最后也是最重要的,团队分工要明确
