在学习Git的几个障碍之后,我遇到了一个新的挑战:重命名一个目录(在本地,在工作目录中)。
当我输入git status
时,它会将旧目录名称中的所有文件(新目录中存在与新目录中完全相同的文件名)列为已删除,新目录名称为“未跟踪”。
有没有办法告诉Git“它实际上是同一个目录,只是一个不同的名字”?
这样所有文件都会被git status
列为仅修改过的文件吗?
举例说明问题,这是我在重命名整个目录时从git status
收到的输出:
git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: old-dir-name/file1
# deleted: old-dir-name/file2
# deleted: old-dir-name/file3
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# new-dir-name/
no changes added to commit (use "git add" and/or "git commit -a")
~/sb/ws>
答案 0 :(得分:18)
只需git add
目录的新名称。 Git没有明确跟踪重命名,它只是稍后检测它们。 git mv
执行效率可能略高(因为它可以直接更新索引),但效果完全相同。
答案 1 :(得分:14)
这里的所有答案对于我所面临的特定场景的实际解决方案的方式非常有帮助。我正在以实际步骤的形式提供对我有用的东西,希望能帮助其他人遇到同样的挑战:
git mv <old-dir-name>
<new-dir-name>
git status
(验证所有文件
标记为重命名,而不是“已删除”)git commit -a -m "git mv
<old-dir-name> <new-dir-name>"
(这是一个“假”提交,准备
对于下一个真正的重命名
步骤)git branch
git_mv_20110708_1500_DO_NOT_USE
(带有时间戳的“假”分支
提醒说我们只是这样做了
解决方法)/bin/rm -Rf <new-dir-name>
cp -Rp .../<new-dir-name> .
(复制
在实际的文件夹上
重命名名称)git status
(大多数修改过的文件
现在将被正确标记为
修改,而不是“已删除”。已重命名的文件将是
标记为已删除的和已添加,
尽管有相同的内容! - 如果这些文件也需要重命名跟踪,则重复步骤1-7)git add <untracked files>
git commit -a -m "finally renamed
this folder"
git branch FOLDER_RENAMED
:) P.S。 gitk
喜欢这个,但Emacs
仍然与重命名混淆。 :(
答案 2 :(得分:4)
你需要使用git的mv:http://www.kernel.org/pub/software/scm/git/docs/git-mv.html
git mv old_dir new_dir
所以你需要将新目录移回旧版,然后用mv重新移动它。
编辑:要回答我的回答:
我决定自己测试一下。我创建了两个包含不同文本的文件,并在其中一个使用git mv
,另一个使用mv file file2
,git add file2
,git add -u
。提交消息表明两者都被跟踪为重命名。因此,我的所有建议都是挽救一步,正如其他人所说的那样。
答案 3 :(得分:2)
Git 2.18(2018年第二季度)应检测“它是同一个目录,只是一个不同的名称”,因为“git status
”学会了注意与UI相关的差异配置变量,例如diff.renames
commit dc6b1d9见Eckhard S. Maaß (``)(2018年5月4日)
(由Junio C Hamano -- gitster
--合并于commit 1e174fd,2018年5月23日)
中的设置
wt-status
:使用git_diff_ui_config
如果您执行以下操作:
- git add .
- git status
- git commit
- git show (or git diff HEAD)
可以期望从
git status
和git show
(或类似的差异相关程序)获得类似的输出。
通常情况并非如此,因为git status
具有差异相关选项的硬编码值。通过此提交,将从状态中删除硬编码设置 命令支持
git_diff_ui_config
提供的值。以下是对难以解决的具体方案的一些评论 以
git status
编码:`diffopt.detect_rename`
自a3e870f中的git状态开始以来(“添加”提交“ 帮助脚本“,2005-05-30,Git v0.99),
git status
总是使用重命名检测, 而对于像show和log这样的命令,必须使用a来激活它 命令行选项。
在5404c11之后(“差异:激活diff.renames
之后 默认“,2016-02-25,Git v2.9.0”默认情况下的默认行为相同,但将diff.renames
更改为其他值可能会破坏之间的一致性 再次git status
和其他命令 使用此提交,可以使用diff.renames
控制相同的默认行为。`diffopt.rename_limit`
同样,有一个选项diff.renamelimit可以调整此限制 所有命令,但git状态。有了这个提交,git status也会受到尊重 那些。
同样的Git 2.18提供status.renames
,这对于那些想要这样做但又不会禁用由
“git diff
”命令。
commit e8b2dc2见Ben Peart (benpeart
)(2018年5月11日)
(由Junio C Hamano -- gitster
--合并于commit 5da4847,2018年5月30日)
添加用于重命名检测的状态配置和命令行选项
默认情况下执行合并后会发生
git status
冲突 尝试检测导致许多物体被检查的重命名 在虚拟化仓库中,这些对象不存在于本地,因此重命名逻辑 触发它们从服务器获取。这会导致状态调用 使用此补丁需要数小时才能完成非常大的回购与秒数。添加新配置
status.renames
设置以启用关闭重命名 状态和提交期间的检测 此设置将默认为diff.renames的值。添加新的配置
的值status.renamelimit
设置以启用时间限制 花了在状态和提交期间找出不精确的重命名 此设置默认为diff.renamelimit
。将
--no-renames
命令行选项添加到启用覆盖的状态 从命令行配置设置 将--find-renames[=<n>]
命令行选项添加到允许检测重命名并可选择设置相似性索引的状态。
答案 4 :(得分:0)
问题是用户界面/用户体验问题,而不是git的“真实”问题。我问了同样的问题how-to-work-with-subdirectory-renames-in-git和一个基本问题how-does-git-record-or-more-likely-represent-file-paths-and-names-for-its-blob
事实上Git实际上并不关心。你(我们)获得的所有消息都是关于'diff'认为可能发生的事情。使用其他选项,消息将是不同的,但存储库将不会有任何不同(它是相同的快照!)。一种选项样式是diff的subtree
选项(虽然它用于不同的目的),--patience
也是如此。
需要更好的UI / UX选项,以便更容易地检测路径更改(基于树而不是blob)。在Linus的论证中,部分问题是the subtle mistake。他是正确的,Git repo应该不显式存储重命名(pathchange),而是我们需要一个允许它正确发现的选项。