问题描述
我正在使用 Git 来管理小型 shell 脚本的小型存储库。 有很多,但没有一个证明自己的存储库是合理的,所以我将它们聚集在一个存储库中。
为了保持整洁,我有几个长期运行的分支 - 一个用于我仍在处理的脚本,另一个用于我通常已完成但仍在测试的脚本,另一个用于经过验证的、值得信赖的脚本。当然,我偶尔会在树枝之间移动它们。
我目前正在使用 git checkout {branch} {filename}
在分支之间传输脚本,但这只会按当前状态导入文件,而将其历史记录保留在旧分支中。
这不是非常重要,但出于好奇 - 有没有办法在具有其历史的分支之间移动单个文件?
谢谢!
解决方法
在 Git 中,文件没有历史记录。相反,提交是历史。 Git 存储库中的历史记录可通过以下方式找到:
- 选择一个分支名称(或其他一些可以让您找到提交的哈希 ID 的标签);
- 观察那个提交,通过其哈希 ID 发现;
- 使用 that 提交,其中包含一个或多个较早提交的哈希 ID,以退回到较早的提交。
正是这种退步,从提交到更早提交,是探索历史的行为。因此,提交是历史。
现在,每个提交都包含文件:事实上,每个提交都有每个文件的完整副本,以只读格式保存,压缩,并且——因为大多数提交主要复制一些以前提交的文件不变——去重。因此,给定一组是历史的提交,我们可以让 Git 过滤掉部分甚至大部分的历史,只向我们显示那些提交Git 认为我们会发现它特别有趣。这就是 git log -- path
和 git log --follow -- filename
的工作原理。他们查看实际历史记录的某个子集——一些提交集——然后简单地对你撒谎,使用精心挑选的、可编程的谎言来为你提供有用的信息。
您必须记住,这些都是谎言,您可以使用 --simplify-by-decoration
或 --full-history
等选项加以控制。否则你会被谎言蒙骗。实际历史是提交,Git 过滤掉了一些。
进行新的提交会使所有现有的提交保持不变。它必须,因为任何提交的任何部分都不能更改,即使是 Git 本身也不行。 (这就是 Git 如何设法完成分布式版本控制系统的“分布式”部分。)