我想重命名/移动Git中的项目子树
/project/xyz
to
/components/xyz
如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。有没有一种方法可以移动它,以保持历史?
我想重命名/移动Git中的项目子树
/project/xyz
to
/components/xyz
如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。有没有一种方法可以移动它,以保持历史?
当前回答
Git检测重命名,而不是通过提交持久化操作,因此使用gitmv还是mv并不重要。
log命令采用--follow参数,该参数在重命名操作之前继续历史,即,它使用启发式搜索类似的内容。
要查找完整的历史记录,请使用以下命令:
git log --follow ./path/to/file
其他回答
我想重命名/移动Git中的项目子树/项目/xyz到/组件/xyz如果我使用普通的gitmv项目组件,那么xyz项目的所有提交历史都会丢失。
没有(8年后,Git 2.19,2018年第3季度),因为Git会检测到目录重命名,现在已经有了更好的记录。
参见Elijah Newren(Newren)提交的提交b00bf1c、提交1634688、提交0661e49、提交4d34dff、提交983f464、提交c840e1a、提交9929430(2018年6月27日)和提交d4e8062、提交5dacd4a(2018年7月25日)。(于2018年7月24日由Junio C Hamano(吉斯特)在提交时合并)
现在在Documentation/technical/directory-rename-detection.txt中对此进行了解释:
例子:
当所有x/a、x/b和x/c都移动到z/a、z/b和z/c时,很可能同时添加的x/d也希望通过以下方式移动到z/d提示整个目录“x”移动到“z”。
但还有很多其他情况,比如:
历史的一方重命名为x->z,另一方将某个文件重命名为x/e,导致合并需要进行传递重命名。
为了简化目录重命名检测,这些规则由Git强制执行:
当应用目录重命名检测:
如果合并的两边仍然存在给定的目录,我们不认为它已被重命名。如果要重命名的文件的子集有一个文件或目录在其中(或将相互妨碍),请“关闭”这些特定子路径的目录重命名,并向用户报告冲突。如果历史的另一端将目录重命名为您的历史的另一侧重命名的路径,那么对于任何隐式目录重命名,忽略历史另一端的特定重命名(但警告用户)。
您可以在t/t6043-merge-rename-directories.sh中看到许多测试,其中还指出:
a) 如果重命名将一个目录拆分为两个或多个其他目录,则重命名最多的目录“获胜”。b) 避免对路径进行目录重命名检测,如果该路径是合并两侧重命名的源。c) 仅在另一侧对目录应用隐式目录重命名历史是一个做更名的人。
在我的例子中,我将两个文件从“resources”目录移动到“src/main/resources”。如下代码所示,它们显示为“已删除”。
然而,在我将重新定位的文件添加到临时区域,然后添加删除的文件后,系统将它们识别为“重命名”。
当我检查这两个文件的历史记录时,它是完整的,它们的永久链接仍然有效。所以,一切都如我们所愿。
myaddress (master *)$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: resources/myaddress-schemas.sql
deleted: resources/select-sangdo-ro-60.sql
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
pom.xml
src/
myaddress (master *)$ git add src/main/resources/*.sql
myaddress (master *+)$ git add `git ls-files --deleted`
myaddress (master +)$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: resources/myaddress-schemas.sql -> src/main/resources/myaddress-schemas.sql
renamed: resources/select-sangdo-ro-60.sql -> src/main/resources/select-sangdo-ro-60.sql
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
pom.xml
src/main/java/
src/main/webapp/
myaddress (master +)$
myaddress (master +)$ git commit -m "two resource files moved to src/main"
[master 0832839] two resource files moved to src/main
2 files changed, 0 insertions(+), 0 deletions(-)
rename {resources => src/main/resources}/myaddress-schemas.sql (100%)
rename {resources => src/main/resources}/select-sangdo-ro-60.sql (100%)
myaddress (master)$
我愿意:
git mv {old} {new}
git add -u {new}
我遵循这个多步骤过程将代码移动到父目录并保留历史记录。
步骤0:从“master”创建了分支“history”以进行安全保管
步骤1:使用gitfilter repo工具重写历史。下面的命令将文件夹“FolderwithContentOfInterest”移动到一个级别,并修改了相关的提交历史记录
git filter-repo --path-rename ParentFolder/FolderwithContentOfInterest/:FolderwithContentOfInterest/ --force
步骤2:此时GitHub存储库丢失了远程存储库路径。添加远程引用
git remote add origin git@github.com:MyCompany/MyRepo.git
步骤3:从存储库中提取信息
git pull
步骤4:将本地丢失分支连接到源分支
git branch --set-upstream-to=origin/history history
步骤5:如果提示,解决文件夹结构的合并冲突
第6步:推!!
git push
注意:修改的历史记录和移动的文件夹似乎已提交。在此处输入代码
完成。代码移动到父目录/所需目录,保持历史记录完整!
只需移动文件并使用:
git add .
提交前,您可以检查状态:
git status
这将显示:
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: old-folder/file.txt -> new-folder/file.txt
我用Git版本2.26.1进行了测试。
从GitHub帮助页中提取。