如何变基和更新拉取请求
###介绍
为开源项目做出贡献是一种有益的体验,因为您致力于为像您这样的最终用户提供更好的软件。 提交拉取请求后,为项目做出贡献的过程可能需要在接受之前对代码进行一些 rebase 和修改,然后对分支进行全面清理。
本教程将指导您完成向开源软件项目提交 拉取请求 后可能需要采取的一些后续步骤。
- 先决条件
本教程将引导您完成发出拉取请求后将采取的步骤,因此您应该已经安装了 Git,并且已经提出或正在考虑创建拉取请求。
截至 2020 年 11 月,GitHub 删除了基于密码的身份验证。 因此,您需要创建一个 个人访问令牌 或添加您的 SSH 公钥信息 以便通过命令行访问 GitHub 存储库。
要了解更多关于为开源项目做贡献的信息,您可以阅读这篇介绍。 要了解如何提出拉取请求,您可以阅读“如何在 GitHub 上创建拉取请求”。
- Rebase 代码和清理注释
在您为开源做贡献时,您可能会发现您的分支或拉取请求与上游代码之间存在冲突。 你的 shell 中可能会出现这样的错误:
OutputCONFLICT (content): Merge conflict in your-file.py Automatic merge failed; fix conflicts and then commit the result.
或者通过 GitHub 的网站在您的拉取请求中像这样:
如果维护人员有一段时间没有响应您的拉取请求,或者如果有很多人同时为项目做出贡献,则可能会发生这种情况。 当这种情况发生并且您仍然想合并您的拉取请求时,您将不得不解决冲突并重新设置您的代码。
rebase 允许我们通过更改它们所基于的提交来移动分支。 这样,我们可以根据主分支最近的提交重新调整我们的代码。 变基应该小心进行,并且您应该确保在整个过程中使用正确的提交并在正确的分支上工作。 我们还将使用 git reflog
命令 below 以防您出错。
正如我们在 拉取请求教程 中所做的那样,我们将进入代码目录:
cd repository
接下来,您要通过使用 git checkout
命令导航到正确的分支来确保您在正确的分支中:
git checkout new-branch
然后,运行 git fetch
获取最新的上游版本代码:
git fetch origin
获取项目的上游版本后,您可以通过压缩或改写您的提交消息来清理您的评论,以使它们更容易被项目维护者消化。 如果你没有做很多小提交,这可能没有必要。
要开始此过程,您将执行交互式变基。 交互式 rebase 可用于编辑以前的提交消息,将多个提交合并为一个,或者删除或恢复不再需要的提交。 为此,我们需要能够通过数字或引用分支基址的字符串来引用我们所做的提交。
要找出我们提交的数量,我们可以使用以下命令检查项目的提交总数:
git log
这将为您提供类似于此的输出:
Outputcommit 46f196203a16b448bf86e0473246eda1d46d1273 Author: username-2 <email-2> Date: Mon Dec 14 07:32:45 2015 -0400 Commit details commit 66e506853b0366c87f4834bb6b39d941cd034fe3 Author: username1 <email-1> Date: Fri Nov 27 20:24:45 2015 -0500 Commit details
日志显示对给定项目的存储库所做的所有提交,因此您的提交将与其他人的提交一起列出。 对于具有多个作者提交的广泛历史的项目,您需要在命令中将自己指定为作者:
git log --author=your-username
通过指定此参数,您应该能够计算您所做的提交。 如果您正在处理多个分支,则可以将 --branches[=<branch>]
添加到命令的末尾以按分支进行限制。
现在,如果您知道在要变基的分支上所做的提交次数,您可以像这样运行 git rebase
命令:
git rebase -i HEAD~x
这里,-i
指的是 rebase 是交互式的,HEAD
指的是来自主分支的最新提交。 x
将是您自最初获取分支以来对分支所做的提交次数。
但是,如果您不知道在分支上进行了多少次提交,则需要找到哪个提交是您的分支的基础,您可以通过运行以下命令来完成:
git merge-base new-branch main
此命令将返回一个称为提交哈希的长字符串,如下所示:
Output66e506853b0366c87f4834bb6b39d341cd094fe9
我们将使用此提交哈希传递给 git rebase
命令:
git rebase -i 66e506853b0366c87f4834bb6b39d341cd094fe9
对于上述任一命令,您的命令行文本编辑器将打开一个包含分支中所有提交列表的文件,您现在可以选择是压缩提交还是改写它们。
- Squash 提交
当我们压缩提交消息时,我们将几个较小的提交压缩或组合成一个较大的提交。
在每个提交之前,您会看到“pick”一词,因此如果您有两个提交,您的文件将与此类似:
GNU nano 2.0.6 文件:...用户名/存储库/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature pick 79c0e80 Here is another new feature # Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))
现在,对于文件的每一行,除了第一行之外,您应该将单词“pick”替换为单词“squash”以组合提交:
GNU nano 2.0.6 文件:...用户名/存储库/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature squash 79c0e80 Here is another new feature
此时,您可以保存并关闭文件,这将打开一个包含所有提交的所有提交消息的新文件。 您可以根据需要改写提交消息,然后保存并关闭文件。
关闭文件后,您将收到反馈:
OutputSuccessfully rebased and updated refs/heads/new-branch.
您现在通过将所有提交压缩在一起,将它们合并为一个。
- Reword 提交
当您发现一个错字,或者您意识到您没有为每个提交使用并行语言时,重新措辞提交消息非常有用。
使用 git rebase -i
命令执行上述交互式变基后,您将打开一个如下所示的文件:
GNU nano 2.0.6 文件:...用户名/存储库/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature pick 79c0e80 Here is another new feature # Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))
现在,对于您想要改写的每个提交,将单词“pick”替换为“reword”:
GNU nano 2.0.6 文件:...用户名/存储库/.git/rebase-merge/git-rebase-todo
pick a1f29a6 Adding a new feature reword 79c0e80 Adding a second new feature # Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))
保存并关闭文件后,终端编辑器中将出现一个新的文本文件,其中显示提交消息的修改措辞。 如果您想再次编辑文件,您可以在保存和关闭文件之前执行此操作。 这样做可以确保您的提交消息有用且统一。
- 完成变基
一旦您对提交的数量和相关的提交消息感到满意,您应该在项目上游代码的最新版本之上完成分支的变基。 为此,您应该从存储库的目录运行此命令:
git rebase origin/main
此时,Git 将开始将您的提交重播到最新版本的 main.js 上。 如果在这种情况下发生冲突,Git 将暂停以提示您在继续之前解决冲突。 如果没有要解决的问题,您的输出将说明以下内容:
OutputCurrent branch new-branch is up to date.
解决冲突后,您将运行:
git rebase --continue
此命令将向 Git 指示它现在可以继续重放您的提交。
如果您之前通过使用 squash
命令合并提交,则只需解决一次冲突。
- 使用强制推送更新拉取请求
执行变基后,分支的历史记录会更改,并且您将无法再使用 git push
命令,因为直接路径已被修改。
我们将不得不使用 --force
或 -f
标志来强制推送更改,通知 Git 你完全知道你在推送什么。
让我们首先通过配置确保我们的 push.default
是 simple
,这是 Git 2.0+ 中的默认值:
git config --global push.default simple
此时,我们应该通过检查我们正在处理的分支来确保我们在正确的分支上:
git checkout new-branch
OutputAlready on 'new-branch' . . .
现在我们可以执行强制推送:
git push -f
现在您应该收到更新的反馈以及这是 forced update
的消息。 您的拉取请求现已更新。
- 恢复丢失的提交
如果在某个时候你抛出了一个你真的想集成到更大项目中的提交,你应该能够使用 Git 来恢复你可能不小心丢弃的提交。
我们将使用 git reflog
命令来查找我们丢失的提交,然后从该提交创建一个新分支。
Reflog 是 reference logs 的缩写,它记录了分支的提示和其他引用在本地存储库中最后一次更新的时间。
从我们正在使用的代码存储库的本地目录中,我们将运行以下命令:
git reflog
运行此命令后,您将收到如下所示的输出:
Output46f1962 HEAD@{0}: checkout: moving from branch-1 to new-branch 9370d03 HEAD@{1}: commit: code cleanups a1f29a6 HEAD@{2}: commit: brand new feature 38f2fc2 HEAD@{3}: commit: remove testing methods . . .
您的提交消息将让您知道哪些提交是您留下的,相关字符串将位于终端窗口左侧的 HEAD@{x}
信息之前。
现在您可以获取该信息并从相关提交创建一个新分支:
git checkout -b new-new-branch a1f29a6
在上面的示例中,我们从上面显示的第三个提交创建了一个新分支,该分支推出了“全新功能”,由字符串 a1f29a6
表示。
根据您需要从此处执行的操作,您可以按照 本教程关于 pull requests 中设置分支的步骤操作,或返回当前教程 的 顶部工作通过重新设置新分支。
注意:如果您最近运行了 git gc
命令来清理不必要的文件并优化本地存储库,您可能无法恢复丢失的提交。
- 在代码审查中可以期待什么
当您提交拉取请求时,您正在与一个更大的项目进行对话。 提交拉取请求是在邀请其他人谈论你的工作,就像你自己在谈论和参与一个更大的项目一样。 为了让您进行成功的对话,重要的是能够通过提交消息传达 为什么 您提出拉取请求,因此最好尽可能准确和清晰。
根据项目的不同,拉取请求审查可能会冗长而详细。 最好把这个过程看作是一种学习体验,也是你改进代码并使拉取请求更好、更符合软件项目需求的好方法。 审查应该允许您通过维护者的建议和指导自己进行更改。
拉取请求将记录审阅者的注释以及您一起进行的任何更新和讨论。 在接受拉取请求之前,您可能需要在整个过程中进行几次额外的提交。 这是完全正常的,并且为您作为团队的一部分进行修订提供了一个很好的机会。
您的拉取请求将继续通过 Git 维护,并在整个过程中自动更新,只要您不断将提交添加到同一分支并将其推送到您的分支。
尽管您将代码放到更大的世界中供您的同行审查,但您永远不应该觉得审查是个人化的,因此请务必阅读相关的 CONTRIBUTION.md
文件或行为准则。 确保您的提交与项目指定的指导方针保持一致很重要,但如果您开始感到不舒服,您正在从事的项目可能不值得您做出贡献。 开源社区中有许多欢迎空间,虽然您可以期望您的代码会以批判的眼光看待,但您收到的所有反馈都应该是专业和有礼貌的。
- Pull 请求接受和删除您的分支
如果您的拉取请求已被接受,则您已成功为开源软件项目做出贡献!
此时,您需要通过本地存储库将所做的更改拉回 fork。 这是您在完成 同步您的分叉 的过程时已经完成的工作。 您可以在终端窗口中使用以下命令执行此操作:
git checkout main git pull --rebase origin main git push -f origin main
现在,您应该通过删除您在这两个地方创建的分支来清理本地和远程分支,因为它们不再需要。 首先,让我们删除本地分支:
git branch -d new-branch
添加到 git branch
命令的 -d
标志将删除您传递给命令的分支。 在上面的例子中,它被称为 new-branch。
接下来,我们将删除远程分支:
git push origin --delete new-branch
删除分支后,您已经清理了存储库,您的更改现在位于主存储库中。 您应该记住,由于您通过拉取请求所做的更改现在是主存储库的一部分,因此下载公共版本的普通最终用户可能无法使用它们。 一般来说,软件维护人员会将几个新功能和修复程序捆绑到一个公开版本中。
##结论
本教程将引导您完成在向开源软件存储库提交 拉取请求 后可能需要完成的一些后续步骤。
为开源项目做贡献——并成为一名活跃的开源开发人员——通常是一种有益的经历。 定期为您经常使用的软件做出贡献有助于确保它对其用户社区有价值和有用。