Git代码仓库无损整理:目录拆分和重命名

Git代码仓库无损整理:目录拆分和重命名

这篇文章主要使用"核弹级"命令git-filter-branch, 对代码仓库进行整理. 这里的整理包括子目录重命名, 子目录独立为新项目(保留或者不保留原来的结构)等. 整理之后, 原来的提交信息都会完好的保存下来, 方便追溯.

重要的事情说三遍:

强烈建议第一次使用的时候做好备份, 切记!!! 强烈建议第一次使用的时候做好备份, 切记!!! 强烈建议第一次使用的时候做好备份, 切记!!!

每处理完一个分支, 都需要执行如下操作, 并重新克隆项目并处理下一个分支

git remote remove origin
git remote add origin xxxxxx.git
git push -u origin BRANCH-NAME
git push --tags

将子文件夹独立为新的仓库

git filter-branch --prune-empty --tag-name-filter cat --subdirectory-filter FOLDER-NAME  BRANCH-NAME 

演示:

原结构:
root
├── delete
└── new
    └── test.sql
    
处理后:
new
└── test.sql

保留原来的目录结构, 清理掉其他的子目录, 也可将要保留的目录重命名.

git filter-branch --prune-empty --tag-name-filter cat --tree-filter 'ls | grep -v FOLDER-NAME | xargs rm -rf && mv FOLDER-NAME NEW-FOLDER-NAME' BRANCH-NAME

演示:

原结构:
root
├── delete
└── new
    └── test.sql
处理后:
root
└── new
    └── test.sql

将项目中的文件移入新建的子目录

#linux only
git filter-branch --prune-empty --tag-name-filter cat --tree-filter 'mkdir FOLDER-NAME && (ls | grep -v FOLDER-NAME | xargs mv -t FOLDER-NAME) ' BRANCH-NAME  

演示:

原结构:
root
├── test1.sql
└── test2.sql   
    
处理后:
root
└── new
    ├── test1.sql
    └── test2.sql

保留项目的多个目录并重命名

git filter-branch --prune-empty --tag-name-filter cat --tree-filter '(ls | egrep -v "(FOLDER-NAME1|FOLDER-NAME2)" | xargs rm -rf) && mv FOLDER-NAME1 NEW-FOLDER-NAME1 && mv mv FOLDER-NAME2 NEW-FOLDER-NAME2' BRANCH-NAME

演示:

原结构:
root
├── old1
│   └── test1.sql
└── old2
    └── test2.sql
处理后:
root
├── new1
│   └── test1.sql
└── new2
    └── test2.sql

迁出多层目录

git filter-branch --prune-empty --tag-name-filter cat --tree-filter 'if [ -d "FOLDER-NAME/SUB-FOLDER-NAME" ]; then mv FOLDER-NAME/SUB-FOLDER-NAME . ;fi && (ls | grep -v FOLDER-NAME | xargs rm -rf )' BRANCH-NAME

演示:

原结构:
root
└── sub
    └── base
        └── base.sql
处理后:
root
└── base
    └── base.sql            

修改author的信息, 如邮箱和名字

这个操作需要在各个分支上都运行一遍. 对commit的修改, 就改变revision id. 需要使用git push --force强制覆盖仓库, 因此tag信息也会被重写, 需要运行git push --tags --force

#对author的信息进行修改: GIT_AUTHOR_NAME, GIT_COMMITTER_EMAIL
git filter-branch --tag-name-filter cat --env-filter '
    if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
    then
        GIT_AUTHOR_EMAIL=john@example.com
    fi
    if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
    then
        GIT_COMMITTER_EMAIL=john@example.com
    fi
' -- --all

参考:

comments powered by Disqus