How to rewrite Git history so that all files are in a subdirectory?

I would like to merge several Git repositories (let repoA and repoB) into one new repository. A new repository (repoNew) should contain each repoA and repoB in a separate subdirectory. Since I have only worked locally so far, I can do whatever I want in the repositories.

In these circumstances, the standard approach would be to use git filter-branch to rewrite the history of each repoA and repoB, so that they look like they were always in a subfolder and then merged them into repoNew.

The first step is what bothers me. I know the SO answers well, such as How to rewrite history so that all files except those that I have already moved are in a subdirectory? (Dan Molding answer), which is what I want.

He suggested something like the following:

 git filter-branch --prune-empty --tree-filter ' if [[ ! -e repoA ]]; then mkdir -p repoA git ls-tree --name-only $GIT_COMMIT | xargs -i mv {} repoA fi' 

The result should be that the folder structure in <repoA-GIT-base> should now be in <repoA-GIT-base>/repoA . However, it is not. The above command is executed randomly on different commits with a message like "mv: cannot move" src "to" repoA / src "

How to avoid these incorrect commits when rewriting history as described?

EDIT:

You should consider excluding .gitignore from moving as follows:

 git filter-branch --prune-empty --tree-filter ' if [[ ! -e repoA ]]; then mkdir -p repoA; git ls-tree --name-only $GIT_COMMIT | grep -ve '^.gitignore$' | xargs -i mv {} repoA; fi' 

The team still does not seem random. I tried this several times, and the failure, "unable to move," occurred on different commits each time. I noticed that when I excluded .gitignore , the probability of breaking through all commits seems to have increased. I was able to sequentially execute the course of all my three different repositories without fail. When I tried it again for fun on another discarded copy of one of the repositories, it again failed.

Since I also sometimes had to delete copies, due to a process supposedly using some files, the problem might have something to do with Windows 7 file access processing, but I am not able to make serious assumptions.

To continue trying until it succeeds, of course, is ridiculous and probably will not work on repositories with a lot of commits (I only had ~ 30).

Info: I used git - bash with Git version 1.7.10.msysgit.1 on a 64-bit version of Windows 7.

+6
source share
2 answers

I suspect you are looking for something like git subhistory . This is a very small project and does not seem to be maintained in good condition, but it is also designed almost for what you are describing. Give it a try!

+2
source

I wrote a program based on libgit2 to filter git branches for another purpose, which I changed a bit to do what you want here. You can try.

It is in the subdir git_filter branch on github:

https://github.com/slobobaby/git_filter/tree/subdir

I just tested it in our commit repository 100000 and it took 43 seconds.

I wrote the program because git filter-based solutions took from a few days to a few weeks.

The configuration example filters the β€œtest” repository and puts everything in the β€œtest” subdirectory - you can change this to do what you want.

+1
source

All Articles