Learn › Linux Foundations › Text Processing
patch - a hands-on Linux lab on a real virtual machine.
Ship a change, not a whole file. patch applies the record diff wrote: patch old < change.patch edits the file, patch -R undoes it, --dry-run tests it safely, and -b keeps a backup. Read the two failures every patch user meets, a rejected hunk and a malformed patch, all in the practice terminal on the change folder.
You fixed a config file. Two lines changed out of hundreds. Now you have to hand that fix to a teammate, or to a machine, or to your future self. You could send the entire new file and hope nobody spots the difference. Or you could send only what changed: a tiny record that says "line 2 becomes this, line 3 becomes that," and let the other side apply it exactly.
That tiny record is called a patch, and the command that applies it is called patch. It is one half of a pair. Its partner, diff, writes down what changed. patch reads that record and edits the old file to match the new one. This lesson is all of patch.
The black boxes in this lesson are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. You are inside a folder called change. It holds server.conf (the old file), server.conf.new (the fixed version), and change.patch (the record of what differs). At the end of the module one real Linux machine boots just for you, and you run the full mission there.
patch never works alone. First diff compares two files and writes the differences into a patch file. Then patch reads that patch file and edits the old file so it matches the new one. Learn the two-step shape once:
diff -u old.txt new.txt > change.patch makes the patch file.patch old.txt < change.patch applies it, editing old.txt to match new.txt.The > sends diff's output INTO a file. The < feeds that file back INTO patch. diff is its own lesson; here you only need to know it produced change.patch for you already. Look at what is inside that patch file:
cat change.patch
prompt: student@linuxcamp:~/change$ answer: cat change.patch output: --- server.conf +++ server.conf.new @@ -1,3 +1,3 @@ host = localhost -port = 8080 -debug = false +port = 9090 +debug = true
That is a unified diff, the format diff -u produces. The --- and +++ lines name the old and new files. The @@ -1,3 +1,3 @@ line is a hunk header: it says "this change touches 3 lines starting at line 1." Then comes the body. A leading space means a line that stays the same. A - means a line to remove. A + means a line to add. So this patch removes the old port and debug lines and adds the new ones. On a real machine the --- and +++ lines also carry file timestamps, which differ from run to run; ignore them, the change itself is what matters.
Now feed that patch file into patch. The shape is patch <oldfile> < <patchfile>: name the file to edit, then use < to pour the patch file into patch. When it works, patch prints one calm line telling you which file it touched.
Apply the fix to server.conf:
patch server.conf < change.patch
prompt: student@linuxcamp:~/change$ answer: patch server.conf < change.patch output: patching file server.conf hint: Name the file, then feed the patch in with a less-than sign: patch server.conf < change.patch
patching file server.conf. That single line is patch telling you it succeeded and which file it rewrote. There is no drama and no diff printed back; a quiet success line is exactly what you want. Your server.conf now reads port = 9090 and debug = true, identical to server.conf.new. You shipped a two-line record and the old file caught up.
Applying a change is only half a safety net. Sometimes the fix was wrong and you need the old file back. patch -R reverses the same patch: it reads the record backwards, turning every add into a remove and every remove into an add. Same patch file, opposite direction. -R is short for reverse.
You just applied change.patch. Now undo it with the very same file:
patch -R server.conf < change.patch
prompt: student@linuxcamp:~/change$ answer: patch -R server.conf < change.patch output: patching file server.conf hint: Add -R to reverse it, same patch file as before: patch -R server.conf < change.patch
The success line looks identical, patching file server.conf, but the direction flipped. server.conf is back to port = 8080 and debug = false, its original state. One patch file gives you both a forward gear and a reverse gear: patch to apply, patch -R to undo. That reversibility is why patches are the safe way to ship a change.
Before touching a real file you often want to know "will this patch even apply cleanly?" without changing anything yet. The --dry-run flag does exactly that: it runs the whole check but writes nothing to disk. Notice the verb in its output changes from patching to checking, a deliberate signal that no edit happened.
Test the patch against the untouched server.conf without applying it:
patch --dry-run server.conf < change.patch
prompt: student@linuxcamp:~/change$ answer: patch --dry-run server.conf < change.patch output: checking file server.conf hint: Add --dry-run before the filename: patch --dry-run server.conf < change.patch
checking file server.conf, not patching. That word swap is patch promising it looked but did not touch. The file on disk is unchanged. --dry-run is the habit to build before applying a patch you are unsure of: if it would fail, you find out here, safely, instead of on the live file.
A patch describes a change against a file it expects to look a certain way. If the file already changed, the patch no longer lines up, and patch refuses to guess. It reports the hunk that FAILED and, instead of throwing the change away, saves the unusable part into a reject file ending in .rej so you can apply it by hand.
Here server.conf was edited by someone else first, so it no longer matches what change.patch expects. Try to apply the patch anyway:
patch server.conf < change.patch
prompt: student@linuxcamp:~/change$ answer: patch server.conf < change.patch output: patching file server.conf Hunk #1 FAILED at 1. 1 out of 1 hunk FAILED -- saving rejects to file server.conf.rej hint: Same apply command; the point is to read the FAILED message it prints: patch server.conf < change.patch
Hunk #1 FAILED at 1. means the first chunk of the change did not match the file at line 1, because the file already moved on. 1 out of 1 hunk FAILED -- saving rejects to file server.conf.rej tells you the whole change was rejected and parked in server.conf.rej. What to check first: has the target file already been edited? A .rej file almost always means the patch was written against an older version of the file. Compare the .rej against the current file and apply the change by hand.
The other error is not about the target file, it is about the patch file. If the patch was truncated in an email, corrupted on download, or hand-edited badly, patch cannot read it and stops with a malformed patch message that names the exact line where it choked. The folder has such a broken file, malformed.patch.
Try to feed the broken patch into patch:
patch server.conf < malformed.patch
prompt: student@linuxcamp:~/change$ answer: patch server.conf < malformed.patch output: patching file server.conf patch: **** malformed patch at line 4: GARBAGE LINE WITH NO LEADING SPACE OR SIGN hint: Same shape, this time the input file is the broken one: patch server.conf < malformed.patch
patch: **** malformed patch at line 4: ... means patch hit a line inside the patch file it could not understand and gave up at that exact line. Every body line in a valid patch must begin with a space, a +, or a -; line 4 here began with a plain letter, so the format broke. What to check first: is the patch file complete and untouched? Re-download or re-generate it with diff -u rather than trying to hand-repair it.
You will meet one flag constantly when patches come from projects rather than a single folder: -pN. Patch files from tools like git carry long path names such as a/src/server.conf. -pN strips the first N path pieces off those names so patch can find your local file. The common value is -p1, which drops that leading a/ or b/.
You do not need it on the flat change.patch in this folder, whose names are already bare. Just know the shape: when a downloaded patch complains it "can't find file to patch," -p1 is the first thing to try. There is nothing to type here; carry the recognition into the next drill.
Rule of thumb: patches you make yourself with diff -u in one folder need no -p. Patches you download from a git project almost always need -p1. If patch says it cannot find the file, adjust the number: -p0 strips nothing, -p1 strips one level, and so on.
Scaffolding off. No command is printed this time. You have every piece you need.
The fix in change.patch was applied to server.conf, and now you have decided it was a mistake. You want to roll server.conf back to exactly how it started, using the same change.patch file you already have, without editing the file by hand. Recall the flag that runs a patch in reverse, and point it at server.conf.
prompt: student@linuxcamp:~/change$ answer: patch -R server.conf < change.patch output: patching file server.conf hint: Reverse means the -R flag, fed the same patch file: patch -R server.conf < change.patch
patching file server.conf, from memory, and the file is back to port = 8080 and debug = false. You picked -R because you wanted the undo direction, and you reused the same change.patch because one patch file drives both gears. That is the whole safety loop: apply with patch, undo with patch -R, and check first with --dry-run. It is exactly the recall the real machine will ask of you.
You earned this cheat sheet. Every row is a form you have already run or seen:
The two errors to recognise on sight: Hunk #1 FAILED ... saving rejects to file X.rej means the target file already moved on, and patch: **** malformed patch at line N means the patch file itself is broken. The one idea under all of it: diff records a change, patch applies it, and -R takes it back.
Add -b when you apply a patch to something precious. It writes a .orig copy of the file before editing, so even without the patch file you can always restore the original. Backup first, patch second, is a habit that has saved many engineers.
The practice terminal has shown you every move of patch: read the patch file, apply it, reverse it with -R, test it with --dry-run, and read the two failures, a rejected hunk and a malformed patch. You also learned -b for a backup and -p1 for git-style paths. Every command you typed yourself.
The Text Processing module ends with one real Linux machine, the Text Processing capstone mission, and that is where you apply and undo a real change for yourself. A VM boots just for you, with its own files. Its objectives use exactly what you practiced across this module: cutting, sorting, translating, and comparing text, and now shipping a change with diff and patch. One difference from here: the mission shows no commands. You read the objective, recall the command, and type it. That recall is what makes it stick.
Finish the other Text Processing lessons, then go apply a real patch for yourself.
Practice patch in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.