In this article I'll document my process for setting up Git Bash / MINGW / MSYS2 on Windows including some additional configuration (e.g. installing make
and apply some customizations via .bashrc
).
Table of contents
- Introduction
- How to install and update Git Bash / MINGW / MSYS2 via Git for Windows
- Update MINGW
- How to install make
- Configuration via .bashrc
- Common issues
- The role of winpty: Fixing "The input device is not a TTY"
- The path conversion issue
- Fixing the path conversion issue for MINGW / MSYS2
- Fixing the path conversion issue for winpty
- Miscellaneous
- Change the bash custom prompt to a $
Introduction
When I was learning git
I started with the fantastic Git for Windows package, that is maintained in the git-for-windows/git
Github repository and comes with Git Bash, a shell that offers a Unix-terminal like experience. It uses MINGW and MSYS2 under the hoodand does not only provide git
but also a bunch of other common Linux utilities like
bashsedawklscprm...
I believe the main "shell" is actually powered by MINGW64 as that's what will be shown by default:
Thus, I will refer to the tool as MINGW shell or Git Bash throughout this article.
I have been using MINGW for almost 10 years now, and it is still my go-to shell for Windows. I could just never warm up to WSL, because the file sharing performance between WSL and native Windows files was (is?) horrible - but that's a different story.
How to install and update Git Bash / MINGW / MSYS2 via Git for Windows
You can find the latest Git for Windows installation package directly at the homepage ofhttps://gitforwindows.org/. Older releases can be found on Github in the Releases section of the git-for-windows/git
repository
Follow the instructions in the How to Install Git Bash on Windows article on git-tower.comto get a guided tour through the setup process.
After the installation is finished, I usually create a desktop icon and assign the shortcut CTRL + ALT + B
(for "bash") so that I can open a new shell session conveniently via keyboard.
Update MINGW
To update Git for Windows, you can simply run
git update-git-for-windows
See also theGit for Windows FAQ under "How do I update Git for Windows upon new releases?"
Git for Windows comes with a tool to check for updates and offer to install them. Whether or not you enabled auto-updates during installation, you can manually run
git update-git-for-windows
.
You can check the current version via git version
$ git --versiongit version 2.37.2.windows.2
How to install make
As perHow to add more to Git Bash on Windows: make
:
- Go to ezwinports
- Download file
make-4.3-without-guile-w32-bin.zip
(get the version without guile) - Extract zip
Copy the contents to your
Git/mingw64/
directory, merging the folders, but do NOToverwrite/replace any existing files- navigate to the
Git/mingw64/
directory via
$(cd /; explorer .)
- navigate to the
Test via make version
$ make --versionGNU Make 4.3.1Built for Windows32Copyright (C) 1988-2016 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.
PS: There's also an alternative way that I've outlined inInstall make on Windows (MinGW),though the one explained here is easier/faster.
Configuration via .bashrc
The MINGW shell is a bash
shell and can thus be configured via a .bashrc
file located at the home directory of the user. The shell supports the ~
character as an alias for the home directory, i.e. you can use ~/.bashrc
to refer to the full path of the file. This means you can also edit it easily via vi ~/.bashrc
- though I prefer an actual GUI editor likeNotepad++. A common workflow for me to open the file is running the following commands in a MINGW shell session
# navigate to to the home directorycd ~# open the file explorerexplorer .
My .bashrc
file usually includes the following setup:
# Get bash completion for make targets by parsing make files in the current directory at # the file "Makefile"# all files with a ".mk" suffix in the folders ".make" and ".makefile"# see https://stackoverflow.com/questions/4188324/bash-completion-of-makefile-target# Notes:# -h hides filenames# -s hides error messagescomplete -W "\`grep -shoE '^[a-zA-Z0-9_.-]+:([^=]|$)' Makefile .make/*.mk .makefile/*.mk | sed 's/[^a-zA-Z0-9_.-]*$//' | grep -v PHONY\`" make# Docker login helper# see https://www.pascallandau.com/blog/structuring-the-docker-setup-for-php-projects/#easy-container-access-via-din-bashrc-helperfunction din() { filter=$1 user="" if [[ -n "$2" ]]; then user="--user $2" fi shell="bash" if [[ -n "$3" ]]; then shell=$3 fi prefix="" if [[ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]]; then prefix="winpty" fi ${prefix} docker exec -it ${user} $(docker ps --filter name=${filter} -q | head -1) ${shell}}
Links:
- SO: bash completion of makefile target
- Easy container access via din .bashrc helper
Common issues
TheGit for Windows Known Issues pagelists common problems with Git Bash and I want to provide some more context (and solutions) to the things that I have encountered.
The role of winpty
: Fixing "The input device is not a TTY"
I encountered the The input device is not a TTY
error while using docker
. To log into a running docker
container or starting a container with a login session, the-i
(Keep STDIN open even if not attached) and -t
(Allocate a pseudo-tty) options must be given:
For interactive processes (like a shell), you must use
-i
-t
together in order to allocate a tty for the container process.-i
-t
is often written-it
.
But attempting to do so via
docker run --rm -it busybox sh
yields the following error:
$ docker run --rm -it busybox shthe input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'
Fortunately, the fix is included in the message: Prefix the command with winpty
. Doing soworks as expected:
$ winpty docker run --rm -it busybox sh/ #
winpty
is according to it's readme
[...] a Windows software package providing an interface similar to a Unix pty-master for communicating with Windows console programs. The package consists of a library (libwinpty) and a tool for Cygwin and MSYS for running Windows console programs in a Cygwin/MSYS pty.
So kind of a translator between your "Windows input" and the "command input" to create input that is compatible with a Unix pty (pty=pseudoterminal interface), e.g. for docker
.
According to theGit for Windows Known Issues page,there are a number of other cases where winpty
is required (though I personally didn'tencounter them yet):
Some console programs, most notably non-MSYS2 Python, PHP, Node and OpenSSL, interact correctly with MinTTY only when called through
winpty
(e.g. the Python console needs to be started aswinpty python
instead of justpython
).
CAUTION: I've seen people put an alias in their .bashrc
file to always prefix docker
commands automatically with winpty
like so:
alias docker="winpty docker"
However, winpty
seems to break pipingand can lead to unexpected results like the error stdout is not a tty
. See the following example:
$ docker run --rm busybox echo "foo" | catfoo
$ winpty docker run --rm busybox echo "foo" | catstdout is not a tty
You might work around this by adding the(undocumented) -Xallow-non-tty
flag like so
$ winpty -Xallow-non-tty docker run --rm busybox echo "foo" | catfoo
But this doesn't seem to be a catch-all solutionand I would recommend against using it as a default - or if you do, only use it when the -it
flag is used as proposed in this answer.
The path conversion issue
Ah. This one has given me lots of headaches over the years. MINGW, MSYS2 and winpty
use automatic conversion of Unix paths to Windows paths, e.g. /foo
gets translated to something likeC:/Program Files/Git/foo
where C:/Program Files/Git/
is the installation directory of the Git for Windows installation.
Fixing the path conversion issue for MINGW / MSYS2
First, the behavior is mentioned on theGit for Windows Known Issues page
If you specify command-line options starting with a slash, POSIX-to-Windows path conversion will kick in converting e.g. "
/usr/bin/bash.exe
" to "C:\Program Files\Git\usr\bin\bash.exe
". When that is not desired -- e.g. "--upload-pack=/opt/git/bin/git-upload-pack
" or "-L/regex/
" -- you need to set the environment variableMSYS_NO_PATHCONV
temporarily, like so:
MSYS_NO_PATHCONV=1 git blame -L/pathconv/ msys2_path_conv.cc
Alternatively, you can double the first slash to avoid POSIX-to-Windows path conversion, e.g. "
//usr/bin/bash.exe
".
and also documented forMINGW at "Posix path conversion",but it's still brought up regularly, see e.g.GH #3619: "/" is replaced with the directory path of Git installation when using MinGW64 Bash.orSO: How to stop MinGW and MSYS from mangling path names given at the command line
Example
$ docker run --rm busybox ls /fools: C:/Program Files/Git/foo: No such file or directory
As quoted above, it can be solved by either
adding an additional
/
to the path$ docker run --rm busybox ls //fools: /foo: No such file or directory
prefixing the command with
MSYS_NO_PATHCONV=1
$ MSYS_NO_PATHCONV=1 docker run --rm busybox ls /fools: /foo: No such file or directory
or exporting the
MSYS_NO_PATHCONV=1
variable as an environment variable to disable the behavior completely$ export MSYS_NO_PATHCONV=1$ docker run --rm busybox ls /fools: /foo: No such file or directory
CAUTION: The value of the MSYS_NO_PATHCONV
variable does not matter - we can also set it to 0
, false
or an empty string. It only matters that the variable is defined!
$ MSYS_NO_PATHCONV=0 docker run --rm busybox ls /fools: /foo: No such file or directory
This is particularly important when using the environment variable approach. In order to selectively enable the path conversion again, you must unset the MSYS_NO_PATHCONV
first via env -u MSYS_NO_PATHCONV ...
, e.g.
$ env -u MSYS_NO_PATHCONV docker run --rm busybox ls /fools: C:/Program Files/Git/foo: No such file or directory
CAUTION: I've seen people adding MSYS_NO_PATHCONV=1
permanently to their environment intheir .bashrc
file to always disable path conversion via
export MSYS_NO_PATHCONV=1
However, this can have some unintended side effects. When I tried it out,my local installation of the gcloud clistopped working with the error
$ MSYS_NO_PATHCONV=1 gcloud versionC:\Users\Pascal\AppData\Local\Programs\Python\Python39\python.exe: can't open file 'C:\c\Users\Pascal\AppData\Local\Google\Cloud SDK\google-cloud-sdk\lib\gcloud.py': [Errno 2] No such file or directory
So instead I recommend setting MSYS_NO_PATHCONV=1
either selectively per command or scope itto the use case. I do this for example in my Makefiles by only exporting it for the scope ofmake
(and all scripts make
invokes) by putting the following code in the beginning of the Makefile:
# OS is a defined variable for WIN systems, so "uname" will not be executedOS?=$(shell uname)# Values of OS:# Windows => Windows_NT # Mac => Darwin # Linux => Linux ifeq ($(OS),Windows_NT) export MSYS_NO_PATHCONV=1endif
The path conversion is also documented forMSYS2 at "Filesystem Paths: Automatic Unix ⟶ Windows Path Conversion"and can be disabled via the MSYS2_ARG_CONV_EXCL
environment variable:
[...] For these cases you can exclude certain arguments via the
MSYS2_ARG_CONV_EXCL
environment variable: [...]MSYS2_ARG_CONV_EXCL
can either be * to mean exclude everything, or a list of one ore more arguments prefixes separated by ;, likeMSYS2_ARG_CONV_EXCL=--dir=;--bla=;/test
. It matches the prefix against the whole argument string.
I.e. setting the variable as MSYS2_ARG_CONV_EXCL="*"
should disable the path conversion completely. I myself have never had to use this, though. Using MSYS_NO_PATHCONV
was always sufficient.
Fixing the path conversion issue for winpty
Unfortunately, winpty
suffers from this path conversion issue as well. In the standard installation of Git for Windows we can even see this by simply using echo
:
$ winpty echo /C:/Program Files/Git
The behavior is known and flagged as a bug e.g. inGH issue #411: Path conversion with and without winpty differs.
Remember the example I gave in sectionThe role of winpty e.g. when using docker?
$ winpty docker run --rm -it busybox sh/ #
Now let's extend this and throw a volume into the mix:
$ winpty docker run --rm -v foo:/foo -it busybox shdocker: Error response from daemon: create foo;C: "foo;C" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
winpty
converts /foo
to C:/Program Files/Git/foo
so that the volume definition becomes-v foo:C:/Program Files/Git/foo
- which is of course invalid.
Using an additional /
as a prefix does work here as well:
$ winpty docker run --rm -v foo://foo -it busybox sh/ #
But there is no environment variable that we could use. The only way to "fix" the path conversion is using a newer release of winpty
and replace the one that is shipped together with Git for Windows as proposed by the maintainer of winpty
.
This comment outlines the full processto replace winpty
and is (slightly adapted) as follows:
# create temporary directorymkdir tempcd temp# download a newer releasecurl -L https://github.com/rprichard/winpty/releases/download/0.4.3/winpty-0.4.3-msys2-2.7.0-x64.tar.gz --output winpty.tar.gz# extract the archivetar -xvf winpty.tar.gz# copy the content of the bin/ folder to `/usr/bin` # (which resolves to e.g `C:/Program Files/Git/usr/bin`; replaces any existing files)cp winpty-0.4.3-msys2-2.7.0-x64/bin/* /usr/bin# delete the temporary directorycd ..rm -rf temp/
Once the new version is installed, the path conversion does not happen any longer (even without specifying any environment variables).
Related comments:
- https://github.com/docker/for-win/issues/1588#issuecomment-594938988
- https://github.com/docker/for-win/issues/1588#issuecomment-698080757
CautionAfter updating MinGW, the fix for winpty
is "gone"!
I.e. you need to re-run the steps above every time you run an update.
Miscellaneous
Some stuff that I need from time to time - not necessarily only relevant for Git Bash.
Change the bash
custom prompt to a $
Via PS1=" $"
:
Pascal@LAPTOP-0DNL2Q02 MINGW64 ~$ PS1="$ "$
See How to Change / Set up bash custom prompt (PS1) in Linux
Wanna stay in touch?
Since you ended up on this blog, chances are pretty high that you're into Software Development (probably PHP, Laravel, Docker or Google Big Query) and I'm a big fan of feedback and networking.
So - if you'd like to stay in touch, feel free to shoot me an email with a couple of words about yourself and/or connect with me on LinkedIn or Twitter or simply subscribe to my RSS feed or go the crazy route and subscribe via mail and don't forget to leave a comment :)
Subscribe to posts via mail