In short
To see what changed between two versions of a formula, compare them line by line on material id and report two things for each line: its own change in weight or dilution, and its change in share. The second matters because a line whose weight is untouched still changes its share when anything else changes. A diff is only half the record; the other half is the reason for each change.
What you will learn
- Compute a diff of two formula versions keyed on material id, classifying lines as added, removed, changed or unchanged
- Explain why an unchanged weight can still change its share, and report both
- Keep version history with reasons, in the app and in plain files
- Use text-based version control for formula records, and know its limits
Before this lesson: Fragrance Calculations in Python, Checked, Compare Two Versions Blind: Study Guide, Formula Design and Iteration Log
Before you start
You need the program from fragrance calculations in Python, the habits of comparing versions and the iteration log. This is an external exercise.
A diff in a few lines
def pure_by_material(lines):
out = {}
for material, weight, dilution in lines:
out[material] = out.get(material, 0.0) + weight * dilution / 100
return out
def diff(old, new):
a, b = pure_by_material(old), pure_by_material(new)
ta, tb = sum(a.values()), sum(b.values())
rows = []
for m in sorted(set(a) | set(b)):
pa, pb = a.get(m, 0.0), b.get(m, 0.0)
ra, rb = 100 * pa / ta, 100 * pb / tb
kind = ("added" if m not in a else "removed" if m not in b
else "changed" if abs(pa - pb) > 1e-9 else "same")
rows.append((m, kind, round(pa, 4), round(pb, 4), round(rb - ra, 4)))
return rows
Summing by material before comparing also merges two lines of one material, which removes the duplicate-id weakness of the earlier program.
Worked example
Version 1: bergamot FCF 30 g, Hedione 25 g, Iso E Super 20 g, Ambroxan 5 g at 10%. Version 2 lowers Iso E Super to 15 g and adds 2 g of Timberol at 10%. The diff (pure grams, then change in relative share, in points):
| Material | Status | Pure v1 → v2 (g) | Share change |
|---|---|---|---|
| Iso E Super | changed | 20 → 15 | −5.27 |
| Timberol | added | 0 → 0.2 | +0.28 |
| Bergamot FCF | same | 30 → 30 | +2.70 |
| Hedione | same | 25 → 25 | +2.25 |
| Ambroxan | same | 0.5 → 0.5 | +0.05 |
A reader who saw only "Iso E Super reduced, Timberol added" would miss that bergamot rose by nearly three points. Whether that matters is for the nose, but the record should not hide it.
In the RUŌOD Lab app
The app keeps versions by duplication. Duplicate makes a new formula named after the original with a version number (Amber v2), and the list marks each formula with its version and how many copies exist; the original is never changed. It has no side-by-side comparison. To diff, export each version (one formula at a time is available on every plan; see pricing for bulk export) as CSV or JSON, and run a comparison like the one above. The versions and reports tutorial shows those steps.
Text-based version control
Formulas stored as CSV or JSON files can be kept in a version-control system such as Git: every change becomes a commit with a message, and the history shows who changed what and when. Two cautions. Line-based text diffs know nothing about formulas, so a reordered file looks heavily changed; diff on ids as above for meaning. And a repository holding confidential formulas is itself confidential: never push one to a public service.
Where it stops
- A diff describes, it does not evaluate. A two-point share change can be invisible or decisive.
- Stocks must be identified. If v2 uses a new 10% dilution of Timberol made on another day, the stock id should differ, so that a bad dilution is traceable.
Practical exercise: Diff five versions of one formula
- Take a formula you developed through at least five versions, from your log or from the app.
- Export or transcribe each version as rows of (material id, weight, dilution).
- Diff each consecutive pair. For every change, quote the reason from your log; for every share drift above one point, note whether you intended it.
- Write one paragraph per version on what the diff shows that your log did not record.
You have done this well if every diff is keyed on ids, both weight changes and share drift are reported, every deliberate change has a reason from the time it was made, and you identify at least one unintended share drift.
Common mistakes
- Diffing by line position. A reorder is not a reformulation.
- Reporting only weights. Shares carry the olfactory meaning.
- Editing an old version to "fix" it. Make a new one and record why.
Key terms
- Diff
- A list of the differences between two versions of a record. For a formula, keyed on material id, with each line marked added, removed, changed or unchanged.
- Share drift
- The change in a line's percentage caused by changes elsewhere in the formula, with its own weight unchanged.
- Commit message
- In version control, the short statement saved with each change saying why it was made. For formulas, the equivalent of the reason column in an iteration log.
Knowledge check
Written and reviewed by the RUŌOD Lab team. This is general education, not legal, regulatory, medical or safety advice. Example dilutions and exercises are for learning, are not validated products, and have not been safety-assessed. Completing a lesson confers no qualification. How we check these lessons.