时不时地,我会被问到如何在开发、修复错误或扩展curl时顺利地使用git,或者我是如何做到这一点的。毕竟,我全职从事开源工作,这意味着我与Git(和GitHub)的互动非常频繁。简而言之,我整天都在和Git打交道。平时,我会发出几百次git命令。
我有一个非常简单的方法,可以在curl中使用git。这就是它的运作方式。
我几乎只在终端的命令行中使用git。为了帮助我了解我在哪个分支机构工作,我有这个小小的bash助手脚本。
Brname(){a=$(git rev-parse--abbrev-ref head 2>;/dev/null)如果[-n";$a";];则ECHO";[$a]";ELSE ECHO";";FI}PS1=";\u@\h:\W\$(Brname)$";
这会给我一个提示符,显示用户名、主机名、当前工作目录和当前签出的git分支。
此外,我对git使用Debian的bash命令行补全,这也非常方便。它允许我使用Tab键完成git命令和分支机构名称等操作。
当然,我也有自己定制的~/.gitconfig文件,可以为我提供一些方便的别名和设置。我最常用的git别名是:
最新的一个是列出自最新版本以来对curl所做的所有更改-注释“同步”。其他的应该是不言而喻的。
主要的curl开发是在单一的curl/curl git库中完成的(主要托管在GitHub上)。我们保留了主分支,即前沿开发树,并且我们努力工作,以始终保持它的工作和功能。当这一天到来的时候(每八周),我们就会在主分支上发布,我们会提供该分支的“每日快照”,并将这些快照放在一起--对--每天。
在将修复和功能合并到master中时,我们避免合并提交,并尽可能多地使用rebase和快进。这使得该分支非常易于浏览、理解和使用-因为它是100%线性的。
当我开始做一些新的事情时,比如修复一个bug,或者尝试别人的补丁或类似的补丁,我会首先创建一个本地分支,然后在这个分支上工作。也就是说,我不是直接在总公司工作。分枝既容易又快捷,没有理由回避大量的分枝!
我通常使用GitHub用户名作为分支命名的前缀,这样当我将它们推送到服务器时,就会注意到谁是创建者(而且我可以在本地和远程使用相同的分支名称)。
一旦我到了某个地方,我就会去树枝。然后,在我认为自己“暂时完成”之前,它可能会以一次或多次提交而告终,而我本来打算做的事情就已经完成了。
我尽量不带着任何未完成的改变离开这棵树--比如,如果我离开一天,甚至只是去吃东西或延长休息时间。这使存储库处于这样一种状态,即当我返回时,我可以轻松地切换到另一个分支--如果我觉得需要这样做的话。此外,最好在休息前承诺并解释更改,而不是回来时不得不再次回忆细节。
因此,“git stash”不是我使用过的命令。我宁愿创建一个新分支并提交(临时?)。在那里工作,作为一种潜在的新工作方式。
是的,我是这个项目的首席开发人员,但我仍然像其他人一样保持着相同的工作流程。除最微小的更改外,所有更改都是通过GitHub上的拉取请求完成的。
当我对我当地分店的功能感到满意的时候。当错误似乎被修复,或者功能似乎在做它应该做的事情,并且测试套件在本地运行良好时。
然后,我使用“git rebase-i”清理提交序列(或者,如果是单次提交,我可以只使用“git Commit--amendate”)。
提交系列应该是一组与此更改相关的逻辑更改,并且不会超过必要的更改,但如果它们是分开的,则应保持独立。每个提交还获得其自己的正确提交消息。不相关的更改应分为独立的分支和后续的单独拉入请求。
然后,在GitHub上,我将新推送的分支转换为Pull请求(也称为“PR”)。然后,它将出现在站点上对curl源库的请求列表中,它将在#curl IRC频道中公布,所有在GitHub上关注该库的人都会收到相应的通知。
也许最重要的是,拉请求会引发大量的CI工作,这些工作将在许多不同的组合和几个平台上构建和测试代码,这些测试的结果将在接下来的几个小时内陆续公布。当我写这篇文章的时候,我们有大约90个不同的CI任务-每个拉取请求-大约8个不同的代码分析器将仔细检查这个变化,看看其中是否有任何明显的缺陷。
大多数使用cURL的贡献者不会像我这样在curl库中创建分支,而是更愿意在他们自己的派生版本中创建分支。差别不是很大,我当然也可以那样做。
由于需要一些时间才能从公关处获得完整的CI结果(通常需要几个小时),所以我切换到下一个分支机构处理我的议程上的工作。在正常的工作日,我可以轻松地移动到10个不同的分支机构,对它们进行润色,并在它们各自的拉取请求中提交更新。
我可以再次回到Git Check Master分支机构,在那里我可以“Git Pull”从上游获取所有东西-就像我的开发伙伴在同一时间推东西的时候一样。
如果审查员或CI工作人员在我的公关中发现了错误,GitHub上就会显示出来,我就会开始处理。要么修复错误,要么与评审者讨论什么是更好的方法。
不幸的是,不稳定的CI作业是生活的一部分,因此在CI作业列表中经常会出现一两个红色标记,可以忽略,因为其中的测试失败是由于设置中的问题,而不是PR…中的实际错误。
为了再次回到我的分支机构进行公关,我“git check out bagder/my-new-thing-or-bugfix”,并修复了这些问题。
我通常从后续提交开始,修复直接的错误,并将它们推到分支上:
如果修复提交的数量变大,或者如果后续的修复不是很少,我通常会进行挤压以将提交的数量减少到一个更小、更简单的集合,然后将它们强制推到分支。
这样做的原因是为了使补丁系列易于查看、阅读和理解。如果提交序列中的提交太多,从而更改了以前的提交,则很难对其进行审查。
当Pull请求的合并时机成熟时(与作者无关),我再次切换到主分支,并将Pull请求的提交合并到其中。在特殊情况下,我会从分支中挑选特定的提交。当所有应该放在那里的东西都被正确地拉入主机时,我就把零钱推到遥控器上。
通常,特别是如果拉请求不是由我完成的,我还会在推送所有内容之前检查提交消息并对其进行一些润色。提交消息应该遵循我们的风格,不仅提到它关闭了哪个PR,而且还提到它修复了哪个问题,并适当地给予错误报告者和所有帮助者信任-使用正确的语法,以便我们的自动工具可以正确地提取它们!
GitHub上有一个按钮,上面写着“Rebase and Merge”,理论上可以用来合并Pull请求。我从不使用它(如果可以的话,我会禁用/隐藏它)。原因很简单:
我觉得我无法正确控制提交消息。
我不能选择压缩提交的子集,只能全部压缩或不压缩。
我经常想在推送之前清理作者部分,这是用户界面不允许的。
不使用合并按钮的缺点是,PR中的消息显示为“Closed by[Hash]”,而不是“Merge in…”这会让相当多的用户感到困惑,他们没有意识到这意味着它实际上是一回事!我认为这是(长期)GitHub UX的一个缺陷。
如果分支没有更多需要保留的内容,我会使用“git Branch-d[name]”再次删除本地分支,并远程删除它,因为它已经完全合并,没有理由保留工作版本。
在任何给定的时间点,我都有大约20-30个不同的本地分支机构在使用这种方法,所以我长期从事的工作都在它们自己的分支机构中进行,也有来自不同人的提交,这些提交还没有合并到Master中,但存在于不同成熟度级别的分支机构中。在这些本地分支中,我正在处理的并发拉请求的数量可能在几到十到十二个之间。
没有严格的关系,但为了让感兴趣的人了解树中正在发生的事情,我们偶尔同步发布说明文件。可能每隔5-7天左右。因此,它变成了一个文件,解释了自上一版本以来我们所做的工作,并使其在发布日到来时得到了良好的维护和准备。
这使得脚本向其添加建议的更新,因此我随后将该文件加载到我的编辑器中,删除分隔标记和实际上不属于那里的所有条目(因为脚本将所有提交作为条目添加,因为它无法判断重要性)。
当它看起来没问题时,我运行一次清理循环,让它对其进行排序,并从文件…中删除未使用的引用。
…。并将更新后的列表粘贴到发行说明中。最后,我通过运行以下命令获得文件顶部数字的刷新计数器。
然后,我提交更新(需要有提交消息Release-NOTES:SYNCED“)并将其推送到master。搞定了!