重构项目文件夹后丢失了git历史记录。

22

大约一个月前,我提交了一个关于创建新文件夹和子文件夹并在它们之间移动源代码文件的内容。今天我第一次查看历史记录时才意识到 Git 在原始文件被删除然后重新添加后“丢失”了历史记录 - 例如当我在 Git GUI 中查看文件时(由于涉及 NDA 我不能直接讨论,但比如这个存储库在 GitHub 上也无法显示),它仅显示每个文件自项目文件夹重新组织以来的历史记录。

阅读了一些问题(Getting Git to Acknowledge Previously Moved FilesHow to make git mark a deleted and a new file as a file move?)后,我比开始时更迷茫了。从那些答案中听起来,似乎我将完全无法解决这个问题?我真的很感激任何帮助。


3
@JUST:你的观点这次是不正确的。SO绝对是关于版本控制问题的正确场所。毫无疑问,OP提供的之前的GIT问题链接也说明了这一点。可以看一下FAQ:“程序员通常使用的软件工具”。我猜想那是你的关闭投票 - 或许你应该去看一下FAQ和特权页面,然后再行使这个特权。 - Cascabel
@Jefromi:我听到你的意见了,但是既然“标签集”出现了,我就停止了这种争论。请参考http://blog.stackoverflow.com/2010/11/stack-overflow-homepage-changes/#comment-51797。他们可以将那些问题移动到任何他们想要的位置... 我会看到它们的;) - VonC
@VonC:我会认为,即使不是为了我们自己,也应该尽量将问题放在一个地方,为的是那些正在寻找答案的人。 - Cascabel
@Jefromi:同意。我重新承诺投入这个努力的过程 ;) - VonC
7个回答

11

在Git中,没有文件移动的概念。

一些工具,如GitHub,认为一个提交包含了一个名为X的已删除文件和一个名为X的新建文件是文件移动。

根据Linus Torvalds的说法,文件移动只是重构的一种特殊情况;因此Git不会对其进行特殊处理。许多其他特殊情况的处理都留给高级工具(如前端)来完成。

有关此主题的更多信息,请查看Linus Torvalds的这个回答


3
我不太了解Git,但是如果你移动文件,Github会丢失它的历史记录。我现在在我的一个github仓库中遇到了这个问题,我移动了整个目录结构,现在所有文件的历史记录都显示为只有1个元素。 - Powerlord
1
你回答中的链接已经失效了,你有其他来源吗?或者你能直接发整个引用吗? - NomenNescio
似乎整个http://permalink.gmane.org/的功能不如预期。 - Gian Marco
1
那么答案是肯定的,历史记录丢失了吗? - s_baldur
@sindri_baldur,答案是Git跟踪内容,而不是创建内容所采取的操作。因此,保留内容历史记录,但不保留对内容执行的操作历史记录。 - Gian Marco
@GianMarcoGherardi 只是从表面上看:当您更改文件的内容时,可以使用命令行上的 git log 或 GitHub 上的 history 等工具查看更改文件内容的提交历史记录。但是,当您更改文件的名称时,似乎两者都不再起作用。在 GitHub 上,我只能看到“文件重命名而没有更改。”但是,之前的历史记录现在无法访问了。 - s_baldur

6
据我所见,您想要:
git log --follow some_file.cpp

请参考http://git-scm.com/docs/git-log以了解详情。我不确定这是否是您想要的;但在Git中,Git跟踪内容而不是文件。问题在于确定该信息真的很昂贵,并且通常假定您不需要它...

3
如果您想在git中移动文件夹,可以使用git mv命令。我有一堆文件夹在我的存储库根目录下,想把它们移动到两个子目录中,所以我使用mkdir创建了两个新目录。然后,我逐个将文件和文件夹移动到新目录中,如下所示:
git mv folder1/ newDirectory1/
git mv file1.txt newDirectory2/

我曾经遇到这样一个情况,我想把其中一个目录重命名为src,我是这样做的:

git mv folder2 newDirectory1/src

这导致产生了一组类似于以下的文件:
repository/
   newDirectory1/
      folder1/
      src/
   newDirectory2/
      file1.txt

完成后,我创建了一个名为“reorganized”的新分支,这样我就不会干扰另一位开发人员在主分支上的工作。他继续在文件上工作,当他将新更改推送到主分支时,我拉取并合并更改到我的分支,并且一切都按照我希望的那样运行。已移动的文件从其原始位置正确引用,并接收其提交。


2
你尝试设置config diff.renames了吗?
diff.renames

告诉git检测重命名。如果设置为任何布尔值,它将启用基本的重命名检测。如果设置为"copies"或"copy",它还将检测复制。

注意:要在重命名后跟踪单个文件的历史记录,您需要使用" git log -p --follow file "。


看起来 TC 实际上是删除了一个文件,然后在之后的版本中恢复了它(或类似的操作),这意味着 Git 无法检测到它作为重命名。 - erjiang
我试过了,没用。这个代码库在GitHub上也是“坏的”,如果我能让GitHub正确读取它,我就会很高兴。 - refulgentis

0

我会运行一个脚本,遍历所有对象。你需要先解压所有打包的文件。脚本会检查类型,如果是提交(commit),则会查看作者是否为你。然后检查日期。列出这些内容并使用 grep 查找你想要的文件名。一旦找到感兴趣的提交(commit),就创建一个分支。

git branch RecoveredWork hash-of-your-commit

看看你是否拥有所需的一切

git log RecoveredWork --graph --decorate

从这里开始,您可能想要进行一些过滤分支、移植和/或变基操作,以重新链接历史记录。


0

我能想到一些可能性。如果只是简单地洗牌,但没有跟踪,那么我认为这是在两个不同的提交中完成的...一个用于删除,另一个用于重新添加。在那之前的提交中创建一个新分支,在下一个两个提交作为一个提交中加载,然后附加在其后的所有内容。

如果不是这种情况,您可能需要使用git log -M -C查看提交。


0

如果你的历史记录确实缺少修订(从你的问题中并不完全清楚实际缺少什么),而且只有一个月左右的时间,那么你可能还有时间——查看reflog;它会保留你检出的每个引用的副本,因此如果你犯了错误,可以恢复到之前的状态。

默认情况下,reflog条目保留90天,它们会被git gc清除。

git help reflog

我应该更清楚一些 - 我没有丢失数据,但是当我尝试在我的git GUI中查看给定文件的历史记录时,它只显示到我的“重新组织”提交。 - refulgentis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接