我已经手动移动了一堆文件,没有考虑,也找不到一种方法让Git认识到这些文件只是被移动了,实际上不是不同的文件。除了删除旧的和添加新的(从而丢失历史),或者用git mv恢复所有更改之外,还有其他方法可以做到这一点吗?
- Git自动获取文件的副本和移动。你为什么说它不起作用?
- 重复?stackoverflow.com/questions/433111/……这个问题的一些好答案(至少帮了我!)
- 编辑:我刚注意到,只要我先调用"git commit-a",就可以在移动的文件上使用"git log"。
- @Jeremywall我发现Git经常出错,除非我明确使用git mv。
- 是否可以在Git中移动/重命名文件并维护其历史记录?
- 对于git 2.18(2018年第2季度),git status现在应该显示重命名(而不是删除/添加文件)。请参阅"[如何告诉Git它是同一个目录,只是一个不同的名称(stackoverflow.comhttps://stackoverflow.com/a/50573107/6‌&误8203;309)"。
要让git删除已经删除或移动的文件,只需输入
- +1:谢谢,这正是我们所缺少的。当git status不进行移动或重命名时,git add -u会修复它。
- 你能解释一下这到底在做什么吗?
- @OlivierBlanVillain:"git add-u"将处理git正在跟踪的所有文件,并在工作目录中进行了更改。请注意,如果您将文件移动到了git不跟踪的目录中,那么'add-u'将不会检测到移动。如果您稍后将目标目录添加到git并重新执行'add-u',git将正确地进行移动。
- 请注意,如果有其他不想暂存的文件,则应指定文件名。
我想它已经做到了。现在,我可能错了,但我已经读到Git根据文件的内容跟踪文件,而不是基于文件系统中的位置或基于delta/differences。在堆栈中,我认为它显示的好像文件正在被删除,然后重新添加,但我认为我已经尝试过一次,它仍然保持了历史,因为前面提到的Git跟踪事情的方式。
如果我是正确的或不正确的话,还是会有帮助的。对不起,如果我误解了你的问题。
- 这是正确的。移动一个文件(分别在旧文件和新文件上使用"git rm"和"git add")和使用"git mv"应该没有区别。迈克尔:如果问题是您没有在"git日志文件"中看到移动前的历史记录,请尝试使用"git日志--跟踪文件"。
- 不适合我。Git将该文件视为正在删除并添加了一个新文件。不知道我做错了什么。可能是位桶问题,因为在提交时,Git似乎检测到文件被重命名。
- 这完全取决于移动文件后文件有多不同,这很愚蠢。如果将dummy.class重命名为clean refactor.clas,则至少通过重命名类名,很可能会更改文件的内容。这些更改可能会使Git不认识到dummy.class和clean-refactor.class属于同一历史:(
- @以我的经验,rafa重命名一个这样的文件,git认识到这个文件正在被重命名。在Git内部,内容主要是存储的内容,内容的名称并不重要。如果不更改内容,它将保持相同的blob、相同的散列值,但在树中的命名方式不同。
- @jorgiesraelpe&241;A只是重命名文件不会有问题。但是,通常在某些重构过程中重命名一个文件,并且与该重构相关的代码更改将使Git感到困惑。
- @拉法哦,好的。在这种情况下,文件内容(blob)会被修改(通过重构),因此它会生成一个不同的sha散列,所以我认为git会将其视为一个完全不同的文件,而不仅仅是名称不同。
- @是的,我知道。因此,我的咆哮是:)在SVN中,文件的历史不会丢失,包括其重构。我可以在日志中看到B类曾经被命名为A,并被重构为B。
- 如果您阅读git commit命令上的文档,它有特定的标志来控制一个文件可以和仍然被认为是同一个文件的不同程度。如果您不使用git mv,然后将文件提交到新的名称/位置,而不将内容更改作为独立提交,那么您将依赖这些自动限制来检测移动。另外,如果使用git mv移动文件,然后进行更改,则移动和修改集可能会超出限制,并导致git将其视为删除并在同一提交中创建。
git不跟踪单个文件的历史记录,也不专门处理移动和复制,也就是说,没有特殊的元数据表明发生了移动或复制。相反,每个git提交都是工作树的完整快照。
如果您想在git log中看到移动,您可以提供-M除了列出已更改文件的选项外,例如:
git将查看提交历史中相邻的树,并推断每个提交所移动的文件。
要查找副本以及重命名,您可以使用-C选项,您可以提供两次,以使git查找可能的副本源更加困难,但会牺牲一些性能。
1
| git log --summary -M -C -C |
号
注意,由于Git不存储文件历史记录(仅提交历史记录),即使您执行了git rm和git mv文件,也不会丢失任何历史记录。对路径的所有更改仍将被记录并在git log中可见。
- 也可以在.git/config中(repository config)或在~/.gitconfig中(用户配置)将diff.renames配置变量设置为true。有关详细信息,请参阅git config手册页。
为了更好地理解为什么Git会执行重命名检测而不是(更常见的)显式重命名跟踪,以及git log路径限制是如何工作的,您可以阅读Git维护者Junio C Hamano(及其参考)的Linus的终极内容跟踪工具博客文章。
它发生在我身上,当我移动和编辑文件时,它将不再识别为移动文件,而是一个新文件,所以我丢失了历史。
我要做的是创建两个分离的提交,一个在移动文件时,另一个在编辑文件。这样我就保留了历史。
您可以将新文件移回/重命名为Git之外的旧文件名和路径,然后使用git mv进行移动;例如在bash中:
1
| mv $NEW $OLD && git mv $OLD $NEW |
。
这有点麻烦,特别是如果你必须用手做的话。但是它的优点是,它会保留其他更改,如更改命名空间或类名,以便您可以检查它们,并且仅在您打算这样做时才进行阶段化。
1我希望找到一个更好的选择,当我找到答案时会更新我的答案。
例子:我把一堆文件移到了oldDir的newDir上,并热情地进行了一些其他的更改。现在我想看看还有哪些修改。使用git-xargs-gawk和bash会导致以下结果(在一行上):
1 2 3
| git status --short |
gawk '/^\?\?/ && match($0, /newDir\/(*.\.cs)/, a) {print"newDir/" a[1]"""oldDir/" a[1]}' |
xargs -n 2 bash -c 'mv $0 $1; git mv $1 $0' |
现在,git status将重命名显示为"要提交的更改",并将文本修改显示为"不准备提交的更改"。