请求工作流

Godot使用的所谓“公关工作流”对于许多使用Git的项目来说是很常见的,对于资深的免费软件贡献者来说应该是熟悉的。其想法是只有少数人(如果有的话)直接承诺 分支。相反,贡献者 fork 项目(即创建一个副本,他们可以根据自己的意愿修改),然后使用github接口请求 pull 从它们的一个分支到原始分支(通常被命名为 上游 )存储库。

结果 拉取请求 (pr)然后可以由其他贡献者进行审查,这些贡献者可能会批准它、拒绝它,或者最经常请求进行修改。一旦获得批准,PR就可以被一个核心开发人员合并,并且它的提交将成为目标分支的一部分(通常是 分支)。

我们将一起通过一个例子来展示典型的工作流和相关的git命令。但首先,让我们快速了解一下Godot的Git存储库的组织结构。

Git源存储库

这个 repository on GitHub 是一个 Git 代码存储库以及嵌入式问题跟踪程序和公关系统。

注解

如果您是文档的贡献者,可以找到它的存储库 here .

Git版本控制系统是一个工具,用于跟踪对源代码的连续编辑,从而有效地为Godot做出贡献,学习Git命令行的基础知识是 高度地 推荐。Git有一些图形界面,但它们通常会鼓励用户养成关于Git和PR工作流的坏习惯,因此我们建议不要使用它们。特别是,我们建议不要使用Github的在线编辑器进行代码贡献(尽管它可以容忍小的修复或文档更改),因为它强制每个文件和每次修改提交一次,这很快导致具有不可读Git历史的PRS(特别是在同行审查之后)。

参见

Git的“书”的第一部分很好地介绍了该工具的原理以及您在日常工作流程中需要掌握的各种命令。你可以在网上阅读 Git SCM 网站。

Git存储库上的分支组织如下:

  • 这个 master 分支是开发下一个主要版本的地方。作为一个开发分支,它可能不稳定,不用于生产。这是应优先进行PRS的地方。

  • 稳定分支以其版本命名,例如 3.02.1 . 它们用于从 master 分支到当前维护的稳定版本(例如3.0.2或2.1.5)。根据经验,最后一个稳定分支将保持到下一个主要版本(例如 2.0 分支机构一直维持到Godot2.1发布)。如果您想对一个保持稳定的分支进行prs,您必须检查您的更改是否也与 master 分支机构。

  • 当时可能有一些功能分支,通常是要合并到 master 在某个时间分支。

分叉和克隆

第一步是 fork 这个 godotengine/godot GitHub上的存储库。为此,您需要有一个GitHub帐户并登录。在存储库的github页面的右上角,您应该看到“fork”按钮,如下所示:

../../_images/github_fork_button.png

单击它,一段时间后,您将被重定向到您自己的godot repo分支,并使用您的github用户名作为命名空间:

../../_images/github_fork_url.png

那你就可以了 克隆 您的fork,即创建在线存储库的本地副本(在git speak中, 源站远程 )如果还没有,请从下载Git its website 如果您使用的是Windows或MacOS,或者如果您使用的是Linux,请通过软件包管理器安装它。

注解

如果您在Windows上,请打开git bash键入命令。MacOS和Linux用户可以使用各自的终端。

要从Github克隆您的fork,请使用以下命令:

$ git clone https://github.com/USERNAME/godot

注解

在我们的示例中,“$”字符表示典型UNIX shell上的命令行提示。它不是命令的一部分,不应键入。

过一会儿,你应该 godot 当前工作目录中的目录。使用 cd 命令:

$ cd godot

首先,我们将建立对原始存储库的引用:

$ git remote add upstream https://github.com/godotengine/godot
$ git fetch upstream

这将创建一个名为 upstream 指向原始GodoEngine/Godot存储库。当您希望从 master 分支以更新您的分叉。你还有一个 remote 名为的引用 origin 指向你的叉子。

只要保持本地,您只需执行上述步骤一次。 godot 文件夹(如果需要,可以移动该文件夹,相关元数据隐藏在其 .git 子文件夹)。

注解

分支它,拉它,编码它,阶段它,提交,推它,重新平衡它…技术。

这是对Daft Punk的坏看法 技术 展示了Git初学者对其工作流程的一般概念:通过复制和粘贴来学习许多奇怪的命令,希望它们能按预期工作。这其实不是一个糟糕的学习方法,只要你好奇,在你的搜索引擎丢失时不要犹豫,我们会给你基本的命令,让你知道在Git工作。

在下面的内容中,我们假设您希望在Godot的项目管理器中实现一个特性,该特性在 editor/project_manager.cpp 文件。

分支

默认情况下, git clone 你应该穿上 master 你的叉子 (origin )要开始您自己的功能开发,我们将创建一个功能分支:

# Create the branch based on the current branch (master)
$ git branch better-project-manager

# Change the current branch to the new one
$ git checkout better-project-manager

此命令等效:

# Change the current branch to a new named one, based on the current branch
$ git checkout -b better-project-manager

如果你想回到 master 分支,您将使用:

$ git checkout master

您可以看到当前使用的分支 git branch 命令:

$ git branch
  2.1
* better-project-manager
  master

正在更新分支

这不是第一次需要(在您分叉上游存储库之后)。但是,下次你想做什么的时候,你会发现你的叉子 master 上游是否有几项承诺 master 分支:来自其他参与者的请求将同时被合并。

以确保您开发的特性和当前上游特性之间不存在冲突 master 分支,您必须更新分支 牵引 上游分支。

$ git pull upstream master

但是,如果您有本地提交,这个方法将创建一个所谓的“合并提交”,您很快就会听到来自其他参与者的消息,即在PRS中不需要这些提交。那么如何在不创建合并提交的情况下更新分支呢?你必须使用 --rebase 选项,以便在更新的上游上重播本地提交 master 分支。它将有效地修改您的分支的git历史记录,但这是为了更大的好处。

因此,您应该(几乎)始终使用的命令是:

$ git pull --rebase upstream master

正在进行更改

然后您将对示例的 editor/project_manager.cpp 使用您通常的开发环境(文本编辑器、IDE等)创建文件。

默认情况下,这些更改是 未老化 . 临时区域是工作目录(在其中进行修改)和本地Git存储库(提交和中的所有元数据)之间的一个层。 .git 文件夹)。要将更改从工作目录带到Git存储库,需要 阶段 他们和 git add 命令,然后用 git commit 命令。

在准备工作之前、准备工作期间以及提交工作之后,您应该知道一些命令来检查当前工作。

  • git diff 将显示当前未分页的更改,即工作目录和临时区域之间的差异。

  • git checkout -- <files> 将撤消对给定文件的未分页更改。

  • git add <files>阶段 所列文件的更改。

  • git diff --staged 将显示当前阶段性更改,即阶段性区域和上一次提交之间的差异。

  • git reset HEAD <files>失稳 对列出的文件所做的更改。

  • git status 将向您显示当前阶段和未阶段的修改。

  • git commit 将提交阶段文件。它将打开一个文本编辑器(您可以定义要与 GIT_EDITOR 环境变量或 core.editor 在Git配置中进行设置),以便编写提交日志。你可以用 git commit -m "Cool commit log" 直接写入日志。

  • git log 将显示当前分支的最后一次提交。如果您执行了本地提交,那么它们应该显示在顶部。

  • git show 将显示上一次提交的更改。您还可以指定提交哈希来查看该提交的更改。

这是很多要记住的!别担心,当你需要改变的时候,只需检查一下这个备忘单,然后通过实践来学习。

下面是Shell历史在我们的示例中的样子:

# It's nice to know where you're starting from
$ git log

# Do changes to the project manager with the nano text editor
$ nano editor/project_manager.cpp

# Find an unrelated bug in Control and fix it
$ nano scene/gui/control.cpp

# Review changes
$ git status
$ git diff

# We'll do two commits for our unrelated changes,
# starting by the Control changes necessary for the PM enhancements
$ git add scene/gui/control.cpp
$ git commit -m "Fix handling of margins in Control"

# Check we did good
$ git log
$ git show
$ git status

# Make our second commit
$ git add editor/project_manager.cpp
$ git commit -m "Add a pretty banner to the project manager"
$ git log

有了这个,我们应该有两个新的承诺 better-project-manager 不在的分支 master 分支。但是它们仍然只是本地的,远程分支不知道它们,上游回购也不知道。

将更改推送到远程

就在那里 git push 将发挥作用。在Git中,提交总是在本地存储库中完成(与提交将直接修改远程存储库的Subversion不同)。你需要 push 新公司致力于建立一个远程分支机构,与世界分享这些信息。其语法为:

$ git push <remote> <local branch>[:<remote branch>]

如果您希望远程分支具有与本地分支相同的名称,那么可以省略有关远程分支的部分,在本例中就是这样,因此我们将执行以下操作:

$ git push origin better-project-manager

Git会询问您的用户名和密码,更改将发送到您的遥控器。如果检查Github上的fork页面,您应该看到一个新的分支,其中包含您添加的提交。

发出拉取请求

当你在Github上加载fork的分支时,你应该看到一行字 “这个分支比GodoteEngine:Master领先2个任务。” (如果您的 master 分支与上游不同步 master 分支机构。

../../_images/github_fork_make_pr.png

在这条线上,有一个“拉请求”链接。单击它将打开一个表单,您可以在godoengine/godot上游存储库上发出请求。它应该显示您的两个提交,并说明“能够合并”。如果没有(例如,它有更多的提交,或者说存在合并冲突),不要创建公关,就会出错。去IRC寻求支持:)

对pr使用明确的标题,并将必要的详细信息放在注释区域中。您可以拖放屏幕截图、gif或压缩项目(如果相关),以展示您的工作实现了什么。单击“创建拉请求”,然后单击tadaa!

修改拉请求

当它被其他贡献者审阅时,您通常需要对尚未合并的公关进行更改,这可能是因为贡献者请求了它们,也可能是因为您在测试时发现了问题。

好消息是,您可以通过对发出拉请求的分支执行操作来修改拉请求。例如,您可以对该分支进行一次新的提交,将其推送到您的fork,然后将自动更新pr:

# Check out your branch again if you had changed in the meantime
$ git checkout better-project-manager

# Fix a mistake
$ nano editor/project_manager.cpp
$ git add editor/project_manager.cpp
$ git commit -m "Fix a typo in the banner's title"
$ git push origin better-project-manager

这应该是技巧,但是…

掌握公关工作流程:REBASE

在上面概述的情况下,对于Git历史特别学究的其他投稿人可能会要求您 重碱 你的分支机构 壁球meld 最后两个提交在一起(即与项目经理相关的两个提交),因为第二个提交基本上解决了第一个提交中的问题。

一旦pr被合并,pr作者所犯的错误与changelog阅读器无关;相反,我们只希望保持从一个工作状态到另一个工作状态的提交。

要把这两个承诺挤在一起,我们必须 重写历史记录 . 对,我们有这种力量。你可能会读到,这是一个糟糕的做法,当谈到上游回购的分支时,这是真的。但是在你的叉子里,你可以做你想做的任何事情,并且所有的事情都可以得到整洁的prs:)

我们将使用 交互式钢筋网 git rebase -i 这样做。此命令将提交哈希作为参数,并允许您修改该提交哈希和分支最后一个分支之间的所有提交,即 HEAD . 在我们的示例中,我们希望对最后两个提交操作,因此我们将执行以下操作:

# The HEAD~X syntax means X commits before HEAD
$ git rebase -i HEAD~2

这将打开一个文本编辑器:

pick 1b4aad7 Add a pretty banner to the project manager
pick e07077e Fix a typo in the banner's title

编辑器还将显示有关如何处理这些提交的说明。特别是,它应该告诉您,“pick”意味着使用提交(什么都不做),“squash”和“fixup”可以用来 meld 父提交中的提交。“squash”和“fixup”的区别在于“fixup”将从压缩的提交中丢弃提交日志。在我们的示例中,我们不希望保存“修复拼写错误”提交的日志,因此我们使用:

pick 1b4aad7 Add a pretty banner to the project manager
fixup e07077e Fix a typo in the banner's title

保存并退出编辑器后,将发生重新平衡。第二个承诺将融入第一个承诺,并且 git loggit show 现在应该确认您只有一个提交,其中包含以前两个提交所做的更改。

注解

你可以通过使用 git commit --amend 修正打字错误时。此命令将阶段性更改直接写入 last 犯罪 (HEAD ,而不是像本例中那样创建新的提交。因此,它相当于我们对一个新提交所做的,然后用一个rebase将其标记为“fixup”。

但是!你重写了历史,现在你的本地和远程分支已经分开了。实际上,上面例子中的commit 1b4aad7已经更改,因此得到了一个新的commit hash。如果尝试推送到远程分支,它将引发一个错误:

$ git push origin better-project-manager
To https://github.com/akien-mga/godot
 ! [rejected]        better-project-manager -> better-project-manager (non-fast-forward)
error: failed to push some refs to 'https://akien-mga@github.com/akien-mga/godot'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart.

这是一种理智的行为,Git不会让您推送将覆盖远程内容的更改。但事实上这就是我们想在这里做的,所以我们必须 它:

$ git push --force origin better-project-manager

还有tadaa!Git会很高兴的 代替 你的远程分支和你在本地拥有的(所以确保这是你想要的,使用 git log )这也将相应地更新PR。

删除Git分支

在你的拉请求被合并后,还有最后一件事你应该做:为公关删除你的Git分支。如果你不删除你的分支,就不会有问题,但是这样做是一个好的做法。您需要这样做两次,一次用于本地分支,另一次用于Github上的远程分支。

要在本地删除更好的项目经理分支,请使用以下命令:

$ git branch -d better-project-manager

或者,如果分支尚未合并,我们希望删除它,而不是 -d 你会用 -D .

接下来,要删除github上的远程分支,请使用以下命令:

$ git push origin -d better-project-manager