Sunday, July 11, 2010

A short note on Cygwin git

I use git for my source control, and when developing under Windows, I use the Cygwin environment for all of my command line needs.  My background is primarily Unix, so I'm used to having a powerful shell prompt and scripting for a lot of tasks.  I also use the git available from Cygwin instead of the one from the git site.

You will quickly run into execute permission problems and CRLF vs. LF translation problems.

Execute bit


Windows doesn't manage the execute bit very well, especially on a FAT filesystem, but I find it even on NTFS.  Files created under Cygwin will be created according to your umask, usually as mode 0644, while files from Windows will show up as 0700.  This isn't a real problem except that git tracks the mode of each file in the repository, so changes to the mode will show up as the file being modified.  Setting core.filemode to false tells git to ignore the executable bit.  If something slips in, you may have to use git update-index --chmod=-x to correct it.

core.filemode is set in your .git/config file by git init regardless of how it's set in your system or global configuration, so you will need to set it in your repository configuration.

CRLF vs. LF


Files created under Cygwin will use only LF to mark end of line, while files created under Windows applications will use CRLF.  By setting core.autocrlf to true, Cygwin git will convert all CRLFs to LFs on commit operations, and all LFs to CRLFs when checking out.

I also set core.safecrlf to warn, which checks, before adding a file, that doing the crlf conversions is "safe".  We want to make sure that we'll get the same file back when it's checked out.  Git cannot "safely" convert files that contain both LFs and CRLFs, so a file that's been edited under both Windows and Cygwin may produce warning: LF will be replaced by CRLF in Foo.java when running git add.  This is not a problem with text files, because the file will be cleaned up during its next commit so that all EOLs are the same.  However, binary files will be corrupted if they are not properly detected by git.  I have never seen git label a binary file as text, but if this does occur you can set the file in .gitattributes as binary.  For example
   *.jpg binary
will make git consider all .jpg files as binary, and will not apply the CRLF conversion, nor will it try a text diff.  

You can also set core.safecrlf to true instead of warn, in which case the error will be fatal, and you will have to correct the problem before you can add the file.  You can run a text file through unix2dos, or add the binary file to .gitattributes, but since git bats a thousand, in my experience, at detecting binary files, it's a waste of time to have to manually fix all of your text files.

TL;DR


So in conclusion, if developing using git under Cygwin, I run the following commands after creating a repository:
   git config core.autocrlf true
   git config core.safecrlf warn
   git config core.filemode false
Explanations of these settings can be found on the git-config man page.

No comments:

Post a Comment