Running Linux, 5th Edition - Matthias Kalle Dalheimer [413]
As was mentioned in the introduction to this chapter, another tool, Subversion, is slowly taking over from CVS, even though CVS is still used by the majority of projects, which is why we cover CVS in detail here. But one of the largest open source projects, KDE, has switched to Subversion, and many others are expected to follow. Many commands are very similar: for example, with Subversion, you register a file with svn add instead of cvs add. One major advantage of Subversion over CVS is that it handles commits atomically: either you succeed in commiting all files in one go, or you cannot commit any at all (whereas CVS only guarantees that for one directory). Because of that, Subversion does not keep per-file version numbers like CVS, but rather module-global version numbers that make it easier to refer to one set of code. You can find more information about Subversion at http://subversion.tigris.org.
Patching Files
Let's say you're trying to maintain a program that is updated periodically, but the program contains many source files, and releasing a complete source distribution with every update is not feasible. The best way to incrementally update source files is with patch , a program by Larry Wall, author of Perl.
patch is a program that makes context-dependent changes in a file in order to update that file from one version to the next. This way, when your program changes, you simply release a patch file against the source, which the user applies with patch to get the newest version. For example, Linus Torvalds usually releases new Linux kernel versions in the form of patch files as well as complete source distributions.
A nice feature of patch is that it applies updates in context; that is, if you have made changes to the source yourself, but still wish to get the changes in the patch file update, patch usually can figure out the right location in your changed file to which to apply the change. This way, your versions of the original source files don't need to correspond exactly to those against which the patch file was made.
To make a patch file, the program diff is used, which produces "context diffs" between two files. For example, take our overused "Hello World" source code, given here:
/* hello.c version 1.0 by Norbert Ebersol */
#include int main() { printf("Hello, World!"); exit(0); } Let's say you were to update this source, as in the following: /* hello.c version 2.0 */ /* (c)1994 Norbert Ebersol */ #include int main() { printf("Hello, Mother Earth!\n"); return 0; } If you want to produce a patch file to update the original hello.c to the newest version, use diff with the -c option: papaya$ diff -c hello.c.old hello.c > hello.patch This produces the patch file hello.patch that describes how to convert the original hello.c (here, saved in the file hello.c.old) to the new version. You can distribute this patch file to anyone who has the original version of "Hello, World," and they can use patch to update it. Using patch is quite simple; in most cases, you simply run it with the patch file as input:[*] papaya$ patch < hello.patch Hmm... Looks like a new-style context diff to me... The text leading up to this was: -------------------------- |*** hello.c.old Sun Feb 6 15:30:52 1994 |--- hello.c Sun Feb 6 15:32:21 1994 -------------------------- Patching file hello.c using Plan A... Hunk #1 succeeded at 1. done papaya$ patch warns you if it appears as though the patch has already been applied. If we tried to apply the patch file again, patch would ask us if we wanted to assume that -R was enabled—which reverses the patch. This is a good way to back out patches you didn't intend to apply. patch also saves the original version of each file that it updates in a backup file, usually named filename~ (the filename with a tilde appended). In many cases, you'll want to update not only a single source file, but also an entire directory tree of sources. patch allows many files to be updated from