我想重命名/移动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 mv {old} {new}
git add -u {new}
Git检测重命名,而不是通过提交持久化操作,因此使用gitmv还是mv并不重要。
log命令采用--follow参数,该参数在重命名操作之前继续历史,即,它使用启发式搜索类似的内容。
要查找完整的历史记录,请使用以下命令:
git log --follow ./path/to/file
在我的例子中,我将两个文件从“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中的项目子树/项目/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) 仅在另一侧对目录应用隐式目录重命名历史是一个做更名的人。
要重命名目录或文件(我不太了解复杂的情况,因此可能需要注意):
git filter-repo --path-rename OLD_NAME:NEW_NAME
要在提到目录的文件中重命名目录(可以使用回调,但我不知道如何):
git filter-repo --replace-text expressions.txt
expressions.txt是一个充满了文字:OLD_NAME==>NEW_NAME等行的文件(可以将Python的RE与regex一起使用,也可以将glob与glob一起使用)。
要重命名提交消息中的目录,请执行以下操作:
git-filter-repo --message-callback 'return message.replace(b"OLD_NAME", b"NEW_NAME")'
Python的正则表达式也受支持,但必须用Python手动编写。
如果存储库是原始的,没有远程,则必须添加--force以强制重写。(在执行此操作之前,您可能需要创建存储库的备份。)
如果不想保留引用(它们将显示在GitGUI的分支历史记录中),则必须添加--replace-refs delete no add。