# How to Best Keep Distinct Package Editions

**URL:** <https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424>\
**Category:** Package Management\
**Created:** [July 22, 2026, 4:26pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424 "2026-07-22T16:26:38Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [July 22, 2026, 4:26pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/1 "2026-07-22T16:26:38Z")

</div>

I have [a package](https://github.com/nathanrboyer/Div3.jl) which reproduces equations from a professional standard that is revised every two years. I need to be able to access specific editions of the package which are linked to specific editions of the standard document e.g. _2025 Edition_. What is the best way to smoothly achieve that?

I used to make a new package with the year in the package name, but that was a lot of work, and realistically, the content of the standard doesn’t change much, if at all, between editions. I’m currently considering two new options (but am open to others).

1. Keep persistent git branches e.g. `2025`.
2. Hijack the release version number to use year as the “major” digit e.g. `2025.0.0`.

Which method do you think would cause the least friction for my internal users?  
(I intend to register this package with LocalRegistry.jl using a local file server for others in my company, but I am still setting that up.)

---

<div class="post-metadata">

**Author:** ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)\
**Post date:** [July 22, 2026, 5:19pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/2 "2026-07-22T17:19:31Z")

</div>

If you change the major version it will be impossible to load both versions in the same Julia process.

If most of the standard doesn’t change you can keep the same package but version the functions and constants inside the package. Like

```julia
foo2023(a, b, c) = a + b + c

const foo2025 = foo2023

```

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [July 22, 2026, 5:19pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/3 "2026-07-22T17:19:59Z")

</div>

I think the best approach is to create a single package where each version is a module (aka `Version.jl`). You move all the commonalities into a single top module, then have dedicated sub modules for the version specific details. That also makes it really clear to users what changes from one to the next version. It also avoids clashing definitions and gives you a clear namespace for each specific version.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [July 22, 2026, 5:39pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/4 "2026-07-22T17:39:05Z")

</div>

> [@nhz2](#):
>
> If you change the major version it will be impossible to load both versions in the same Julia process.

That has nothing to do with major versions. You can only load one version of a given package in the same process, no matter in what way the version numbers differ.

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [July 22, 2026, 6:24pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/5 "2026-07-22T18:24:52Z")

</div>

I will typically not need to access multiple Editions in the same Julia process. They would be used in separate analyses.

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [July 22, 2026, 6:59pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/6 "2026-07-22T18:59:49Z")

</div>

I don’t think I like this idea because it forces me to change all my downstream function calls in the packages using this package e.g. from `Div3.2023.KM6.f(x)` to `Div3.2025.KM6.f(x)`. I would rather load a specific version of `Div3.jl` into an environment and have the function definitions update in place when called by a downstream package there e.g. as `Div3.KM6.f(x)`. I have tried to reproduce the source text as closely as possible, giving the equations the same names in the same order, so I am reluctant to scramble them into different common or edition-specific modules.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [July 22, 2026, 7:13pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/7 "2026-07-22T19:13:05Z")

</div>

> [@Nathan\_Boyer](#):
>
> I don’t think I like this idea because it forces me to change all my downstream function calls in the packages using this package e.g. from `Div3.2023.KM6.f(x)` to `Div3.2025.KM6.f(x)`

No it doesn’t. Because you can just do

```julia
julia> module A

       module B

           f(x) = x^2

       end

       module C

           f(x) = x^3

       end

       end
Main.A

julia> using .A.B: f

julia> f(2)
4

```

You want to switch versions for an entire package, you just do

```julia
julia> using .A.C: f

julia> f(2)
8

```

---

<div class="post-metadata">

**Author:** ![j-fu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/j-fu/32/11373_2.png) [@j-fu](https://discourse.julialang.org/u/j-fu)\
**Post date:** [July 22, 2026, 7:24pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/8 "2026-07-22T19:24:58Z")

</div>

See the approach in PhysicalConstants.jl. They use different modules for CODATA2014, CODATA2018 and CODATA2022 .

---

<div class="post-metadata">

**Author:** ![matthias314](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@matthias314](https://discourse.julialang.org/u/matthias314)\
**Post date:** [July 22, 2026, 9:35pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/9 "2026-07-22T21:35:37Z")

</div>

> [@Nathan\_Boyer](#):
>
> from `Div3.2023.KM6.f(x)` to `Div3.2025.KM6.f(x)`

As a variation of @langestefan’s answer, you could say

```julia-auto
import Div3.v2023 as Div3

```

at the beginning of your file (if the version is called `v2023`) and then later simply `Div3.KM6.f(x)`.

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [July 23, 2026, 1:16pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/10 "2026-07-23T13:16:53Z")

</div>

Hmm, the downside I see then is ever-expanding duplicate source code. I wonder if I should flip my question. Why might I **not** want to implement editions via each method?

1. as branches
2. as releases
3. as modules

Then I can pick my poison.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [July 23, 2026, 2:39pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/11 "2026-07-23T14:39:29Z")

</div>

> [@Nathan\_Boyer](#):
>
> Hmm, the downside I see then is ever-expanding duplicate source code

If you use proper abstraction you should be able to avoid this. Put the common parts into functions shared across modules, but dispatch to version specifics where you need to.

> [@Nathan\_Boyer](#):
>
> 1. as branches

Many reasons why this is a bad idea… for one, it does not avoid your code duplication concern. I think it makes it worse, or even unavoidable. Github code search only indexes the main branch, see [About GitHub Code Search - GitHub Docs](https://docs.github.com/en/search-github/github-code-search/about-github-code-search#limitations). For N versions you’ll need N PRs to fix anything etc etc.

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [July 23, 2026, 2:59pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/12 "2026-07-23T14:59:18Z")

</div>

> [@langestefan](#):
>
> If you use proper abstraction you should be able to avoid this. Put the common parts into functions shared across modules, but dispatch to version specifics where you need to.

I’m not quite sure what this would look like.  
What goes in `module Common` if the definitions are as below?

- `f(x) = x^2` for 2021 - 2023
- `f(x) = x^3` for 2025
- `g(x) = x/2` for 2021
- `g(x) = x/3` for 2023 - 2025

I’m guessing I can do something like below to avoid rewriting the functions each time? (I don’t know the actual syntax yet.)

```julia-auto
module Ed2025
f(x) = x^3
g = ..Ed2023.g
end
```

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [July 23, 2026, 3:19pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/13 "2026-07-23T15:19:10Z")

</div>

> [@Nathan\_Boyer](#):
>
> What goes in `module Common` if the definitions are as below?

For example:

```julia
julia> module Div3

       module Impl
           "f, introduced 2021"
           f_2021(x) = x^2
           "f, revised 2025"
           f_2025(x) = x^3

           g_2021(x) = x/2
           g_2023(x) = x/3
       end

       module Ed2021
           import ..Impl
           const f = Impl.f_2021
           const g = Impl.g_2021
       end

       module Ed2023
           import ..Impl
           const f = Impl.f_2021
           const g = Impl.g_2023
       end

       module Ed2025
           import ..Impl
           const f = Impl.f_2025
           const g = Impl.g_2023
       end

       end
Main.Div3

```

then you can do:

```julia
julia> using .Div3.
Ed2021
Ed2023
Ed2025
Impl

julia> using .Div3.Ed2023: 
eval
f
g
include
julia> using .Div3.Ed2023: f, g

julia> f(2)
4

julia> g(2)
0.6666666666666666

```

And maybe even cleaner. Something based on singletons like

```julia
abstract type Edition end
struct Ed2021 <: Edition end
struct Ed2025 <: Edition end

h(::Ed2021, x) = 1.5x
h(::Ed2025, x) = 1.6x

```

This one can be combined with Preferences.jl to set a global version. Many possible flavours of this recipe

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [July 23, 2026, 5:46pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/14 "2026-07-23T17:46:02Z")

</div>

A potential complication with the module method is that I am using Pluto notebooks as source code to get math rendering for function definitions. I’m not sure if I would be able to still render the functions as math if I pull their definition from other modules/notebooks. Maybe a special type that stores the function with its `LaTeXString` …

```julia-auto
module Div3

module KM6
include("KM6.plutojl")
end # module KM6

module KD2
include("KD2.plutojl")
end # module KD2

module KD4
include("KD4.plutojl")
end # module KD4

end # module Div3

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/0/c/0cf2c45058a8cbeec2ea5639310dd1d32bd0c669.png)

Anyway, what’s the downside to using major Releases as Editions?

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [July 23, 2026, 5:59pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/15 "2026-07-23T17:59:41Z")

</div>

> [@Nathan\_Boyer](#):
>
> Anyway, what’s the downside to using major Releases as Editions?

You would never be able to use functions from two different versions within the same environment. So that rules out comparisons of any kind for all your users. Besides it just abusing a system which it was never intended for in the first place. I doubt such a hack would even be accepted in the general registry. Now that I think of it how would even register a package which is spread across multiple releases?

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [July 23, 2026, 8:08pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/16 "2026-07-23T20:08:21Z")

</div>

> [@Nathan\_Boyer](#):
>
> I will typically not need to access multiple Editions in the same Julia process. They would be used in separate analyses.

I’d expect that a lot of final deliverables could profit from a low-effort way of including analyses according to multiple (all!) standard versions.

E.g. “this boiler is happy up to 85.2C in 1998-2013, up to 81.5C in 2014-2021, and up to 80.0C in 2022-2025”.

User then has the relevant information to know whether to fight over the relevant date (…some of the work/signatures happened in '21, some got delayed into '22. It’s always complicated, and sometimes up to interpretation).

Poweruser who needs to develop and maintain intuitions over all the editions and differences between them is empowered to do so.

---

<div class="post-metadata">

**Author:** ![herman435](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/herman435/32/222787_2.png) [@herman435](https://discourse.julialang.org/u/herman435)\
**Post date:** [July 23, 2026, 9:04pm UTC](https://discourse.julialang.org/t/how-to-best-keep-distinct-package-editions/138424/17 "2026-07-23T21:04:59Z")

</div>

I would recommend to go with versioning rather than separate branches or package names. Using something like 2025.x.y, 2027.x.y, etc makes it obvious which standard a release matches while still letting you publish bug fixes for each edition. Its also easier for users to pin a specific version through the package manager than having to switch branches.
