In an open source project, only the project maintainers are able to actually make changes. Therefore, other contributors must send their changes to the project maintainers in the form of patches, usually by e-mail. If the maintainers approve of the change, they will then apply the patch to the project, thereby incorporating the change.

Essentially, a patch shows the difference between two states of a file (or collection of files), in such a form that a piece of software can then replicate this change automatically on [ <!> IN?] another copy of the file(s). In this document, we demonstrate how to make a simple change to the source code of an existing project, producing a record of that change (a patch) suitable to submit back to the project.

You needn't actually follow this process on your machine (though it should be possible). Our intention is that you simply read the document to get a concrete idea of the process of producing a simple patch.

Preparation

The project we will use for the demonstration is the GNU Coreutils project, which provides some of the most basic command-line tools for a GNU system, like 'cd' and 'ls'. The project package actually contains the code for over 30 such tools, though only one of these tools will be modified here. Coreutils targets UNIX-like systems, and as such comes with many automated scripts that require a UNIX-like system to work. It may be possible to replicate this environment on, for example, Windows, but this will require more work.

Download Coreutils

The Coreutils website explains that the project uses the Git revision control system. A revision control system is a system that manages the files that make up the project, keeping track of all the changes that are made and who produced them. Using the corresponding Git client software, you will be able to download an initial copy. You can then easily update this with subsequent changes made to the code in the project's repository by other developers.

The Coreutils website explains how to actually download a copy of the source. To do this, Git is invoked from the command-line as follows:

$ git clone git://git.sv.gnu.org/coreutils

The files making up the project are downloaded to the current directory, including some instructions and scripts.

Read the instructions

A project should provide documentation for potential contributors. Coreutil's documentation provides a complete guide to the process, part of which describes the style guidelines for Coreutils code and written material. It is important to observe these guidelines in any changes made. The two most important items can be seen here and here.

Before making a contribution to a project, you will need to consider some legal issues, primarily in order to determine who owns the copyright to the contribution. Then, since it is to be included in someone else's project, the copyright holder of the contribution must enter into an agreement that allows their work to be incorporated legally into the project. The procedure for doing so varies between projects.

Coreutils' policy with regard to this is set out in one of the 'readme' files that accompany the code. If a contribution involves a 'significant' change (defined by Coreutils, for example, as an addition of more than about 10 lines of code), the copyright holder of the patch must submit a form assigning the rights to the project. The process for doing so is explained in the instructions.

Coreutils, along with many other projects, also requires that all modifications include the name and e-mail of the individual who is responsible for them. Used with the record of contributor license agreements described above, this allows the project to prove the legal ownership status of any section of code (intellectual property due diligence). You should therefore configure Git with a name and email address to include in the patches it produces. The configuration file .gitconf, in the user's home directory, needs to contain the following:

[user]
        name = Johnny Developer
        email = j.developer@developers.com

Perform a test build of the project

Before you can be build the project for the first time, you will need to run the following script in order to generate the build scripts:

$ ./bootstrap

This script will fail if some tools are missing from the system; if this happens, you will have to install what it needs. Once it succeeds, the instructions explain how to build the project. Coreutils uses the common Automake system for automating the build process:

$ ./configure
$ make
$ make check

configure will complain if not all the necessary tools are present. Again, if this happens, you will need to find out how to install these on your system. The purpose of make check is to run automated tests on the compiled binaries generated by make, which establish a baseline of functionality that the programs must display. It is possible that not all tests will succeed, depending upon the state of the project at the point it was downloaded; what is in the project's repository is, after all, work-in-progress.

Make the changes

This demonstration will involve making a change to the 'echo' command, which simply prints back the parameters fed to it (or the contents of STDIN). Let's have a look at an example:

$ echo Monday Tuesday Wednesday
Monday Tuesday Wednesday

The change will be to make echo print out the parameters in reverse order. For example:

$ echo Monday Tuesday Wednesday
Wednesday Tuesday Monday

The code for the program is in a single file, echo.c; the following algorithm does the work:

while (argc > 0)
        {
                fputs (argv[0], stdout);
                argc--;
                argv++;
                if (argc > 0)
                putchar (' ');
        } 

In order to print the parameters in reverse order, it must be changed to:

while (argc > 0)
        {
                argc--;
                fputs (argv[argc], stdout);
                if (argc > 0)
                putchar (' ');
        } 

The program must now be rebuilt. Thanks to the Automake system, only the programs which have been changed are rebuilt. As before:

$ make

Test

[ <!> PLEASE EXPAND THIS SENTENCE, E.G. 'THE NEXT STEP IS TO TEST ...] To test (making sure to run the copy of echo just compiled, rather than the system's own version):

$ ./src/echo Monday Tuesday Wednesday
Wednesday Tuesday Monday

However, as this project also came with automated tests, they should be re-run now. This will show whether the results have changed since the first run above, now that one of the programs has been changed. As before:

$ make check
...
=========================
 All 346 tests passed
 (35 tests were not run)
=========================
...
========================
 All 99 tests passed
 (3 tests were not run)
========================
...

Success! The output here has been abbreviated somewhat, but the important part is that no problems occurred. Of course, having made a change that significantly changes the behaviour of echo, you might find it necessary to change some of the automated tests to reflect this, and submit a patch for that as well. However, this is outside the scope of this demonstration.

Commit the change

You will now need to update Git's local record of the project with the changes made to echo's source code (otherwise, the changes are not permanent). To do this, you must 'commit' the file containing the alterations:

$ git commit -s ./src/echo.c

The -s tells Git to add a line identifying the person responsible for the patch, for the reasons mentioned earlier. Git then brings up a text editor so the change can be annotated; the Coreutils documentation specifies the form this must take. The full text of the change record, with the annotation, is:

echo: command-line parameters are now printed out in reverse order.

* src/echo.c (main): iterate from argument (argc - 1) to argument 1

Signed-off-by: Johnny Developer <j.developer@developers.com>

# Please enter the commit message for your changes.
# (Comment lines starting with '#' will not be included)
# On branch master
# Changes to be committed:
#   (use "git reset HEAD^1 <file>..." to unstage)
#
#       modified:   src/echo.c
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       gnulib/
#       lib/arpa/
#       lib/uniwidth/

After you have saved the change and exiting the text editor, the change is committed. The original command with its output was:

git commit -s ./src/echo.c
Created commit 48c74ed: echo: command-line parameters are now printed out in reverse order.
 1 files changed, 1 insertions(+), 2 deletions(-)

This now appears in the history of changes made to the project:

$ git log
commit 48c74ed73e72b5e276d888a798a9ef64df5d039d
Author: Johnny Developer <j.developer@developers.com>
Date:   Thu Jul 31 21:17:36 2008 +0100

    echo: command-line parameters are now printed out in reverse order.

    * src/echo.c (main): iterate from argument (argc - 1) to argument 1

    Signed-off-by: Johnny Developer <j.developer@developers.com>

commit b44f5f74aa1cb209720cbb2cd60ecd47975397ab
Author: [DETAILS REMOVED]
Date:   Wed Jul 30 14:29:52 2008 +0200

    * timeout.c: Fix grammar in a comment. Normalize comment syntax.

commit 662ce25d830adaa427608ea582688369c70639e2
Author: [DETAILS REMOVED]
Date:   Mon Jul 28 11:48:22 2008 +0200

    bootstrap: work also when there are no .po files in po/

    * bootstrap (update_po_files): Complete the change that I began
    in 7ba2dd808232cff3ee76aaceb97f4381c3c9cde4.

etc...

As this is quite an established project, there is a long history of changes; only our change and the two before it are shown here.

Produce the patch

Having made the change successfully, you now need to produce the patch to send back to the project. Of course, if this were a real change that was really going to be submitted back to the project, other small changes might also have to be made. For example, the 'help' message the program prints out, if there is one, would have to be changed to reflect its new behaviour; likewise, the 'man' page for the program. Even though some of these changes are not to the code itself, they would still be submitted in the same way, as a patch.

The 'diff'

When the commit was made earlier, Git made an exact record of the differences between the file echo.c in its original state and in its new, modified, state. This is called a 'diff', and looks like this:

$ git show
commit 48c74ed73e72b5e276d888a798a9ef64df5d039d
Author: Johnny Developer <j.developer@developers.com>
Date:   Thu Jul 31 21:17:36 2008 +0100

    echo: command-line parameters are now printed out in reverse order.

    * src/echo.c (main): iterate from argument (argc - 1) to argument 1

    Signed-off-by: Johnny Developer <j.developer@developers.com>

diff --git a/src/echo.c b/src/echo.c
index 11e648e..b265567 100644
--- a/src/echo.c
+++ b/src/echo.c
@@ -261,9 +261,8 @@ just_echo:
     {
       while (argc > 0)
        {
-         fputs (argv[0], stdout);
          argc--;
-         argv++;
+         fputs (argv[argc], stdout);
          if (argc > 0)
            putchar (' ');
        }

'Show' displays the diff for the most recent commit. The diff shows the file in which the changes were made (echo.c). This is followed by an excerpt of code: the lines preceded by '-' are ones that were present in the original version and then removed; the line preceded by '+' is only present in the modified version; the other lines are unchanged. Between these is information about the line number at which the code excerpt begins, in the original and modified versions - in this case, 261 in both - and the total length of the section of code - 9 lines in the original and 8 in the modified version. The above is the content of the patch that will be produced.

Resolve conflicts

Because other developers are also working on the project, changes may have been made in the project's repository since our copy was downloaded. It is therefore possible that echo.c might have been modified in such a way that conflicts with the changes made here, which would make it difficult for the maintainers to apply the patch. To avoid this, you need to download and merge the latest changes from Coreutils into the local copy before producing the patch, and deal with any conflicts that occur before creating the patch. Anyone submitting a patch is expected to do this, to avoid creating extra work for the project maintainers. Even so, there is always a chance that in the time it takes for the maintainer to review the patch, new conflicts will arise.

Git will update the local version in one step:

$ git pull
Already up-to-date.

In this case, no changes had been made in the project repository since the first download, so no conflicts occurred. It is therefore safe to go on to generate the patch.

Generate the patch

Git can automatically generate a patch file for each change (defined as each 'commit' performed), showing the explanatory comment and the actual diff itself. It can also generate it as a 'mbox' email file:

$ git format-patch --stdout -1
From 48c74ed73e72b5e276d888a798a9ef64df5d039d Mon Sep 17 00:00:00 2001
From: Johnny Developer <j.developer@developers.com>
Date: Thu, 31 Jul 2008 21:17:36 +0100
Subject: [PATCH] echo: command-line parameters are now printed out in reverse order.

* src/echo.c (main): iterate from argument (argc - 1) to argument 1

Signed-off-by: Johnny Developer <j.developer@developers.com>
---
 src/echo.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/src/echo.c b/src/echo.c
index 11e648e..b265567 100644
--- a/src/echo.c
+++ b/src/echo.c
@@ -261,9 +261,8 @@ just_echo:
     {
       while (argc > 0)
        {
-         fputs (argv[0], stdout);
          argc--;
-         argv++;
+         fputs (argv[argc], stdout);
          if (argc > 0)
            putchar (' ');
        }
--
1.5.6.3

The argument -1 tells Git to output just a single patch - the most recent one - which the change to echo.c; --stdout tells Git not to save as a file.

Submit the patch

This output can then be taken and used in email software to send the change to the address specified by the project. Again, the project documentation explains where to find the email address to send the patch to, and gives a link to submission guidelines on the web.

Next step

That is the process for creating a simple patch. This particular patch, of course, would be useless to the project, so was not really submitted. But if we had submitted it, the next step would be to wait to hear from the project maintainer, who may ask for further changes to be made before the patch is incorporated into the project.

Further reading

Acknowledgements

The major sources of information for this document were:

Further information from OSS Watch

OSSWatchWiki: MakeASimplePatch (last edited 2013-04-15 13:56:28 by localhost)

Creative Commons License
The content of this wiki is licensed under the Creative Commons Attribution-ShareAlike 2.0 England & Wales Licence.

OSS Watch is funded by the Joint Information Systems Committee (JISC) and is situated within the Research Technologies Service (RTS) of the University of Oxford.