Move .git one level up while keeping the source files where they are

There are similar questions but not quite what I need.

I have this structure in several projects:

/var/www/proj-a/
  app/
    .git/
    script-a.js
    script-.js
    ... more files and directories
  data/
    ... data and config files go here

I want to have the .git folder directly in the project folder, not as a sub-directory of app. But the repo will still only manage files in the app directory. In other words, I will use .gitignore to exclude everything inside the project directory except for the app directory.

The new structure should look like this:

/var/www/proj-a/
  .git/
  app/
    script-a.js
    script-.js
    ... more files and directories
  data/
    ... data and config files go here
  .gitignore

Now, in git are paths saved as absolute paths allowing me to just move the .git directory to the project directory without any issues; or are paths relative resulting in source files not being found? If the paths are relative, how can I achieve this change without loosing my git branches and history?


There are other reasons I prefer the new structure.
Sounds like it is not a simple mater of moving the .git one level up though ... Is there no way?

You don't exactly move the .git/ folder one level up.

What you can do is move the elements in the current Git repository one level down, under a new app/ folder, using git filter-repo.

  • install git filter-repo (python-based)
  • rename / as /app: git filter-repo --path-rename /:/app (Filtering based on paths)

Once you have a Git repository with the right structure, you can add the data/ folder in it, and clone the end result as proj-a.


As noted by knittl in the comments:

This modifies all existing commit ids.
If you have your history shared, all others need to re-clone.

This is true for any rebase or filter operations (git filter-branch, git filter-repo, BFG, ...): a git push --force or git push --mirror is often implied at the end.
And that does mean communicating to any contributor the new state of that repository, for them to clone it again.