拉取远程仓库的贡献

如果你的贡献者建立了自己的版本库,并且向其中推送了若干修改, 之后将版本库的 URL 和包含更改的远程分支发送给你,那么你可以将其添加为一个远程分支,并且在本地进行合并。

比如 Jessica 向你发送了一封电子邮件,内容是在她的版本库中的 ruby-client 分支中有一个很不错的新功能, 为了测试该功能,你可以将其添加为一个远程分支,并在本地检出:

$ git remote add jessica git://github.com/jessica/myproject.git
$ git fetch jessica
$ git checkout -b rubyclient jessica/ruby-client

这对于与他人长期合作工作来说很有用。 而对于提交补丁频率较小的贡献者,相对于每个人维护自己的服务器,不断增删远程分支的做法,使用电子邮件来接收可能会比较省时。 况且你也不会想要加入数百个只提供一两个补丁的远程分支。 然而,脚本和托管服务在一定程度上可以简化这些工作——这很大程度上依赖于你和你的贡献者开发的方式。

这种方式的另一种优点是你可以同时得到提交历史。 虽然代码合并中可能会出现问题,但是你能获知他人的工作是基于你的历史中的具体哪一个位置;所以 Git 会默认进行三方合并,不需要提供 -3 选项,你也不需要担心补丁是基于某个你无法访问的提交生成的。

仅拉取而不添加远程仓库

对于非持续性的合作,如果你依然想要以这种方式拉取数据的话,你可以对远程版本库的 URL 调用 git pull 命令。 这会执行一个一次性的抓取,而不会将该 URL 存为远程引用:

$ git pull https://github.com/onetimeguy/project
From https://github.com/onetimeguy/project
 * branch            HEAD       -> FETCH_HEAD
Merge made by the 'recursive' strategy.

查看贡献内容

你已经有了一个包含其他人贡献的主题分支。 现在你可以决定如何处理它们了。

首先,应该查看非 master 分支即主题分支的内容,因为对方如果也遵守git规范,那么特性都是放在分支上的。假设贡献者向你发送了两个补丁,为此你创建了一个名叫 contrib 的分支并在其上应用补丁,你可以运行:

$ git log contrib --not master
commit 5b6235bd297351589efc4d73316f0a68d484f118
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Oct 24 09:53:59 2008 -0700
 
    seeing if this helps the gem
 
commit 7482e0d16d04bea79d0dba8988cc78df655f16a0
Author: Scott Chacon <schacon@gmail.com>
Date:   Mon Oct 22 19:38:36 2008 -0700
 
    updated the gemspec to hopefully work better

如果要查看每次提交所引入的具体修改,你应该记得可以给 git log 命令传递 -p 选项,这样它会在每次提交后面附加对应的差异(diff)。

其次是查看和 master 分支的差异,通过使用 ... 语法可以实现将 主题分支 与 和master分支的最近公共祖先 的差异显示出来:

$ git diff master...contrib

该命令仅会显示自当前主题分支 contribmaster 分支的共同祖先起,该分支中的工作。

整合贡献内容

合并工作流

将所有的工作直接合并到 master 分支。 在这种情况下,master 分支包含的代码是基本稳定的。 当你完成某个主题分支的工作,或审核通过了其他人所贡献的工作时,你会将其合并进入 master 分支,之后将主题分支删除,如此反复。

例如有主题分支 ruby_clientphp_client 将其贡献整合到自己的 master 分支中可能如下:

但在更大更稳定的项目中,这么做很可能带来问题,现在更推崇两阶段合并循环,即维护两个长期分支,分别是 master 存放非常稳定的版本 和 develop 存放整合新代码的版本。

例如: 觉得 ruby_client 不错的话就先整合到 develop 在经过长期测试之后再发布到 master 中:

大项目合并工作流

这里以 Git 项目举例

变基与挑拣工作流

通过变基来合并可以保持主分支的线性历史,将主题分支变基到主分支上后再进行向前合并。

具体参见 202501161656 git rebase

另一种将引入的工作转移到其他分支的方法是拣选。 Git 中的拣选类似于对特定的某次提交的变基。 它会提取该提交的补丁,之后尝试将其重新应用到当前分支上。 这种方式在你只想引入主题分支中的某个提交,或者主题分支中只有一个提交,而你不想运行变基时很有用。 举个例子,假设你的项目提交历史类似:

如果你希望将提交 e43a6 拉取到 master 分支,你可以运行:

$ git cherry-pick e43a6
Finished one cherry-pick.
[master]: created a0a41a9: "More friendly message when locking the index fails."
 3 files changed, 17 insertions(+), 3 deletions(-)

这样会拉取和 e43a6 相同的更改,但是因为应用的日期不同,你会得到一个新的提交 SHA-1 值。 现在你的历史会变成这样: