Using Git for Windows' 'git' out of '--exec-path' (MSYS2) from Cygwin

117 Views Asked by At

Git for Windows uses MSYS2 which is derived from Cygwin. While the location where "cygdrive" (Cygwin uses /cygdrive, MSYS2 uses /) gets mounted, differs by default, it can be brought into a form that is be compatible between both flavors which is prefixed /proc/cygdrive (using cygpath -U ...).

Why do I need this?

  1. while Cygwin features a git package, there is no git-lfs. This led to quite some confusion initially, because the Git/cmd/git-lfs from Git for Windows was found and used by Cygwin, but turned out to be incompatible with the git from Cygwin's package. Sure, I could build my own git-lfs, but I don't want to. I want to leverage the Git for Windows installation that is already installed on our developers' systems.
  2. Process creation on Windows in the Win32 subsystem is much more expensive than a clone() or fork() on -- say -- Linux. Therefore I would like to avoid the complexity in my script to call cygpath across all sorts of of git invocations in one environment, but not the other ... so avoiding the spawning of additional processes is a real performance factor.

The problem

From the perspective of MSYS2 there is no Cygwin environment, so it gets to see the path for external tools, i.e. %ProgramFiles%\Git\cmd, hence C:\Program Files\Git\cmd\git.exe (or from Cygwin's perspective: /cygdrive/c/Program Files/Git/cmd/git).

This "flavor" of git expects the path in Windows respresentation, i.e. the form that cygwin -w or cygwin -m spit out.

Using "/cygdrive/c/Program Files/Git/cmd/git" --exec-path I am able to find the canonical path for Git for Windows' "exec directory":

$ cygpath -Ua "$("$(type -p git)" --exec-path)"
/proc/cygdrive/c/Program Files/Git/mingw64/libexec/git-core

Inquiring --exec-path again I can determine if this is the end of the indirection.

So, by using the following, I can populate a shell variable GITBIN with the absolute canonical path to git from Git for Windows, which ought to work in Cygwin and MSYS2 alike:

GITBIN="$(cygpath -Ua "$("$(type -p git)" --exec-path)")/git"

At this point I would expect that I can call $GITBIN using an absolute canonical path retrieved on the MSYS2 side using cygpath -Ua ....

Suppose the git repo I want to act on is checked out in /proc/cygdrive/x/gitrepo and Cygwin lets me change into that directory or list its contents.

Question

Why does the following fail?:

$ "$GITBIN" -C "/proc/cygdrive/x/gitrepo" status
fatal: cannot change to '/proc/cygdrive/x/gitrepo': No such file or directory

What I also tried

MSYS2 allows to use environment variables to control implicit path conversion. I have tried starting $GITBIN as follows:

env MSYS_NO_PATHCONV=1 "$GITBIN" -C /proc/cygdrive/x/gitrepo status

I also tried setting MSYS2_ARG_CONV_EXCL="-C" and I tried using --work-tree=/proc/cygdrive/x/gitrepo/.git instead of -C /proc/cygdrive/x/gitrepo in all permutations with these environment variables. But no luck ... the only difference was that the error message reads now fatal: not a git repository (or any of the parent directories): .git.

Then I even tried to coerce the $GITBIN into thinking it runs inside MSYS2 by setting environment variables, but admittedly I could be missing some:

env MINGW_CHOST=x86_64-w64-mingw32 MINGW_PREFIX=/mingw64 MSYSTEM_CARCH=x86_64 MSYSTEM_CHOST=x86_64-w64-mingw32 MSYSTEM_PREFIX=/mingw64 MSYSTEM=MINGW64 "$GITBIN" -C /proc/cygdrive/x/gitrepo status

Nothing seems to convince MSYS2 from the outside to consider the passed path already to be suitable for it and only internally convert it.

1

There are 1 best solutions below

0
0xC0000022L On

So far the only workaround I have found is to use the representation that cygpath -m returns across MSYS2 and Cygwin. I.e. basically Windows paths with a drive letter, but forward slashes instead of backslashes, e.g. X:/gitrepo for /proc/cygdrive/x/gitrepo from the question.

This seems to be more "portable" even than the representation that cygpath -Ua returns.

But this was all deduced from observation of the behavior and not from looking at the code.

NB: If there is someone who can 1) at least explain why the MSYS2-git.exe refuses the provided path and 2a) provide a working alternative with cygpath -Ua or 2b) provide authoritative sources that confirm that cygpath -m should be used across the board, I shall accept and upvote that answer.