在Windows系统下使用gvim和msys git 1.7.0.2时,使用fugitive.vim的:GDiff命令出错。

11
我一直在Windows上使用git和fugitive.vim来管理代码。然而,我遇到了一个问题。根据文档,:GDiff命令应该打开一个diff窗口,并允许我只暂存文件的部分内容。然而,当我在一个有更改的文件中使用该命令时,我会收到以下错误消息:alt text。这是Windows、vim、fugitive、msysgit还是文件权限的问题?有人知道吗?

3
我遇到了完全相同的问题 - 如果您解决了这个问题,请告诉我们解决方法! - Charles
4个回答

14

我曾经遇到同样的问题 - 这是我如何解决的。

默认情况下,Vim会尝试在原文件旁边存储交换文件。Fugitive创建了一个与任何实际文件路径都不对应的缓冲区,因此当Vim尝试创建交换文件时,它就会抛出错误。解决方案是确保Vim有一个可以写入的路径。

以下是我解决此问题的方法:

if has("win32") || has("win64")
   set directory=$TMP
else
   set directory=~/tmp
end

以下是GitHub上的原始问题: https://github.com/tpope/vim-fugitive/issues/9

编辑:

如下所示,正如fow在下面指出的那样,最好使用以下内容:

set directory+=,~/tmp,$TMP

Vim应该使用它可以找到的第一个路径。


1
值得注意的是,'directory'选项是一个目录列表,Vim将使用它能找到的第一个目录。最好只需向列表中添加一个值,而不是完全删除整个列表,例如set directory+=$TMP。这样做是安全的,无需进行操作系统检查,因为在Unix中默认添加了~/tmp,即使在Unix上$TMP为空,添加它也不会有任何影响。 - fow
@fow: +1 -- 当我使用 set directory+= 时,需要包括 ,,对吗(因为它是一个用注释分隔的列表)? - Charles
另外,尝试使用 set directory^=$TMP 命令(参见 :help :set^=)。 - Chris Johnsen
@Chris Johnsen:太棒了,我一直很好奇我是否能做到这样的事情。 - Charles

2

我没有Windows电脑,但我能够在Mac OS X 10.6系统上重现和隔离这个问题。

要么创建C:\TMPC:\TEMP:help 'directory'说两者都是Vim Windows版本中directory选项的默认值),或将现有目录添加到directory选项的值中。

我在我的主目录下使用一个特定于Vim的临时目录(这里也没有Windows),并添加了两个尾随斜杠(~/tmp/.vim-swaps//)。这种设置集中了交换文件,但基于正在编辑的文件的目录为其提供了唯一的名称。请参见:help :swapname中的“优点”和“缺点”,以及:help 'directory'中的“如果目录以两个路径分隔符结尾”部分。

使用^=来添加你的目录(如果存在则始终使用):

set directory^=C:\\some\\existing\\directory//

或者,使用+=来附加您的目录(这样只有在存在且不存在其他适用的directory条目时才会使用它):

set directory+=C:\\some\\existing\\directory//

查尔斯的回答建议在Windows中使用$TMP(一个环境变量的引用)作为一个好的值:

set directory+=$TMP//

根本原因与:Gdiff的索引“伪”文件的路径名相关联的directory选项的默认值有关。 :Gdiff视图的索引侧缓冲区使用特殊的路径名,看起来像fugitive:///path/to/repository/.git//0/path/to/file/under/repository(fugitive捕获对所命名缓冲区的读取和写入,并通过调用Git “plumbing”命令将它们重定向到索引)。 directory中的第一个条目通常是.。这意味着Vim将尝试将交换文件放在编辑文件的相同目录中(即foo/bar.txt将尝试使用foo/.bar.swp)。如果无法创建首选交换文件,则会尝试使用directory中的后续条目。
.作为第一个directoryfugitive:///path/to/repository/.git//0/path/to/file/under/repository的首选交换文件将是fugitive:///path/to/repository/.git//0/path/to/file/under/.repository.swp。这个路径名的前导组件(fugitive:pathto等)可能不存在,所以Vim将继续使用directory的下一个条目。如果没有其他directory条目可用于创建交换文件(例如,它们不存在),则会出现错误E302。
我使用set directory=.,~/no-such-dir,/var/no-such-dir,/no-such-dir在类Unix系统上重现了您的问题(即采用默认的Unix值并将tmp的出现更改为no-such-dir)。这些“no-such-dir”目录实际上都不存在。当我使用:Gdiff时,我得到了相同的错误。 1:help :set^=仅说“添加”,但代码显示set listopt^=…类似于set listopt+=…附加(后者被记录为这样做)。两者都应根据需要自动插入逗号(尽管这个领域可能存在错误)。

我想知道为什么Fugitive允许对fugitive:///path/to/repository/.git//0/path/to/file/under/repository缓冲区进行读写操作?为什么它们不是只读的?在我的情况下,我可以修改这些缓冲区,如果我保存它们然后执行git diff,输出会受到影响。 - Hải Phong
1
@HảiPhong:还可以尝试使用git diff --cached。通过伪路径名(例如fugitive://…/.git//0/…),编辑和保存它们等同于直接更改为下一次提交暂存的内容(即Git的“索引”:stage 0)。如果您有信心使用索引来制作下一个提交,它可以成为强大的工具(例如git add或带有--patchgit reset,但更加直接)。如果您不想使用索引,可以使用git reset <pathname>(或在相关缓冲区中使用:Gread -)来“清除”其内容(使其与HEAD匹配)。 - Chris Johnsen
哇,这解释了很多问题。谢谢。 - Hải Phong

1

这可能与我在SO答案中提到的msysgit问题428有关(issue 428 of msysgit mentioned in my SO answer)

尝试按照我以前的回答所描述的方法修补 cmd/git.cmd,看看这是否有帮助。

除此之外,还有两个选择:

  • 可能是锁定问题(文件被进程锁定):像process monitorprocess explorer这样的实用程序可以帮助查看是否存在这种情况(以及确切的交换文件句柄)。
  • 也可能是Git的问题。一个好的技巧是安装msysgit的net-installer,它会在Windows上构建最新版本的Git。然后你可以尝试看看是否使用该更新版本仍然存在问题。
    注意:第三个选项是尝试降级Git,以排除与该工具的任何链接。

我已经修补了git.cmd,这解决了之前的问题(顺便感谢你)。 - Paul Wicks
@Paul:我没意识到你是之前那个提问的人!;) - VonC
我检查了交换文件,看起来vim是唯一一个处理这些文件的应用程序。我正在检查不同版本的msysgit,并在github上提交了一个问题。 - Paul Wicks

1

顺便说一下,我遇到了同样的错误,当我尝试对未保存的文件使用:gdiff命令时也会出现这种情况 - 当我进行保存 (:w) 就可以正常工作了!


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