Git使用不当导致代码丢失的N种场景

简介: 背景git作为目前使用最广泛的分布式版本控制软件,集团内基本上所有开发同学都使用它来做代码管理。一个最典型的使用场景,是一个git仓库存在一个master主干分支,多个需求基于master拉自己的开发分支,然后在发布日时,新建一个release分支,然后原先并行的几个开发分支merge到release分支上,最后基于该分支发布上线,上线后release再merge到master主干上,一次发布完成

背景

git作为目前使用最广泛的分布式版本控制软件,集团内基本上所有开发同学都使用它来做代码管理。

一个最典型的使用场景,是一个git仓库存在一个master主干分支,多个需求基于master拉自己的开发分支,然后在发布日时,新建一个release分支,然后原先并行的几个开发分支merge到release分支上,最后基于该分支发布上线,上线后release再merge到master主干上,一次发布完成。

但由于每位开发同学对git的掌握程度不一,可能对git使用不当,导致某次提交丢失了部分曾经已经在git仓库的代码,最后该分支发布上线后造成故障。并且这种丢代码情况在代码改动量本身就很多的时候,往往比较隐秘,并且如果丢失的代码不在本次变更的范围内,测试回归时可能也就不会涉及到,结果就是只有在线上真正发生故障时才意识到问题。

所以这里梳理了一下有哪些不当使用git可能会导致代码丢失的场景,防止踩坑。如果有遗漏的其它场景,也请留言补充。

场景梳理

1)强制Push

触发场景

在多人并行开发同一个分支时,某人写完代码,git push,如果此时该分支已经也被别人改过且push过了,则会提示这个信息:

此时不熟悉git的同学,可能会通过加 -f 参数,强制push:

git push -f origin branchA

或者在IDEA里面,选择了Force Push:

这样之前别人已经push的代码,就被丢掉了(因为将会以你本地非最新的代码为准)。

正确操作

push代码遇到本地不是最新时,不要强制push!务必先git pull拉最新代码,如果遇到冲突则解决冲突,解决完再git push。

2)Merge时错误处理冲突

触发场景

在自己的分支上开发,然后需要将其它分支(例如master)的代码merge过来时,遇到了代码冲突,此时处理完冲突后,push代码,如果没有发生冲突的其它分支文件,没有同时也勾选push的话,则代码也会丢失。

例如下面的例子:

  • 在dev分支上修改了Tester.java文件和其它内容,merge master提示其中Tester.java有冲突;

  • 处理完Tester.java的冲突后,在IDEA里面准备push代码,此时展现了有修改的文件列表(如下图)。此时列表内不仅有自己在dev分支里面修改的代码,还有被合并过来的分支(master)修改的文件(图中ClassA和ClassB)。

  • 此时正确操作,是必须要把ClassA和ClassB 这些master上修改的文件内容,也勾选上。如果未勾选,而只勾了自己在dev上修改的文件,再去push,则此时master上这些修改的代码会丢失。

正确操作

merge后遇到冲突,解决完冲突后,不要部分提交!push时务必把所有修改文件都勾选,再push。

这个对于IDEA这种图形化界面容易犯错。对于命令行,其实merge冲突后,未冲突的文件,是默认已经放入暂存区了,所以git push时这些未冲突文件就会一起被正确push上去。

3)错误使用Merge

触发场景

有的时候可能遇到这种情况:自己的开发分支,需要将其他开发分支上的改动merge过来,但是只需要其中部分功能,此时如果使用git merge的话,就可能会存在问题。

例如下面这个例子:

主干Master上有两个文件:fileA和fileB。其中fileA的内容是AAA,fileB的内容是BBB。最新的CommitId是M1;

  1. 张三基于Master,拉了一个分支:Dev1,其最新CommitId是G1,其中fileA和fileB的内容没有变更;
  2. 李四也基于Master,拉了一个分支:Dev2,其最新CommitId是P1,其中fileA和fileB的内容也没有变更;
  3. Dev1分支,做了一次commit,ID是G2,其中把fileA和fileB的内容都做了变更(fileA变成AAA1,fileB变成BBB1);
  4. Dev2分支,希望能将Dev1的代码Merge过来,但只想要fileB的改动,而暂时不需要fileA的改动,于是他执行git merge Dev1,然后rollback了其中fileA的变化,提交,commitId为P2;
  5. Dev1分支发布,代码被合并到了Master,此时Master的CommitId为M2,并且fileA和fileB内容都以Dev1的G2为准(即fileA是AAA1,fileB是BBB1);
  6. Dev2继续开发,然后等Dev2自己也准备要发布了,于是他执行git merge master合并最新主干代码(CommitId是P3)。此时他以为fileA的内容会被改成AAA1,因为Master上就是AAA1,但其实因为之前merge Dev1时,fileA被自己人工改过了,所以会以自己版本为准,即实际内容还是AAA。此时Dev2的代码已经有问题了;
  7. 最后Dev2分支发布,代码被合并到了Master,其CommitID是M2,其中fileA的内容也在主干里面被丢失了,导致故障。

正确操作

出问题的点在Dev2的Commit P2。对于这种希望将其它分支上的部分改动(例如某几个commit)移动到自己分支上的情况,强烈建议是不要使用git merge,而是使用cherry-pick将这几个commit合并过来

预防策略

目前能做的更多还是在机制上做兜底。典型的就是在发布前,发布分支和master做diff。在这个环节里,不再关心需求代码写的怎么样(这个是之前CR时做的),而是只关心Diff出来的内容,是否是我们要的,特别是diff出来被删除/修改的逻辑,确认是否是发布的业务需求逻辑。如果不是,或者没人知道这部分逻辑是谁改的为啥改,那就有问题,可能是之前Merge时丢代码了。

相关文章
|
7小时前
|
安全 开发工具 数据安全/隐私保护
《Git 简易速速上手小册》第8章:保护你的代码(2024 最新版)
《Git 简易速速上手小册》第8章:保护你的代码(2024 最新版)
32 1
|
7小时前
|
开发工具 git C++
【git 实用指南】git下载、拉取 代码
【git 实用指南】git下载、拉取 代码
270 2
|
7小时前
|
存储 前端开发 开发工具
Git Hooks实战:提交前检查修改文件中是否包含调试代码
Git Hooks实战:提交前检查修改文件中是否包含调试代码
51 0
|
7小时前
|
Linux 网络安全 开发工具
Git拉取代码的完整示例操作
Git拉取代码的完整示例操作
81 0
|
7小时前
|
数据可视化 项目管理 开发工具
使用SourceTree可视化更新git代码
使用SourceTree可视化更新git代码
|
7小时前
|
开发工具 git
【git 实用指南】git 上传代码
【git 实用指南】git 上传代码
38 2
|
7小时前
|
人工智能 运维 Linux
一文了解IntelliJ IDEA如何使用git上传代码到GitHub(附常见问题解决方案)
一文了解IntelliJ IDEA如何使用git上传代码到GitHub(附常见问题解决方案)
114 0
|
7小时前
|
开发工具 git
Git -- 代码上传错误 error: failed to push some refs to ‘git@gitee.com:JMFive/uni-shop2.git‘
Git -- 代码上传错误 error: failed to push some refs to ‘git@gitee.com:JMFive/uni-shop2.git‘
|
7小时前
|
敏捷开发 测试技术 持续交付
云效产品使用常见问题之直接git clone 输入账密可以拉代码,但是云效平台上不行如何解决
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
7小时前
|
开发工具 git
git 拉取代码仓库代码报错(合并错误 refusing to merge unrelated histories)
git 拉取代码仓库代码报错(合并错误 refusing to merge unrelated histories)
26 0