Torque
Torque

Reputation: 3584

Use git filter-repo to move a subdirectory to root while retaining files in root

I am attempting to split up a repository that contains a client and server into two repositories, and I want to move the respective folders to the root while also keeping the files I already had in root - project readmes, .gitlab-ci.yml, .gitignore, .gitattributes` and so on.

I tried the following line with no luck:

git filter-repo --path .gitattributes --path .gitignore [...] --subdirectory-filter server

The result was something I still don't quite understand; the subdir filter seemed to have worked, but whole commits full of changes ended up missing. The above clearly wasn't the correct way to do this, assuming there even is a correct way.

I hacked my way out of it by using separate calls with --path-rename-match to first move the root files to the server subdir so that they would be moved back to root by a final call with --subdirectory-filter server, but that doesn't seem right at all.

Upvotes: 5

Views: 3036

Answers (1)

gofestive
gofestive

Reputation: 494

If I understand you correctly, you have something similar to the following project structure.

client/
server/
.gitlab-ci.yml
.gitignore

If you want to extract the client and server directories each to a dedicated project but retain the files in the root directory for each, you could use the --invert-paths option.

Using a fresh clone of the original, remove the server directory, set the origin to the new client project and push to the main branch.

git filter-repo --path server --invert-paths

Take a new clone of the original, remove the client directory, and push to the new server project.

git filter-repo --path client --invert-paths

If you want to update the path, use --path-rename. This could be used to rename a child directory or to move a child directory up in the hierarchy. For example, if you wanted to remove the enclosing server directory and move the content to the root of the project.

git filter-repo --path-rename server/foo:foo

Depending on your structure there are probably more elegant ways to achieve what you're looking for, but a combination of the above should solve for your use case.

Don't forget to process and push any tags you might have as well.

Upvotes: 3

Related Questions