Ensuring relative Git paths
Asked Answered
A

4

22

I've moved a Git repository (containing several submodules) to another directory on the local disk. Any git command produces the error:

fatal: Not a git repository: <absolute path to .git/modules/*>

The error is derived from absolute paths to files encoded in various places[1]. Two questions:

  • Is there a Git command for fixing these paths, i.e., making them relative?[2]
  • Is there a way to ensure that future Git repositories only use relative paths?[3]

Thanks!


Notes

  1. I notice that with all submodules, the .git file contains:

    gitdir: <absolute path to repository>
    

    The core.worktree parameter within each submodule (.git/modules/*/config) is set to the absolute path of that submodule.

  2. I'm not looking for a shell command, rather a native Git method.

  3. I'm not sure if absolute paths were created with an older version of Git, and newer that has since adopted relative paths.

Albigenses answered 8/6, 2012 at 18:12 Comment(6)
Fixed in git 1.7.10. a quickie sed -si on your configs should fix it up until you can upgrade.Calhoun
jthill: when you say it's fixed, do you mean only for repos that were init'ed or cloned using git 1.7.10+ ?Elmaelmajian
1.7.10 appears to fix this condition so all subsequent versions should maintain the fix.Albigenses
@DairaHopwood Once you have updated to 1.7.10+, you should clone the repository to fix itCommutator
I didn't see anything in the release notes to 1.7.10, but I did see something seemingly related in the 1.7.12 notes (github.com/git/git/blob/master/Documentation/RelNotes/…)Rehabilitation
I also have this issue on Ubuntu 16.04 with Git 2.7.4. If I clone a new repository, it uses absolute path everywhere.Guillermoguilloche
F
7

I wrote a oneliner (bash and coreutils required) that changes any .git gitdir file into a relative path:

find -type f -name .git -exec bash -c 'f="{}"; cd $(dirname $f); echo "gitdir: $(realpath --relative-to=. $(cut -d" " -f2 .git))" > .git' \;

And if you don't like find here's one with git submodule:

git submodule foreach --recursive '[[ -f .git ]] && echo "gitdir: $(realpath --relative-to=. $(cut -d" " -f2 .git))" > .git'
Fire answered 20/7, 2016 at 19:49 Comment(6)
/usr/lib/git-core/git-submodule: 1: eval: [[: not foundDissatisfaction
If you see the errror @PhilippLudwig mentions, replace the double brackets by single ones: git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $(realpath --relative-to=. $(cut -d" " -f2 .git))" > .git'Roundy
Can you give an example of how to do this by hand? I tried changing a .git file to point to a relative worktree but it's not recognizedGladis
Neither command worked, second one reported "not a git repository" error, first one reported lots of "No such file or directory" and left empty "gitdir:" in every submodule. I guess these commands are safe to run only before moving Git repository otherwise they do not work correctly and make things worse. It would be nice if the answer included a warning about this.Chrissy
Note that because absolute directory can point anywhere there's no safe way to do this automatically if the repository hierachy has already been moved.Plinth
use this to support folders with empty spaces : git submodule foreach --recursive '[[ -f .git ]] && echo "gitdir: $(realpath --relative-to=. "$(cut -d" " -f2- .git)")" > .git'Dishpan
A
4

@r3dey3 solution adapted for Windows:

git submodule foreach --recursive '[[ -f .git ]] && chmod +w .git && echo "gitdir: $(realpath --relative-to=. "$(cygpath -u "$(cut -d" " -f2 .git)")")" > .git'

Here I added:

  • chmod +w .git to remove readonly attribute
  • cygpath -u call to convert Windows path to Unix path
Amygdala answered 2/12, 2016 at 12:54 Comment(0)
J
0

I've encountered the same problem.

Here's a gist of a small script that I wrote, which might help.

It doesn't really solve the problem by converting the paths to a relative form, but it does do a quick search & replace in the relevant locations, allowing you to fix everything up. Particularly handy if you're dealing with a complex set of submodules where there might be a lot of paths to fix.

Note that I've used this script myself on OS X 10.8, but I can't be 100% certain that it works in all cases, so be careful and take sensible precautions!

https://gist.github.com/3394771

Janina answered 19/8, 2012 at 13:48 Comment(1)
If you do sed -i ... instead of sed -i.bak then sed won't create a backup file, answering the question from the comment in your Gist. You're welcome :)Trauner
C
0

The following command converts paths for all submodules to relative ones (it works even if gitdir value in submodule .git file is wrong or empty, so you can use the command even after moving the repository to new location):

for module in $(dirname $(find .git/modules -type f -name description)); do
    git="$(echo $module | cut -d/ -f2- | perl -pe "s|modules/||g")/.git"
    if [[ -e $git ]]; then
        echo "gitdir: $(realpath --relative-to=$(dirname $git) $module)" > $git
    fi
done

It needs to be executed from repository root directory (where is .git directory is located).

I tested it with PyTorch repository which not only has submodules but even submodules of submodules, and it worked as expected. To make sure it detects right paths without writing to the files, you can perform "dry run" by replacing > with . (or some other symbol without special meaning). If everything is OK, then use > to actually write changes.

Chrissy answered 23/2, 2021 at 18:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.