2022年,继续做开源的朋友-如何专业的同步最新代码

【本文正在参与优质创作者激励】
作为《2022年,继续做开源的朋友》的续篇,本文做些补充,专门来说说贡献代码时---如何正确的同步最新代码。

1、 先看看问题是什么

先看下XTS ACTS代码仓的一次提交,显示这一次commit提交,修改了400多个文件,修改了27多万行,删除了4万行。OpenHarmony社区里一次性提交大量的代码,情况也比较常见,通常是新特性从内源转为开源,三方库初始化和版本升级等等。这次的提交又是什么情况呢?我们使用TortoiseGit查看下提交历史日志,图中大的红框里,包含相关的3次commit和一次PR代码合入引起的一个commit。

xts_acts_commit.png

再去看看对应的PR,从网页上看到的提交信息,确实是包含3次提交,和TortoiseGit工具上看到的git log信息是一致的。

xts_acts_pr.png

怪异的是,我们再看看这个PR改动的文件,其实是就2个文件改动,代码行改动也就3行,如下图。Git log里查询出来的几十万行的代码修改量是如何产生的呢? 为什么小小的修改3行代码,会需要三次commit?这样不太好,给git log提交历史信息里带来了很多的冗余信息。

xts_acts_pr_files.png

2、问题是如何产生的

提交消息git message:Merge branch 'master' of .... 已经显示显示是合并Merge,另外如下图所示,该提交有2个Parents,说明是两个父级提交进行合并产生的。

xts_acts_commit_parents.png
协作开发代码,一个是开发者fork的分支,一个是要合入的master分支,在fork分支向master分支提交代码申请合入时,两个分支有差异是非常正常的。如果差异的是不同的文件,或者是同一个文件的不同的地方,git能识别出差异,能自动合并,就不会产生这样的问题。如果改动了同一个文件的同一行,存在冲突,无法自动合并,就需要开发者介入修复冲突,然后再提交代码。

现在我们复现下,上述问题是如何产生的。

2.1 准备模拟代码仓环境

我准备了2个gitee账户,模拟社区贡献代码。rtos_lover创建了代码仓https://gitee.com/rtos_lover/demo_repo,初始时只有readme文件。然后rtos_yuan 对代码仓fork到开发者分支https://gitee.com/rtos_yuan/demo_repo。如下:

demo_repos.png

然后,rtos_yuan改动README.md文件的第一行,然后提交PR进行合入,现在PR状态是正常的,是可以合入的。等待仓库owner rtos_lover审核合入。

2.2 制造代码冲突

rtos_love没有处理上述的PR合入。可能同时提交的PR比较多,合入了其他PR,正好导致修改了同一文件的同一行,导致冲突。我们模拟下这种情况,以rtos_lover的账户改动README.md的第一行,然后再随便合入一个其他文件。我们再去看提交的PR已经显示存在冲突,无法合并了。

demo_conflict.png

2.3 修复冲突进行合入

rtos_yuan代码提交者需要处理修复冲突,然后再合入代码。fork过来的代码仓已经不够新,需要从合入目标master代码仓中更新,执行如下命令:

git remote -v
git remote add remote_origin --mirror=fetch https://gitee.com/rtos_lover/demo_repo.git
git pull remote_origin master
git pull

可以看到合并的时候,出现了冲突:CONFLICT (content): Merge conflict in README.md。

demo_conflict_show.png

编辑冲突的文件,添加到暂存区,然后git commit提交,并推送到fork的代码仓。

vi README.md
git add README.md
git commit
git push origin master

然后再去看PR,可以看到冲突已经被修复了。也额外增加了一条提交记录显示:Merge branch 'master' of https://gitee.com/rtos_yuan/demo_repo/ ,如下图。到现在,我们已经复现了Merge branch 'master' of ...。

demo_conflict_merge.png

2.4 如何避免产生额外的提交记录

为了解决一个小问题,额外增加一条git提交记录,是非常不专业的。额外增加的提交记录,会给后期查看之前的更改记录时带来很大的不方便。那出现冲突时,应该怎么解决呢?在文章https://ost.51cto.com/posts/10262中,已经提供了解决方案,那就是使用rebase操作,可以参考文章的学会解决冲突部分。命令中的git pull -r remote_origin master的-r就是指的rebase方式同步代码。

git remote -v
git remote add remote_origin --mirror=fetch https://gitee.com/openharmony/kernel_liteos_m.git
git pull -r remote_origin master
vi README.md
git add README.md
git rebase --continue
git commit --amend
git push origin master -f

3、更多知识Merge和Rebase

最后,建议继续深入掌握下git的merge和rebase操作。假设有main分支和feature等两个分支,现在需要把main上的修改同步到feature分支,有merge合并和rebase变基两个操作。

3.1 Merge合并

为了把main分支里新增的代码应用在你的feature分支,可以使用merge操作,git graph示意图如下(图片来自参考资料Git使用Merge和Rebase)。合并操作会在提交历史上增加一个无关的提交历史。如果main分支的更新非常活跃,这种操作也可能会对feature分支的git log提交历史产生一些污染。

gitmerge.png

3.2 Rebase变基

不使用merge操作,而是使用rebase操作把feature分支的提交历史rebase到main分支的提交历史顶端,如下图(图片来自参考资料Git使用Merge和Rebase)。相对于merge操作中新建一个合并提交,rebase操作会通过为原始分支的每次提交创建全新的提交,从而重写原始分支的提交历史。详细的信息可以参考附录的参考资料。

gitrebase.png

附录-参考资料

想了解更多关于鸿蒙的内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://ost.51cto.com/#bkwz

::: hljs-center

21_9.jpg

:::