@@ -22,7 +22,32 @@ The full lifecycle looks like this:
22221. :ref: `patching-create ` — capture local edits as a ``.patch `` file with ``dfetch diff ``
23232. :ref: `patching-wire ` — reference the patch from the manifest so it is applied on every fetch
24243. :ref: `patching-update ` — refresh the patch as your edits evolve with ``dfetch update-patch ``
25- 4. :ref: `patching-upstream ` — reformat the patch for upstream use with ``dfetch format-patch ``
25+ 4. :ref: `patching-upstream-bump ` — re-apply your patch when you move to a new upstream version
26+ 5. :ref: `patching-upstream ` — reformat the patch for upstream use with ``dfetch format-patch ``
27+
28+ .. _patching-prereq :
29+
30+ Before you begin
31+ ----------------
32+
33+ *Dfetch * calculates the diff for a project by comparing the working tree
34+ against the revision recorded in the project's ``.dfetch_data.yaml `` metadata
35+ file. For that comparison to be meaningful, the fetched files should already
36+ be committed to your superproject's VCS — they become the baseline that the
37+ patch is measured against.
38+
39+ After fetching, commit before editing:
40+
41+ .. code-block :: console
42+
43+ $ dfetch update some-project
44+ $ git add some-project/
45+ $ git commit -m "vendor: add some-project v1.2.3"
46+
47+ You can then make edits to ``some-project/ `` and capture them with
48+ ``dfetch diff ``. Both committed and uncommitted edits are included in the
49+ generated patch, so you do not need to commit every intermediate step — only
50+ the clean upstream baseline matters.
2651
2752.. _patching-create :
2853
@@ -43,6 +68,13 @@ metadata file and writes a patch file named ``some-project.patch`` (or
4368
4469.. asciinema :: ../asciicasts/diff.cast
4570
71+ **What goes into the patch **
72+
73+ The diff captures all tracked modifications and any new untracked files in the
74+ vendored directory. Files ignored by your superproject's VCS (via
75+ ``.gitignore `` or ``svn:ignore ``) and the ``dfetch `` metadata file itself are
76+ always excluded.
77+
4678**Controlling which revisions are compared **
4779
4880By default, *Dfetch * uses the revision stored in the project's metadata as the
@@ -68,8 +100,8 @@ See :ref:`diff` in the command reference for all options.
68100Adding the patch to the manifest
69101---------------------------------
70102
71- Once you have a patch file, reference it from the project entry in
72- ``dfetch.yaml `` using the :ref: `patch ` attribute:
103+ Once you have a patch file, commit it to your repository and reference it from
104+ the project entry in ``dfetch.yaml `` using the :ref: `patch ` attribute:
73105
74106.. code-block :: yaml
75107
@@ -82,7 +114,23 @@ Once you have a patch file, reference it from the project entry in
82114 patch : some-project.patch
83115
84116 From this point on, every ``dfetch update `` will fetch the upstream source and
85- re-apply the patch on top.
117+ re-apply the patch on top. You can test the round-trip immediately:
118+
119+ .. code-block :: console
120+
121+ $ dfetch update --force some-project
122+
123+ The ``--force `` flag overwrites the working tree with the freshly fetched and
124+ patched version. Confirm the result looks right, then commit the manifest
125+ change and the patch file together.
126+
127+ **Organizing patch files **
128+
129+ Keep patch files alongside ``dfetch.yaml `` or in a dedicated subdirectory such
130+ as ``patches/ ``. *Dfetch * resolves patch paths relative to the manifest file,
131+ so as long as the path in the manifest matches the location on disk you have
132+ full flexibility. Committing the patch files to VCS ensures every team member
133+ and every CI run gets the same result.
86134
87135**Multiple patches **
88136
@@ -97,7 +145,9 @@ order:
97145
98146 Patches are applied in the order listed. A good convention is to prefix each
99147file name with a zero-padded number so they sort correctly and their purpose is
100- clear at a glance.
148+ clear at a glance. The ``dfetch update-patch `` command always updates the
149+ **last ** patch in the list, so the earlier patches represent stable, settled
150+ changes and the final one accumulates ongoing work.
101151
102152See :ref: `patch ` in the manifest reference for the full attribute syntax.
103153
@@ -106,22 +156,29 @@ See :ref:`patch` in the manifest reference for the full attribute syntax.
106156Refreshing a patch
107157------------------
108158
109- As your local edits evolve — or when the upstream version changes — the
110- existing patch file may no longer apply cleanly. Instead of manually
111- regenerating it, run:
159+ As your local edits evolve, the existing patch file may become stale. Instead
160+ of manually regenerating it, run:
112161
113162.. code-block :: console
114163
115164 $ dfetch update-patch some-project
116165
117- This regenerates the last patch for ``some-project `` from the current working
118- tree, keeping the upstream revision unchanged. It is safe to run repeatedly
119- as you iterate on the fix.
166+ This command:
120167
121- When the upstream version changes, *Dfetch * applies patches with fuzzy
122- matching, so a patch can survive minor context changes without needing an
123- immediate refresh. If the patch no longer applies at all, ``dfetch update ``
124- will report the failure and you can refresh with ``dfetch update-patch ``.
168+ 1. Re-fetches the upstream revision (without applying any patches).
169+ 2. Computes the diff between that clean baseline and your current working tree.
170+ 3. Overwrites the **last ** patch in the manifest list with the new diff.
171+ 4. Re-fetches the project and applies all patches so the working tree is left
172+ in the patched state.
173+
174+ It is safe to run repeatedly as you iterate on a fix. The upstream revision
175+ stays unchanged — only the patch file is updated.
176+
177+ .. note ::
178+
179+ ``update-patch `` requires the project directory to have **no uncommitted
180+ changes ** in the superproject. Commit or stash your work first, then run
181+ the command.
125182
126183.. asciinema :: ../asciicasts/update-patch.cast
127184
@@ -137,6 +194,52 @@ See :ref:`update-patch` in the command reference for all options.
137194
138195 .. scenario-include :: ../features/update-patch-in-svn.feature
139196
197+ .. _patching-upstream-bump :
198+
199+ Upgrading the upstream version
200+ -------------------------------
201+
202+ When you want to move to a new upstream release, update the ``tag ``,
203+ ``branch ``, or ``revision `` in ``dfetch.yaml `` and then run ``dfetch update ``.
204+ *Dfetch * fetches the new version and attempts to re-apply the patch using fuzzy
205+ matching, so patches often survive minor context changes automatically.
206+
207+ .. code-block :: console
208+
209+ $ # 1. Edit dfetch.yaml: change tag v1.2.3 → v1.3.0
210+ $ dfetch update some-project
211+
212+ Three outcomes are possible:
213+
214+ **Patch applies cleanly ** — you are done. Review the result, commit the
215+ updated manifest and the updated vendored files.
216+
217+ **Patch applies with fuzz warnings ** — the patch applied but the context lines
218+ shifted slightly. The files are in the correct state. Run
219+ ``dfetch update-patch some-project `` to refresh the patch against the new
220+ baseline so it stays clean for future upgrades:
221+
222+ .. code-block :: console
223+
224+ $ git add some-project/
225+ $ git commit -m "vendor: update some-project to v1.3.0"
226+ $ dfetch update-patch some-project
227+ $ git add some-project.patch
228+ $ git commit -m "patches: refresh some-project.patch for v1.3.0"
229+
230+ **Patch fails to apply ** — the upstream changes conflict with the local edits
231+ tracked in the patch. Resolve the conflict manually by editing the vendored
232+ files, then use ``dfetch update-patch `` to record the resolved state:
233+
234+ .. code-block :: console
235+
236+ $ # Manually resolve conflicts in some-project/
237+ $ git add some-project/
238+ $ git commit -m "vendor: update some-project to v1.3.0 with resolved conflicts"
239+ $ dfetch update-patch some-project
240+ $ git add some-project.patch
241+ $ git commit -m "patches: update some-project.patch for v1.3.0"
242+
140243 .. _patching-upstream :
141244
142245Contributing the patch upstream
@@ -152,10 +255,15 @@ for a project:
152255 $ dfetch format-patch some-project
153256
154257 This writes a ``formatted-some-project.patch `` file (or one file per patch if
155- there are several) that is ready to share with the upstream project.
258+ there are several) in the current directory. Use ``--output-directory `` to
259+ place the formatted files in a specific location:
260+
261+ .. code-block :: console
156262
157- Before sending it, do a dry-run check to confirm it applies cleanly to a local
158- clone of the upstream repository:
263+ $ dfetch format-patch some-project --output-directory patches/upstream
264+
265+ Before sending a patch, do a dry-run check to confirm it applies cleanly to a
266+ local clone of the upstream repository:
159267
160268.. tabs ::
161269
@@ -188,3 +296,41 @@ clone of the upstream repository:
188296.. asciinema :: ../asciicasts/format-patch.cast
189297
190298See :ref: `format-patch ` in the command reference for all options.
299+
300+ .. _patching-troubleshooting :
301+
302+ Troubleshooting
303+ ---------------
304+
305+ **"No diffs found" **
306+
307+ ``dfetch diff `` found no changes between the working tree and the upstream
308+ baseline recorded in ``.dfetch_data.yaml ``. If you expected changes, make
309+ sure the edits are in the vendored directory and are not excluded by your
310+ VCS ignore rules. If the metadata file is missing, run
311+ ``dfetch update some-project `` first to re-establish the baseline.
312+
313+ **Patch fails to apply after an upstream bump **
314+
315+ The upstream version introduced changes that conflict with the local edits
316+ in the patch. Follow the manual resolution workflow in
317+ :ref: `patching-upstream-bump `: edit the vendored files to the desired
318+ state, commit them, then run ``dfetch update-patch `` to regenerate the
319+ patch from the resolved working tree.
320+
321+ **"skipped — Uncommitted changes" **
322+
323+ ``dfetch update-patch `` detected unstaged or staged-but-uncommitted changes
324+ in the project directory. Commit or stash those changes before running the
325+ command so the patch calculation starts from a clean state.
326+
327+ **"skipped — the project was never fetched" **
328+
329+ Run ``dfetch update some-project `` first. The project must exist on disk
330+ before a patch can be updated.
331+
332+ **"skipped — there is no patch file" **
333+
334+ The project has no ``patch: `` entry in the manifest. Use
335+ ``dfetch diff some-project `` to create the initial patch, then add it to
336+ the manifest as described in :ref: `patching-wire `.
0 commit comments