在git diff中配置临时文件夹是否可行?

11
在本地存储库中调用git difftool时,Git会将修改后的文件与其远程匹配项进行比较。为此,它会创建一个临时文件来代表远程匹配项,并设置变量LOCALREMOTE,调用在Git配置中指定的差异工具。默认情况下,临时文件会创建在/tmp/<hash>_filename中。 是否可以更改此默认位置?

为什么要这样做?

简而言之,我正在使用Windows子系统来操作Git,并想使用Windows工具来进行差异和合并。问题是,/tmp无法从Windows一侧访问,因此我需要将Git创建临时文件的默认位置移动到Windows可访问的地方。

我尝试过的:

到目前为止,我所能找到的建议是执行sudo mount -B /tmp /mnt/c/tmp,但这似乎不起作用(/tmp仍然指向以前的目录...)

2
你尝试设置 TMPDIR 环境变量了吗? - sergej
不,老实说我从没听说过。我会去查一下。 - GPhilo
2
好的,这样做了(有些过度杀伤力)。我希望这可以通过git配置禁用,而不是系统范围内的变量..现在我在控制台中运行的所有命令都将使用我的新tmp位置。@sergej如果你把它作为答案添加,我至少会点赞(如果没有其他仅限于git的选项存在,我会将其标记为实际答案)。我还会为像我这样的Linux外行人提供关于TMPDIR的最小解释;) - GPhilo
2
这是Git。Git创建临时文件,然后将“LOCAL”和“REMOTE”设置为临时文件的路径和存储库中匹配文件的路径。最后,它使用设置的环境变量调用“.gitconfig”中指定的命令。 - GPhilo
1
@Liam 是的,那正是我正在做的事情。然而,自定义命令将 LOCALREMOTE 作为两个要进行差异比较的文件的参数。我的问题在于 LOCAL 的创建位置,而不是调用外部工具。 - GPhilo
5个回答

8
您可以尝试设置TMPDIR环境变量。
来自POSIX手册:

TMPDIR此变量应表示可供需要创建临时文件的程序使用的目录的路径名。


快速查看git代码(git/builtin/difftool.c)后,我认为当前不支持配置临时目录:
/* Setup temp directories */
tmp = getenv("TMPDIR");
xsnprintf(tmpdir, sizeof(tmpdir), "%s/git-difftool.XXXXXX", tmp ? tmp : "/tmp");

似乎 git 正在使用 TMPDIR 值,或者如果 TMPDIR 未定义,则使用 "/tmp"。

1
在此我添加一条评论,该问题下我已经说过:这个方法可行,但是它会改变控制台中运行的所有命令/tmp。我认为这有点过了,所以我希望能够在 git 的配置中设置这个。 - GPhilo
1
我刚刚一直在查找源代码中的这行。干得好。如果你真的非常想要这个功能,可以在邮件列表上发布一个功能请求。 - Liam
哇,我猜这就解决了。 - GPhilo
如果您的difftool是tkdiff,请确保您的~/.tkdiffrc文件没有将tmpdir定义为它可能会覆盖您的shell环境的TMPDIR。 - Dom

2
默认情况下,临时文件会被创建在路径 /tmp/<hash>_filename 中。
是否可以更改这个默认位置呢?
不完全可以,但是从 Git 2.37(2022年第三季度)开始,传递给外部diff命令的临时文件现在会在同一基本名称下的一个新临时目录中生成。
查看提交8af7593提交2c2db19(2022年4月20日),作者为René Scharfe (rscharfe)
(由Junio C Hamano -- gitster --提交2e96975中合并,2022年5月20日)

diff: 使用mks_tempfile_dt()

签名:René Scharfe

Git使用临时文件将blob的内容传递给外部的diff程序和textconv过滤器。
它调用mks_tempfile_ts()来创建这些文件,这会将它们全部放在同一个目录中。
这需要添加一个随机名称前缀。

相反地,使用mks_tempfile_dt(),它允许文件具有任意名称,并且每个文件都位于自己独立的临时目录中。
这样它们可以与原始blob具有相同的基本名称,在图形化diff程序中更美观。

tempfile: 添加 mks_tempfile_dt()

签名:René Scharfe

添加一个函数,用于在使用 mkdtemp(3) 创建的临时目录中创建具有特定名称的临时文件。
它的结果比使用 mks_tempfile_ts() 创建的路径更美观,后者包括一个随机前缀。
这对于传递给显示其名称的程序(例如外部的 diff 工具)的文件非常有用。


2

同样的问题,解决方案不是更改git的临时目录,而是使用差异脚本来定义:

  1. Define script for diff in .gitconfig

    [diff]
    external = /home/user/scripts/my_diff.sh
    
  2. Create script /home/user/scripts/my_diff.sh to use the Windows tool:

    #!/bin/bash
    FILE2="C:\\dev\\wsl\\Debian\\rootfs\\${2//\//\\}"
    FILE1=$(wslpath -w $5)
    /c/Program\ Files\ \(x86\)/WinMerge/WinMergeU.exe $FILE1 $FILE2
    
在我的例子中,我使用的是WinMerge。
我知道这种解决方案违反了Windows工具不允许触及Linux文件的规则,但我对此感到满意,因为我们正在谈论一个临时文件,而且我不认为在WinMerge中更改它有任何意义。 手动路径替换是必要的,因为wslpath无法处理Linux内部路径。
你的WSL可能不同,通常会在某个地方。
C:\Users\%username%\AppData\Local\Packages\TheDebianProject.DebianGNULinux_76v4gfsz19hv4\LocalState\rootfs

这种方法有些不太正规,但我现在正在使用它,并且一直很满意。

0

将以下内容放入您的Windows/HOME目录下的.gitconfig文件中。 您需要安装cygwin以使用cygpath(和git)命令, 并调整下面WinMerge的位置。

[difftool "winmerge"]
         # Usage: git difftool --tool winmerge
        path = C:/bin/WinMergeU.exe
        cmd =  C:/bin/WinMergeU.exe \"$(cygpath -wam $LOCAL)\" \"$(cygpath -wam $REMOTE)\"

0

我为自己的使用制作了两种方法的变体。我创建了一个脚本,我称之为代替运行git diff(如果复制,请更改“twm”路径,那是我的用户目录):

#!/bin/bash                                                                     

export TMPDIR=$( realpath --relative-to=. /mnt/c/Users/twm/tmp )
git difftool -y -t winmerge "$@"

我专门针对在Windows子系统中运行的Git调用WinMerge。使用TMPDIR时遇到的问题是,虽然Git写入了它,但WinMerge没有识别临时路径,最初是因为它以“/mnt/c”开头 - 我已经让WSL和Windows之间的路径匹配,除了前导的“c:”,但WinMerge仍然无法识别它。然而,我注意到另一个路径被正确识别,并且ps显示它作为相对路径传递给WinMerge,因此我也使用realpath使TMPDIR成为相对路径。
使用脚本在本地设置TMPDIR还解决了评论中提到的一个问题。即,为这个用例更改所有其他程序的临时目录似乎有些过度,并可能产生一些意想不到的副作用。
像这里列出的第二种方法一样,我也尝试使用Git别名来解决这个问题。但是,我希望利用Git现有的WinMerge集成,以防内置集成提供比硬编码脚本更多的功能,现在或将来。

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