5

I believe that git filter-branch can allow me to do this, but I can't figure out if i need to use --subdirectory-filter or if I need to use an index filter.

But, let's say I have a repository called repo, and the structure looks something like:

repo/fileA
repo/fileB
repo/dir1/fileC

What I want to do is move everything in to a directory called dir2 so the result is:

repo/dir2/fileA
repo/dir2/fileB
repo/dir2/dir1/fileC

I want to use filter-branch to make it look like ever since the birth of this repository, everything was always done in dir2. Is it more appropriate to use a subdirectory file or index filter to do this?

gnychis
  • 7,289
  • 18
  • 75
  • 113

3 Answers3

3

A tree filter. Something like the following should work:

git filter-branch --tree-filter 'test -e fileA && mkdir dir2 && mkdir dir2/dir1 && mv fileA fileB dir2/ && mv dir1/fileC dir2/dir1/ || echo "no op"' HEAD

However, this assumes that fileA, fileB and fileC were added at the same time (since we use test -e for fileA) and that might not be the case. If that's not the case you have to do several sweeps for each of the files.

rtn
  • 127,556
  • 20
  • 111
  • 121
2

With Git 2.24, git filter-branch is deprecated.

The equivalent would be, using newren/git-filter-repo, and its example section:

cd repo
git filter-repo --to-subdirectory-filter dir2

That will rename any folder, including / to dir2.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
1

Probably a tree filter.

  • subdirectory filter is designed to go the other way (move an existing directory to the root of the repository, ignoring the rest).
  • index filter is designed to modify the index without checking things out, but git mv doesn't have an option to only work on the index, so you probably do actually need a checkout to work with.
Amber
  • 507,862
  • 82
  • 626
  • 550