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
参考: