一个git存储库,但一个文件在两台不同的计算机上是不同的



我有一个远程(非现场、托管)git存储库,我正在从两台笔记本电脑访问它。由于我是唯一一个使用这个存储库的人,所以我不需要有单独的分支。通常,当我提交并推送到存储库时,我会很快在另一台笔记本电脑上获取并合并。

我现在发现自己在两台计算机上都有一个不同版本的文件,git告诉我什么都不需要做,也没有更新。

在两台笔记本电脑上,当我键入时

git remote -v

我收到了完全相同的东西-远程存储库的地址

origin  git@XYZ.com:myproj.git (fetch)
origin  git@XYZ.com:myproj.git (push)

在两台笔记本电脑上,都会返回git状态调用:

On branch master
Your branch is up-to-date with 'origin/master'

如果我执行

git remote update

我收到

Fetching origin

然后我打电话给

git status -uno

我得到

On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit

最后,如果我打电话给

git fetch origin

没有输出。如果我打电话给

git merge

我收到的回复

Already up-to-date.

当我键入时

git rev-parse HEAD

在两台笔记本电脑上,我都收到了完全相同的哈希值:

d353340c1.....8503b

据我所知,两台笔记本电脑都认为远程存储库的一切都是最新的,但其中一个文件在两台笔记本上明显不同。

这怎么可能呢?我该如何声明一切都是真正同步的?

一台笔记本电脑正在从命令行运行Ubuntu 16.04和git 2.7.4版本。另一个是Windows10,通过Mintty终端上的gitbash 2.19.0.Windows.1访问。

除了之外的所有,两个签出文件中的差异在这里看起来非常正常。假设这两个签出的文件是(显然——见下文)跟踪的文件,即在每台机器上的Git索引中,这种差异通常应该导致git status,即两个系统中的至少一个系统上有not staged for commit的变化。

在这一点上,可能会发生以下几件事:

  1. 文件实际上可能不在索引中,并且被忽略(但在注释中似乎已经排除了这一点)
  2. 该文件可能被错误地标记为";"干净";以便git status只是假设文件的工作树副本与文件的索引副本匹配
  3. 该文件可能是字面上的";清洁">

在我详细讨论案例2和案例3之前,这里有一个特殊的事实值得注意。使用Git时,您看到和使用的文件不在Git中。在Git中是的文件——存储在提交中——以一种特殊的只读、仅限Git、压缩和消除重复的形式存储,只有Git才能真正使用。因此,为了使用提交,Git必须将提交的复制到某个地方,将文件变成您可以实际使用的普通日常文件。这些文件在工作树的工作树Git存储库中。(存储库通常位于工作树顶层的.git子目录中。)

现在,情况1非常简单:

  • Git的索引本身是一个复杂的问题,但它相当于要提交的所有文件的列表,包括截至下一次提交时,它们应该具有的已Git化的内容
  • 在Git的索引中不是的文件将不会出现在下一次提交中(当然,您可以更改这一点,例如使用git add)
  • 存在于工作树中但不存在于Git索引中的文件,根据定义是未跟踪的文件

这就是不被跟踪的全部:它只需要存在于你的工作树中,但不存在于Git的索引中。未跟踪的文件通常会导致Git发出呜呜声,但如果列在.gitignore中,Git就会停止发出呜呜声。这当然需要.gitignore.git/info/exclude文件的存在。(您可以在主目录配置中有一个全局.gitignore,但如果git check-ignore -v导致文件被忽略,它会指出它。)

如果为该存储库定义了cleansmout过滤器(通过存储库中的.gitattributes和一些Git配置文件中的过滤器定义),则可能发生情况3:

  • 污点过滤器(如果有的话)负责在文件从Git出来时更改。当Git提取提交时,它首先将提交的所有文件复制到其索引中(以便它们可以进入下一次提交)1然后,Git将这些文件提取到您可以实际使用的版本中,这些版本将进入您的工作树。如果有污点过滤器,数据在到达工作树副本的途中会通过污点过滤器,因此工作树副本不需要与(展开的)索引副本匹配。

  • 干净过滤器(如果有的话)负责在文件进入Git时更改。当您git add一个文件时,Git会压缩、编译和消除文件数据的重复。如果有一个干净的过滤器,Git会在开始压缩和Git化过程之前通过干净的过滤器运行数据。因此,干净的滤镜可以带走污迹滤镜放在中的东西。通过这种方式,您可以提交与实际使用的文件不同的文件2

根据使用的干净过滤器和污迹过滤器,可以想象,在两台不同的机器上,某些工作树文件的大部分内容会完全不同。这当然需要文件定义干净和污迹过滤器,而这又需要.gitattributes.git/info/attributes文件。

这留下了最后一种可能性:情况2,Git认为文件是干净的(因为它是这样标记的),尽管它不是。克服这种情况的最简单方法是touch文件(如果您有Unix/Linuxtouch命令,请使用该命令)。这将文件上的修改时间戳设置为"0";现在";,这可能比保存在Git索引中的任何保存的修改时间戳(从"then"开始,几秒钟或更长时间)都要晚。

如果这些都不能找到或纠正问题,那么其他事情——一些非常神秘的事情,可能是Git错误——正在发生


1这太简单了:在某些情况下,Git的索引中已经有了一些东西,可以保留在原地。我们将忽略这些角落案例。

2至少在理论上,这是一种获得人们不断要求的东西的方法:拥有一个带有";本地配置";未提交的部分。不过,这样做也存在一些难以实现的问题。

相关内容

最新更新