Now that the Collaborative workflows section has explained various repository setups, we'll learn about a few common patterns for contributing to a project. We'll see what our (main) options for publishing changes are.
Before starting work on new changes, you should usually sync to the main development, merging the official version into your repository. This, and the work of the maintainer, is left to be described in Chapter 7, Merging Changes Together.
In a centralized workflow, publishing your changes consists simply of pushing them to the central server, as shown in Fig 2. Because you share this central repository with other developers, it can happen that somebody has already pushed to the branch you are trying to update (the non-fast-forward case). In this scenario, you need to pull (fetch and merge, or fetch and rebase) others' changes, before being able to push yours.
Another possible system with similar workflow is when your team submits each set of changes to the code review system, for example, Gerrit. One available option is to push to a special ref
(which is named after a target branch, for example to refs/for/<branchname>
) in a special repository. Then change review server makes each set of changes land automatically on a separate per-set ref (for example, refs/changes/<change-id>
for commits belonging to a series with given Change-ID).
In both peer-to-peer (see Fig 3), and in maintainer workflows or its hierarchical workflow variant (Fig 4 and Fig 5), the first step in getting your changes included in the project is also to push, but to push to your own public repository. Then you need to ask your co-developers, or the project maintainer, to merge in your changes. You can do this for example by generating a pull request
.
In workflows with personal public repositories, one needs to send the notification that the changes are available to co-developers, or to the maintainer, or to integration managers. The git request-pull
command can help with this step. Given the starting point (the bottom of the revision range of interest) and the URL or the name of remote public repository, it will generate a summary of changes:
$ git request-pull origin/master publish The following changes since commit ba5807e44d75285244e1d2eacb1c10cbc5cf3935: Merge: strtol() + checks (2014-05-31 20:43:42 +0200) are available in the git repository at: https://git.example.com/random master Alice Developer (1): Support optional <count> parameter src/rand.c | 26 +++++++++++++++++++++----- 1 files changed, 21 insertions(+), 5 deletions(-)
The pull request contains the SHA-1 of the base of the changes (which is the revision just before the first commit, in series proposed for pull), the title of the base commit, the URL and the branch of the public repository (suitable as git pull
parameters), and the shortlog
and diffstat
of changes. This output can be sent to the maintainer, for example, by email.
Many Git hosting software and services include a built-in equivalent for git request-pull
(for example, the Create pull request
action in GitHub).
Many larger projects (and many open-source projects) have established procedures for accepting changes in the form of patches, for example, to lower the barrier to entry for contributing. If you want to send a one-off code proposal to a project, but you do not plan to be a regular contributor, sending patches might be easier than a full collaboration setup (acquiring the permission to commit in the centralized workflow, setting up a personal public repository for the forking workflow and for similar workflows). Besides, one can generate patches with any compatible tool, and the project can accept patches no matter which version control setup they're using.
Additionally, patches, being a text representation of changes, can be easily understood by computers and humans alike. This makes them universally appealing, and very useful for code review purposes. Many open-source projects use the public mailing list for that purpose: you can email a patch to this list, and the public can review and comment on your changes.
To generate e-mail versions of each commit series, turning them into mbox-formatted patches, you can use the git format-patch
command, as follows:
$ git format-patch -M -1 0001-Support-optional-count-parameter.patch
You can use any revision range specifier with this command, most commonly used is limiting by the number of commits, as in the preceding example, or by using the double-dot revision range syntax—for example, @{u}..
(see Chapter 2, Exploring Project History). When generating a larger number of patches, it is often useful to select a directory where to save generated patches. This can be done with the -o <directory>
option. The -M
option for git format-patch
(passed to git diff
) turns on rename detection; this can make patches smaller and easier to review.
The patch files end up looking like this:
From db23d0eb16f553dd17ed476bec731d65cf37cbdc Mon Sep 17 00:00:00 2001 From: Alice Developer <[email protected]> Date: Sat, 31 May 2014 20:25:40 +0200 Subject: [PATCH] Initialize random number generator Signed-off-by: Alice Developer <[email protected]> --- random.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/random.c b/random.c index cc09a47..5e095ce 100644 --- a/random.c +++ b/random.c @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdlib.h> +#include <time.h> int random_int(int max) @@ -15,6 +16,7 @@ int main(int argc, char *argv[]) int max = atoi(argv[1]); + srand(time(NULL)); int result = random_int(max); printf("%d ", result); -- 2.5.0
It is actually a complete email in the mbox format. The subject (after stripping the [PATCH]
prefix) and everything up to the three-dash line ---
forms the commit message—the description of the change. To email this to a mailing list or a developer, you can use either git send-email
or git imap-send
. The maintainer can then use git am
to apply the patch series, creating commits automatically; there's more about this in Chapter 7, Merging Changes Together.
The [PATCH]
prefix is here to make it easier to distinguish patches from other emails. The prefix can—and often does—include additional information, such as the number in the series (set) of patches, revision of series, information about it being a work-in-progress, or the request-for-comments status, for example: [RFC/PATCHv4 3/8]
.
You can also edit these patch files to add more information for prospective reviewers—for example, information about alternative approaches, about the differences between previous revisions of the patch (previous attempts), or a summary and/or references to the discussion on implementing the patch (for example, on a mailing list). You add such text between the ---
line and the beginning of the patch, before the summary of changes (diffstat); it will be ignored by git am
.