GIT Split Repository directory preserving *move / renames* history

后端 未结 5 891
余生分开走
余生分开走 2020-12-15 08:18

Let\'s say you have the repository:

myCode/megaProject/moduleA
myCode/megaProject/moduleB

Over time (months), you re-organise the project.

5条回答
  •  猫巷女王i
    2020-12-15 08:55

    I'm aware of no simple way to do this, but it can be done.

    The problem with filter-branch is that it works by

    applying custom filters on each revision

    If you can create a filter which won't delete your files they will be tracked between directories. Of course this is likely to be non-trivial for any repository which isn't trivial.

    To start: Let's assume it is a trivial repository. You have never renamed a file, and you have never had files in two modules with the same name. All you need to do is get a list of the files in your module find megaProject/moduleA -type f -printf "%f\n" > preserve and then run your filter using those filenames, and your directory:

    preserve.sh

    cmd="find . -type f ! -name d1"
    while read f; do
      cmd="$cmd ! -name $f"
    done < /path/to/myCode/preserve
    for i in $($cmd)
    do
      rm $i
    done
    

    git filter-branch --prune-empty --tree-filter '/path/to/myCode/preserve.sh' HEAD

    Of course it's renames that make this difficult. One of the nice things that git filter-branch does is gives you the $GIT_COMMIT environment variable. You can then get fancy and use things like:

    for f in megaProject/moduleA
    do
     git log --pretty=format:'%H' --name-only --follow -- $f |  awk '{ if($0 != ""){ printf $0 ":"; next; } print; }'
    done > preserve
    

    to build a filename history, with commits, that could be used in place of the simple preserve file in the trivial example, but the onus is going to be on you to keep track of what files should be present at each commit. This actually shouldn't be too hard to code out, but I haven't seen anybody who's done it yet.

提交回复
热议问题