# GitError when another user tries to add my package from shared file server

**URL:** <https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466>\
**Category:** Package Management\
**Tags:** pkg\
**Created:** [September 17, 2025, 5:35pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466 "2025-09-17T17:35:51Z")\
**Posts on this page:** 14\
**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:** [September 17, 2025, 5:35pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/1 "2025-09-17T17:35:51Z")

</div>

I am able to add and use this package without issue, but if anyone else at my company tries to use it, they get this error. How can I permit anyone with access to the network drive to use my packages?

Input:

```julia-auto
Pkg.add(path="S:\\Julia\\Packages\\KM620")

```

Output:

```julia-auto
ERROR: GitError(Code:EOWNER, Class:Config, repository path 'S:/Julia/Packages/KM620/' is not owned by current user)

```

---

<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:** [September 17, 2025, 5:44pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/2 "2025-09-17T17:44:40Z")

</div>

Google says:

> Git now checks if the owner of a repository directory matches the user executing Git commands. If they do not match, Git raises this error to prevent potential security vulnerabilities where a malicious actor could exploit a repository owned by another user.
> 
> You can explicitly tell Git to trust a specific repository path by adding it to the `safe.directory` configuration.
> 
> ```julia-auto
> git config --global --add safe.directory "/path/to/your/repository"
> 
> ```

but my users will (likely) not have Git installed on their Windows systems.

Is there a way to bypass this security check from my end?

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [September 17, 2025, 6:12pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/3 "2025-09-17T18:12:54Z")

</div>

Not sure how to avoid this from your side, but two alternatives come to mind right now:

- Does `develop` work for your use case? (I’m not sure: Does `Pkg.add` actually create a copy in the user depot when used with a local path? `develop` happily handles local packages also when they are not git repos, so it might work here.)

```julia
Pkg.develop(path="<path/to/package>")

```

- I found LocalRegistry.jl very useful for in-house sharing of packages. It has a bit of overhead setting it up, but is worth it in my opinion because from the user perspective it’s a one-time setup of the registry and then it works just like the General registry

---

<div class="post-metadata">

**Author:** ![dilumaluthge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dilumaluthge/32/29283_2.png) [@dilumaluthge](https://discourse.julialang.org/u/dilumaluthge)\
**Post date:** [September 17, 2025, 6:41pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/4 "2025-09-17T18:41:13Z")

</div>

I agree with Sevi; a [LocalRegistry](https://github.com/GunnarFarneback/LocalRegistry.jl) and/or [LocalPkgServer](https://github.com/GunnarFarneback/LocalPackageServer.jl) might be good options for you to consider.

---

<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:** [September 17, 2025, 6:49pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/5 "2025-09-17T18:49:24Z")

</div>

`Pkg.develop` did work! It seems considerably slower though since now the code must run directly off the network drive.

I will need to figure out LocalRegistry.jl eventually, but I’ve yet to bite that bullet. I’ve looked through the documentation, and it’s all over my head. Seems a lot of work to just share a package.

> [@dilumaluthge](#):
>
> a [LocalRegistry](https://github.com/GunnarFarneback/LocalRegistry.jl) and/or [LocalPkgServer](https://github.com/GunnarFarneback/LocalPackageServer.jl)

What’s the difference?

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [September 17, 2025, 7:44pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/6 "2025-09-17T19:44:35Z")

</div>

> [@Nathan\_Boyer](#):
>
> `Pkg.develop` did work! It seems considerably slower though since now the code must run directly off the network drive.

Ah yes, so it seems like `add` really creates a local copy (the docstring from `pkg>?add` mentions the restriction that the package has to be a git repo). Using a shared directory directly is anyhow not a good idea since updates to the code will propagate to every user immediately. A hacky workaround would be that users first locally copy the package and then run `develop` on it 😅 It could be automated with a small Julia function or shell script though.

> [@Nathan\_Boyer](#):
>
> What’s the difference?

I haven’t used LocalPkgServer myself, but it’s also not required for LocalRegistry to work. This is my (limited) understanding of these two tools:

- LocalRegistry sets up a regular git repository which resides somewhere (ideally online, reachable by everyone who wants to use it). As a registry, it simply contains a list of packages, where to find them, and which versions of the packages have been registered in it. So when someone runs `Pkg.add` or similar, Julia will pull the latest version of this remote registry to the local machine and look up what the existing versions of the package are and where to find them (including dependencies, etc.). It’s really just a directory with files for each packages containing URLs and git commit information for each registered version and their dependencies/compat information. The repo will look like the one here, just that there are only the packages you registered locally: [GitHub - JuliaRegistries/General: The official registry of general Julia packages](https://github.com/JuliaRegistries/General/tree/master)
- The PkgServer is a completely separate entity that acts as a “middleman” between your Julia process and the registry and/or actual code of the packages you are `add`ing. In principle it’s not required if I understand correctly. When installing/updating/… a package, `Pkg` will look in the registry for the most up-to-date information, and then just take the package code from the URL (e.g. Github) stored in the registry. The package server somehow helps streamlining this process for potentially many different storage locations (Github, Gitlab, …) and reduce traffic over the network by caching stuff etc. This issue contains a comprehensive write-up (that I didn’t read entirely 😅 ) [Proposal: Pkg & Storage Protocols · Issue #1377 · JuliaLang/Pkg.jl · GitHub](https://github.com/JuliaLang/Pkg.jl/issues/1377) But Julia can just find packages at standard URLs that point to git repos without a package server.

The point is that `Pkg` operations work most smoothly when there is a registry holding all the relevant information about the packages – plus you get versioning of your packages for free. So LocalRegistry.jl lets you create such a private git repo holding this information and anyone who you give access to it can run `Pkg.Registry.add(url="...")` once to permanently add this registry to their Julia depot and afterwards they will (in principle) not notice anymore that a package comes from the General registry or from your local one.

That’s the big constraint though, that your registry needs to reside in some location reachable with an URL and with git support. In our case, we have a local GitLab installation that hosts this repository.

The actual package code then needs to reside in (potentially different) locations, but I’m pretty sure it also needs to be a git repo with corresponding URLs. If you just want to install a package from the local registry, `Pkg.add` should just work™, but if you want to register a new (version of a) package, you need to also have write access to the remote git repo. LocalRegistry.jl will take care of updating the git repo with the registry in a consistent way (through the function `LocalRegistry.register` which you need to call from the machine from which you want to register the current code to the registry.

---

<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:** [September 17, 2025, 8:22pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/7 "2025-09-17T20:22:26Z")

</div>

> [@Sevi](#):
>
> Using a shared directory directly is anyhow not a good idea since updates to the code will propagate to every user immediately.

My current workaround for this is that I keep the master development code on my local machine and a private GitHub repository. Then I just `git clone` and `git pull` to the shared server to _release_ a new version.

> [@Sevi](#):
>
> That’s the big constraint though, that your registry needs to reside in some location reachable with an URL and with git support. In our case, we have a local GitLab installation that hosts this repository.

I’m confused about the requirements and best setup options for me. I’m the only person doing any coding here, so we don’t have any infrastructure around these things. Can I have a public GitHub registry that points to local (private) server packages? I don’t want to have to set up GitHub accounts and ssh keys for everyone. Or should I set it all up on the network drive despite the recommendation not to?

> “The recommended way to manage local packages and a local registry is by using a web-based git hosting service such as GitHub, GitLab, or Bitbucket - either public or private or in-house. However, it is also possible to do this on a shared or network filesystem, or on a single computer.”

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [September 17, 2025, 9:01pm UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/8 "2025-09-17T21:01:30Z")

</div>

> [@Nathan\_Boyer](#):
>
> I’m confused about the requirements and best setup options for me. I’m the only person doing any coding here, so we don’t have any infrastructure around these things. Can I have a public GitHub registry that points to local (private) server packages? I don’t want to have to set up GitHub accounts and ssh keys for everyone. Or should I set it all up on the network drive despite the recommendation not to?

Ah, I wasn’t aware that shared filesystems are also supported. But yes, you can also have the registry completely public and have it point to private locations (then everyone could add the registry, but when they try to install packages from that registry, they will be prompted for some kind of authentication – and note that the URLs/paths/… of your private packages will be visible in the public git repo).

I think setting everything up on the shared file system _might_ be the most straightforward for your current situation, if you can ensure that the paths to the packages and the registry are identical on all machines of your users. But you could just try it with a dummy package.

The [doc page](https://github.com/GunnarFarneback/LocalRegistry.jl/blob/master/docs/shared_filesystem.md)\* that you quoted shows a nice example: I just tried these to set up a registry on a shared Nextcloud folder and it seems to work fine. I am on Mac though, so I’m not sure what pitfalls Windows holds in store.

But I think the biggest issue will be local paths. When you register a package with LocalRegistry.jl and put everything on the shared filesystem, you set the package git repo’s upstream remote location to a `file://...` URL that will then be “hard-coded” into the registry when you register the package. Every machine that wants to install this package will get the same URL and it needs to point to the same folder. The same holds true for the registry itself.

So if all users can find the package under `"S:\\Julia\\Packages\\KM620"` then the URL `file:///s:/Julia/Packages/KM620` should resolve fine. Or if you have a host named `server-name` in the local network, you could write `file://server-name/Julia/Packages/...` etc.

But if for example user A has the package under `S:\\Julia\\Packages\\KM620` and user B under `T:\\Julia\\Packages\\KM620` it will not work.

* * *

\* Shout out to @GunnarFarneback for creating this package and also the nice examples in the docs!

---

<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:** [September 18, 2025, 1:21am UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/9 "2025-09-18T01:21:02Z")

</div>

> [@Sevi](#):
>
> When you register a package with [LocalRegistry.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/LocalRegistry) and put everything on the shared filesystem, you set the package git repo’s upstream remote location to a `file://...` URL that will then be “hard-coded” into the registry when you register the package.

Doesn’t that make this an issue again?

> [@Sevi](#):
>
> Using a shared directory directly is anyhow not a good idea since updates to the code will propagate to every user immediately.

Where would I develop the package? Can you `git push` to folders?

Is there a way to still keep a copy on GitHub as a backup (even if the master lives on the file server)?

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [September 18, 2025, 7:31am UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/10 "2025-09-18T07:31:36Z")

</div>

> [@Nathan\_Boyer](#):
>
> Doesn’t that make this an issue again?

As long as all machines can understand the URL correctly, it should work. But that depends on the details of your setup – so I can’t tell whether it will work in your particular case without knowing more details.

At the moment I imagine it like this:

- you have a local git repo in path `C:\some\local\path\KM620`
- the repo is connected with a remote/upstream repo on github, but only you can access it at the moment (and setting up SSH/Token access for every user is too cumbersome)
- there is a shared file system, which you can reach on your machine as drive “S”, so you can copy the package to `S:\Julia\Packages\KM620`
- Other users can access that location as well and see the package files

But the main question is: Can every user access the literal path `S:\Julia\Packages\KM620`? If not, then using the “file URL” `file:///s:/Julia/KM620` won’t work. So to use the (local) registry you would definitely need a URL that resolves to the same location for all users and is accessible.

* * *

**But**  
Now that I think about it, I’m not sure whether that solves the original git permissions problem. I suspect that in the end, Julia would still try to install the package from a local directory and complain about the file permissions.

Here’s another idea on how to avoid the git issue in the first place: use the Git.jl package and run this once per user that wants to install the package:

```julia
# add Git first, e.g. to a temporary environment

using Git
run(`$(git()) config --global --add safe.directory "/path/to/your/shared/repository"`)

```

I just tried this by first manually changing the file ownership of a repo on my local machine to reproduce the `GitError(Code: EOWNER, ...)` and after running the code above I could add the package just fine. I do also have git installed on my local machine, but I expect that the global config should also be used by Pkg (not sure though).

> [@Nathan\_Boyer](#):
>
> Where would I develop the package? Can you `git push` to folders?

As far as I can tell from testing it, `git` understands the “file URL” just as any other URL, so yes, you can push/pull to/from a local folder. It should also be possible to add more than one remote to a git repo, so you could have

- a local repo for development
- its corresponding remote repo on github
- another remote repo in the shared filesystem

The remote repo could basically be a “mirror” for the one on github (I found this SO post on [how to push](https://stackoverflow.com/a/14290145) to both simulataneously)

---

<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:** [September 18, 2025, 7:49am UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/11 "2025-09-18T07:49:09Z")

</div>

> [@Nathan\_Boyer](#):
>
> but my users will (likely) not have Git installed on their Windows systems.

That’s a small impediment if they have Julia installed.

```julia-auto
using Pkg
Pkg.add("Git")
using Git
run(`$(Git.git()) config --global --add safe.directory "/path/to/your/repository"`)

```

For what it’s worth, all that does is to add the lines

```julia-auto
[safe]
	directory = /path/to/your/repository

```

to the global git config file, which on my Linux computer is located at `/home/gunnar/.gitconfig`. I.e. any other method to add these lines to the appropriate file would work equally well.

---

<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:** [September 18, 2025, 8:17am UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/12 "2025-09-18T08:17:03Z")

</div>

> [@Nathan\_Boyer](#):
>
> What’s the difference?

The LocalRegistry package provides tooling to make your packages behave like the public packages in the General registry, so that the package manager can keep track of multiple versions, resolve compatibility constraints, know where they are located, etc. For the users the most obvious difference is that they can refer to the package (in the package manager) just by its name and not by a full path. They still need to be able to access the packages’ repositories as well as the registry’s repository.

The LocalPackageServer package relaxes the last requirement so that the local packages are delivered by http/https instead of via git. Then the users no longer need to be able to access any repositories. One limitation is that this only covers registered versions of the packages. You also need to have a computer on your local network that can run the package server 24/7 (or at least whenever someone might want to download a package).

---

<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:** [September 18, 2025, 8:24am UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/13 "2025-09-18T08:24:38Z")

</div>

> [@Sevi](#):
>
> I do also have git installed on my local machine, but I expect that the global config should also be used by Pkg (not sure though).

Pkg (by default) uses LibGit2 for git operations and LibGit2 does indeed read the config.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [September 18, 2025, 8:31am UTC](https://discourse.julialang.org/t/giterror-when-another-user-tries-to-add-my-package-from-shared-file-server/132466/14 "2025-09-18T08:31:07Z")

</div>

> [@GunnarFarneback](#):
>
> Pkg (by default) uses LibGit2 for git operations and LibGit2 does indeed read the config.

Good to know!

@Nathan_Boyer sorry for the lengthy tangent about local registries 😅 I still recommend using them if you have the infrastructure for it, but for now just using a Julia-packaged git, as @GunnarFarneback suggested, seems like the best solution. Hope it solves your issue.
