-->

Splitting many subdirectories into a new, separate

2019-02-23 00:29发布

问题:

This question is related to:

  • detach-many-subdirectories-into-a-new-separate-git-repository
  • Git subtree and multiple directories

Instead of detaching a single subdirectory, I want to detach a couple. For example, here is my folder structure:

/app1
  /file1
  /file2
  /folder1
  /folder2
/app2
  /file3
  /file4
  /folder3
  /folder4
/test
  /file5
  /file6
  /folder5
  /folder6
/README.md
/new_file

And I would like this instead:

/app1
  /file1
  /file2
  /folder1
  /folder2
/app2
  /file3
  /file4
  /folder3
  /folder4

I have tried the below alternatives, and none have worked so far:

git filter-branch --index-filter 'git rm --cached -qr -- . && git reset -q $GIT_COMMIT -- /app1/* app2/*' --prune-empty -- --all

Error: 
    pathspec '.' did not match any files

Second Try:

git filter-branch --tree-filter "mkdir samples; mv app1 app2 samples/" HEAD

Error:
   rename app1 to samples/app1: No such file or directory
   Same error for the second sub-directory

Any ideas?

回答1:

In the case with tree-filter you will evaluate the script for each commit, even commits where app1 and app2 may not exist, this can be solved by a guard and an alternative command that does not fail.

 git filter-branch --tree-filter "mkdir samples && test -d app1 && mv app1 samples/|| test -d app2 && mv app2 samples/ || echo 'nothing to do'" HEAD

Then making samples the root directory, this will move app1 and app2 to the root of the project.

git filter-branch -f --subdirectory-filter samples -- --all

I recommend that you do a backup first!



回答2:

# safety play: do this in a scratch clone
git clone --mirror . ../redo
cd !$

# build the exact index you want:
git filter-branch --index-filter '
        git read-tree --empty
        git read-tree --prefix=app1/ $GIT_COMMIT:app1
        git read-tree --prefix=app2/ $GIT_COMMIT:app2
' -- --all

... probably with --tag-name-filter cat to point old tags at new(ly rewritten) commits w/o changing names.