如何提交PR来参与开源项目

 

本文主要是转载自这里,做一个备份。如有侵权,请联系我删除。

一、概述

二、为什么要参与开源项目

三、为什么我想介绍如何 PR

四、我想参与开源项目,怎么开始?

五、我要提交 PR,怎么上手?

第一步:Fork 项目

第二步:克隆项目仓库到本地

注意是clone你自己的fork仓库,而不是原仓库。

git clone <your-fork-repo-url>

# 设置上游仓库
git remote add upstream <original-repo-url>
# 设置永不push到上游仓库
git remote set-url --push upstream no_push

设置完后,就可以看到本地的remote仓库有两个了:

$ git remote -v

>>>
origin <your-fork-repo-url> (fetch)
origin <your-fork-repo-url> (push)
upstream <original-repo-url> (fetch)
upstream no_push (push)

记住啰,你本地的代码变更永远只提交到 origin,然后通过 origin 提交 Pull Request 到 upstream。

第三步:更新本地分支代码并创建新分支

每次开发前,记得更新本地代码,避免冲突。

# 更新本地代码
git fetch upstream
git checkout main
git rebase upstream/main

# 创建新分支
git checkout -b <new-branch-name>

第四步:写代码

第五步:Commit 和 Push

第六步:开一个 PR

push 完代码后,你会在github上看到一个黄色的提示里面有按钮 Compare & pull request 点击它,然后填写 PR 的标题和描述,最后提交 PR。

或者切换到刚才开发的分支,点击 Contribute -> Open pull request

第七步:PR 合入

如果你的 PR 很完美,毫无争议,那么过不了太长时间,项目管理员会直接合入你的 PR,那么你这个 PR 的生命周期也就到此结束了。

但是,没错,这里有个“但是”,但是往往第一次 PR 不会那么顺利,我们接下来就详细介绍一下可能经常遇到的一些问题和对应的解决办法。

六、我提交了一个 PR,然后遇到了问题 A,B,C,D,E,F,G,…😭

6.1、Reviewers 提了一些修改意见,我如何更新 PR?

很多时候,我们提交了一个 PR 后,还需要继续追加 commit,比如提交后发现代码还有点问题,想再改改,或者 reviewers 提了一些修改意见,我们需要更新代码。

一般我们遵守一个约定:

  1. 在 review 开始之前,更新代码尽量不引入新的 commits 记录,也就是能合并就合并,保证 commits 记录清晰且有意义;
  2. 在 review 开始之后,针对 reviewers 的修改意见所产生的新 commit,可以不向前合并,这样能够让二次 review 工作更有针对性。

不过不同社区要求不一样,可能有的开源项目会要求一个 PR 里只能包含一个 commit,大家根据实际场景灵活判断即可。

说回如何更新 PR,我们只需要在本地继续修改代码,然后通过和第一个 commit 一样的步骤,执行这几个命令:

git add <file>
git commit -s -m "some description here"
git push origin feat-xxx

这时候别看 push 的是 origin 的 feat-xxx 分支,其实 GitHub 会帮你把新增的 commits 全部追加到一个未合入 PR 里去。没错,你只管不断 push,PR 会自动更新。

6.2、Commits 太多或者记录混乱,如何合并 Commits?

有时候我们提交 PR 的时候,可能会有很多次 commit,或者 commit 记录混乱,这时候我们可以通过 git rebase 来合并 commits。

# 选择要合并的 commit,假设为2个
git rebase -i HEAD~2

执行这个命令会进入一个编辑页面,默认是 vim 编辑模式,内容大致如下:

pick 3114c0f docs: just for test
pick 9b7d63b docs: just for test

# Rebase d640931..9b7d63b onto d640931 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.

这里有几个命令:

  • pick:保留这个 commit
  • reword:保留这个 commit,但是可以修改 commit message
  • edit:保留这个 commit,但是可以修改 commit message,或者修改代码
  • squash:合并这个 commit 到上一个 commit, 保留这个 commit 的 commit message
  • fixup:合并这个 commit 到上一个 commit,但是不保留这个 commit 的 commit message
  • drop:删除这个 commit
并且回放的顺序是从上到下

,所以如果你想要合并两个 commit,可以将第二个 commit 的命令改为 squash,然后保存退出:

pick 3114c0f docs: just for test
squash 9b7d63b docs: just for test

保存退出后,会进入一个新的编辑页面,这时候可以修改 commit message,然后保存退出即可。

6.3、PR 产生了冲突,如何解决?

6.3.1、在线解决冲突

6.3.2、本地解决冲突

# 更新本地代码
git fetch upstream
git checkout main
git rebase upstream/main

# 切换到开发分支
git checkout feat-xxx
git rebase main

rebase 的过程中可能会产生冲突,类似如下的日志:

First, rewinding head to replay your work on top of it...
Applying: docs: conflict test 1
Using index info to reconstruct a base tree...
M       README.md
Falling back to patching base and 3-way merge...
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: Failed to merge in the changes.
Patch failed at 0001 docs: conflict test 1
The copy of the patch that failed is found in: .git/rebase-apply/patch

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

这时候我们需要手动解决冲突,并且使用 git add 命令来标记冲突已经解决,最后执行 git rebase --continue 来继续 rebase 过程。

推送变更到远程仓库:

git push -f origin feat-xxx

6.4、CI 检查不过:commit message 相关问题如何修复?

前面我们提到过 commit message 的规范,但是第一次提交 PR 的时候还是很容易出错,比如feat: xxx其实能通过 ci 检查,但是feat: Xxx就不行了。假设现在我们不小心提交了一个 PR,但是里面 commit 的 message 不规范,这时候怎么修改呢?

太简单了,直接执行:git commit --amend,然后修改 commit message 即可,最后再 git push -f origin feat-xxx

6.5、CI 检查不过:DCO(sign) 问题如何修复?

相当多的开源项目会要求所有合入的 commits 都包含一行类似这样的记录:

Signed-off-by: <Your Name> <Your Email>

这行信息相当于是对应 commit 的作者签名。要添加这样一行签名当然很简单,我们直接在git commit命令后面加一个-s参数就可以了,比如git commit -s -m “some description here”提交的 commit 就会带上你的签名。

如果你提交了一个 PR,但是 CI 检查不过,提示你没有签名,那么你可以通过 git commit --amend -s 来添加签名,然后再 git push -f origin feat-xxx

七、最后

这是原作者贴的一些链接,这里一并贴上,方便查看: