如何提交一个优雅的pr
如何提交一个优雅的pr
暑假参加了2025OSPP的活动,有幸参与了apache/fory的开源项目的开发活动,也因此在实践中学习到了如何在GitHub上参与一个开源项目
在GitHub上你想要给开源项目提交你的代码,就需要提交pr,也就是所谓的 pull request。
1. fork 仓库
首先需要将这个项目fork到你的主页,注意:后续所有的操作都是基于你仓库内的这个派生的代码库展开的。
拉取的项目的main分支不要动,因为我们要靠这个分支与原仓库做同步。
从优雅简洁的角度来看,每次你想要提交一个pr,都请先在你的这个派生的代码库中新建一个分支:
分支名最好和本次提交的主题相关,这样方便分辨哪个分支是干什么的,比如我这次需要提交一个新特性:让go语言的代码生成部分支持slice,那么我就可以新建一个叫做feat-slice的分支。
GitHub里的派生的代码库不会默认进行同步,如果你派生的代码库落后于最新的原始仓库,那么这里就会有提示,点击 Sync fork 按钮即可 Update branch。(注意我们每次只要更新main分支就好,保持main分支是最新的就行)
2. 本地开发
本地开发始终记住:永远不要在main分支上修改提交commit!!!每次开发都请和远程派生的代码库一样,各自新建一个分支来开发,pr提交合并结束记得删除本地相关分支和派生代码库的相关分支。
这里的好处是非常非常大的,也是我本地踩过很多次坑发现的:因为GitHub提交pr的特点是,pr中可能有10个commit,最终如果owner approve 你的合并,那也只会将这个pr的内容作为一个整体commit提交上去。所以如果你在main分支上直接开发,就会出现你的本地commit多于远程代码库的main分支,这显然是有问题的,两边git历史对不上。所以这就是为什么我说的永远不要在main分支上直接修改提交,新建新的分支开发完提交pr之后就可以删掉了,然后本地main分支重新git pull就可以保持完全一致!
首先先查看git历史:
|
|
然后切换到main分支:
|
|
新建并切换分支:
|
|
下面就可以在这个新的分支上进行愉快的开发了!
3. 创建合并请求
只要你将本地的修改push到你远程的派生代码库的相关分支上,回到线上派生项目的工作区,会看到新分支和修改的合并提交信息,点击Compare & pull request:
选择你想并入的原项目分支,标题和描述信息。如果有对应的 issue,就通过键入 # 添加(Github 会自动展示 issues 列表)
然后点击Create pull request即可创建合并请求成功,之后就等待cr就行。
4. 根据评论修改你的代码
你提交的pr是需要 code owner 进行 review 的,他们认为你的代码有问题就会在cr的时候提出评论,此时你需要根据评论去修改你本地的内容,然后再提交到之前的那个远程分支上就可以自动更新pr中的commit了。
但是很多情况下会有很复杂的情况,比如给你的评论很复杂改了几天,回头发现有人先提交了一些新的pr并且合入了怎么办?
我们可以把这种情况抽象为下面的模型:
- 初始情况:
- 远程
main: Afeat-slice: A
- 本地
feat_slice: A
- 你在本地提交了 C
- 本地
feat_slice: A–C - 然后你 push 到远程
feat-slice:main: Afeat-slice: A–C
- 远程 main 更新为 A–B
- 远程:
main: A–Bfeat-slice: A–C
- 本地:
feat_slice: A–C (还没git pull --rebase)
- 本地
git pull --rebase到 main
执行:git pull --rebase
结果:
- 本地
feat_slice: A–B–C (C 被“挪”到 B 后面) - 远程还是:
main: A–Bfeat-slice: A–C
- 此时
git push origin master:feat_slice到远程feat-slice
Git 会检查:
- 远程
feat-slice目前是 A–C - 你要推的是 A–B–C
👉 这两条历史分叉了:
- 远程的 C 在 A 后直接接,
- 本地的 C 在 A–B 后接。
所以,Git 默认会认为这是「非快进 (non-fast-forward) 更新」,直接 push 会报错:
|
|
- 强制推送
怎么办?
如果你确认要让远程 feat-slice 变成 A–B–C,需要强制推送:
|
|
这样远程 feat-slice 就会被改写成 A–B–C。pr上也会出现force-pushed的相关显示:
5. 删除你的分支
请记住:每次提交的pr合并进去,都请删除本地和派生代码库的相关分支,然后在本地的main分支重新git pull即可,如果还需要继续开发,请回到 步骤2. 本地开发