DEV Community

Cover image for ๐Ÿ™ Please Add .gitattributes To Your Git Repository
Carl Saunders
Carl Saunders

Posted on • Updated on

๐Ÿ™ Please Add .gitattributes To Your Git Repository

What Is .gitattributes?

The .gitattributes file allows you to specify the files and paths attributes that should be used by git when performing git actions, such as git commit, etc.

In other words git automatically saves the file according to the attributes specified, every time a file is created or saved.

One of these attributes is the eol (end of line) and is used to configure the line endings for a file. This article will now dive deeper into how to configure the line endings, so every developer uses the same value when using different machines / OSes across the repository.

Why .gitattributes (Developers At War โš”๏ธ)?

Not all developers are the same, just because you develop on a Windows machine using Visual Studio Code, don't expect the next pull request to have been implemented using the same dev environment (MacOS machine using Sublime Text 2).

As mentioned above the developers are using different OSes (Windows and MacOS) the default for the line ending will differ. On the Windows machine the default for the line ending is a Carriage Return Line Feed (CRLF), whereas on Linux/MacOS it's a Line Feed (LF).

To the naked eye the content will look the same, so why should we bother???

Well, if you have prettier enabled and the endOfLine property is set to lf.

{
  "endOfLine": "lf"
}
Enter fullscreen mode Exit fullscreen mode

On the Windows machine the developer will encounter linting issues from prettier, like those below.

Code File With Prettier Linting Errors - .gitattributes

Code File With Prettier Linting Errors

This is where .gitattributes comes to the rescue and saves the day ๐Ÿฆธ!

New Repository (Repo)

To add the .gitattributes to the repo first you need to create a file called .gitattributes into the root folder for the repo.

Below is an example of the contents for the .gitattributes file.

*.js    eol=lf
*.jsx   eol=lf
*.json  eol=lf

Enter fullscreen mode Exit fullscreen mode

Commit this file to the repo and push your changes to the server.

git add .
git commit -m "Added .gitattributes to repo"
git push
Enter fullscreen mode Exit fullscreen mode

Now when anyone gets the code from the repo the default correct line ending will be used automatically via git, when creating and modifying the files.

Add to Existing Git Repository (Repo)

Follow the steps mentioned in the New Repository (Repo) steps to create the .gitattributes file. Once the file has been pushed to the git server then make sure that your local repo is clean and has nothing to commit. Use git status to determine whether your repo is clean.

git status
Enter fullscreen mode Exit fullscreen mode

Note: If you still have files to push or commit, please make sure that these actions are performed or the files are stashed before you perform the next commands.

GitAttributes Reset

git rm --cached -r .
git reset --hard
Enter fullscreen mode Exit fullscreen mode

The above commands will now update the files for the repo using the newly defined line ending as specified in the .gitattributes.

Any changes or new changes will automatically use the line endings specified for that file type.

Next step is to inform any team mate or collaborator, to run the GitAttributes Reset commands.

Now prettier won't complain about CR and all developers can now live in peace! โ˜ฎ๏ธ

Code File With No Linting Errors - .gitattributes

Code File With No Prettier Linting Errors

Top comments (69)

Collapse
 
tiguchi profile image
Thomas Werner

There's also an option that makes everyone happy: Let the git installation on a user's machine decide which line ending to use when a repository is checked out:

* text=auto
Enter fullscreen mode Exit fullscreen mode

That way it really doesn't matter and Windows users can still open their files using Notepad if they wish (I'm not judging ๐Ÿ˜„).

AFAIK line endings are committed to the repository "normalized" as LF, but the checked out version depends on the OS default for line endings.

The setting can be also fine tuned with additional overrides in case there are specific file types that need their line endings preserved (e.g. shell scripts or Windows batch files)

See also: help.github.com/en/github/using-gi... and git-scm.com/docs/gitattributes

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
moopet profile image
Ben Sinclair

Ah, the glory days of Unux and Linix.

Collapse
 
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan • Edited

I admit to still typing notepad into Run/cmd/PS on occasion, but I swear it's only for notes I plan to throw away quickly lol

Literally me, lol!

Windows + R, type notepad, and then dump my thoughts in there from time to time (usually my TODOs for the day). It's good to have such a minimal editor on hand, without all those UI distractions.

Collapse
 
charlesroper profile image
Charles Roper

Install Notepad2-mod, choose to replace Notepad when you install it, and you'll get all the lightweight joy of old Notepad with just enough extra sprinkles (like lf support and syntax highlighting) to make it practical.

xhmikosr.github.io/notepad2-mod/

Collapse
 
vtvh profile image
Hแบฃi

I'm a heavy Windows desktop user. But live primarily in wsl terminal nowadays.

Btw, that Regex would match Unux๐Ÿ˜

Collapse
 
deadlybyte profile image
Carl Saunders

Thanks for this additional information. Please NO, not Notepad!!! ๐Ÿ˜€

Collapse
 
rtpharry profile image
Matthew Harris

Haha I moved to macOS at the start of the year and I miss notepad. :P

TextEdit can be configured close but it's not the same.

I also never realised how much I used WIN+R as a quick scratchpad when I found myself distracted by another task but still had something live in my clipboard.

Thread Thread
 
pclundaahl profile image
Patrick Charles-Lundaahl

Try sublime text!

Thread Thread
 
ytjohn profile image
YourTech John

Check out Quiver for macOS. Create notes within notebooks, and each note can have cells of markdown, code blocks, or sequence diagrams.

happenapps.com/#quiver

For other platforms, check out Joplin. It's not as nice as quiver, but shares some of the same ideas.

Thread Thread
 
tiguchi profile image
Thomas Werner

I miss that app so much... I switched to Linux from Mac OS a while ago, and that one was one of my most favorite productivity apps.

My crude workaround at the moment is Typora. It's not bad, but not nearly as polished as Quiver.

I will check out Joplin soon. Thanks for the tip!

Thread Thread
 
xevion profile image
Xevion

Currently using Joplin. It is amazing, and a quick look at Quiver yields a very similar look. I don't know of any implementation that allows "sharing" notebooks like I saw in a screenshot of Quiver, but otherwise, Notebooks with sub-notebook organization, Markdown is possible. Also, there seem to be a lot more methods for accessing Joplin on different platforms, with Windows/MacOS/Linux/Android/iOS/Terminal implementations with DropBox and other file storage services. Highly recommended.
Also, Joplin is FREE. Major bonus.

Collapse
 
mistval profile image
Randall

As a (mainly) Windows user I always disable autocrlf and standardize on LF because:

  1. If I'm building Docker images (and I often am), I don't want to be copying CR LF files into the Docker images. Some Linux utilities will choke on them.

  2. If my program reads, say, XML files, I don't want the (multiline) strings going through my code to differ depending on my OS, this has bit me before too.

  3. If I calculate a hash on a file I want it to be the same on any OS.

  4. While I have had problems with CR LF files on Linux, I have never had problems with LF files on Windows (I don't use Notepad).

Collapse
 
joepkockelkorn profile image
Joep Kockelkorn

@mistval Thanks for your comment, it got me thinking ๐Ÿ˜ƒ.

For 1., isn't it wise to convert the line-endings to fit the target OS anyway? In your situation, if you want a Windows image in the future and copy over any files with LF endings, you will have the same problem.

For 2., this would also be solved if you take the solution from up above, convert the line-endings before running your code as a Docker container. But it depends on your use case as well: What are the files used for?; Who will use them in the future? etc.

For 3., if you use git hash-object to calculate the hash it will take into account the core.autoclrf or text=auto settings so the hash should be the same, even on a different OS.

You could also have issues on Windows by defaulting to LF for non-binary files like .bat.

Thread Thread
 
mistval profile image
Randall

Hi Joep, you have some good points. I suppose I just am rarely in situations where LF breaks things. I rarely run .bat files and I never build Windows images.

Ultimately it's ideal if repos have .gitattributes, if not, I've had a lot more luck with configuring git to default to LF than using autocrlf.

Collapse
 
doctorderek profile image
Dr. Derek Austin ๐Ÿฅณ

This doesn't work because if you have ESLint set to error then (like to error on Prettier) than Windows developers will get CRLF endings with errors on every line. They'll have to "eslint . --fix" and make a fake commit to fix the problem.

  • text=auto can't be the solution, since it's the default...
Collapse
 
tiguchi profile image
Thomas Werner

I think your remark misses the point I was originally trying to make, which is to give developers the freedom to use whatever line ending they want to use on their development platform.

Enforcing \n via ESlint rule defies that purpose, so why did you set up your project with that .gitattributes rule?

Also why don't you just disable that line ending ESlint rule since it's safe to assume that the line endings are always correct on the platform where you check out and build your project. There is no point in checking for \n line endings using that .gitattributes setting.

Thread Thread
 
doctorderek profile image
Dr. Derek Austin ๐Ÿฅณ

Hey Thomas! Thanks for your thoughtful reply.

I agree 100% that the ESLint line ending rule is pointless and dumb. But I find that a ton of open source projects enforce it, while few have .gitattributes files.

So instead of convincing a library to change their ESLint settings, the .gitattributes file (* text eol=lf) absolutely fixes the issue for Windows developers without other changes. For everyone else, it's just pointless.

A common ESLint configuration file errors on prettier/prettier, ala Tailwind: github.com/tailwindlabs/tailwindcs...

{
  "extends": ["prettier"],
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": [
      "error",
      {
        "semi": false,
      }
    ]
  }
Enter fullscreen mode Exit fullscreen mode

If you are using ESLint to enforce Prettier settings, it makes sense. But it will also cause the error. You could fix it by changing the ESLint rule, because it's pointless, but it's easier to add .gitattributes instead, I think.

Thread Thread
 
doctorderek profile image
Dr. Derek Austin ๐Ÿฅณ

To put it another way, you'd never accept a contribution from a Windows contributor using Notepad in the first place, because they can't use Prettier. (OK, they could run Prettier and ESLint manually, but it's just not a realistic development environment.) So since you're already enforcing Prettier to the point of erroring on it, then you might as well force them to download the correct line endings when checking out.

ESLint even recommends .gitattributes over changing the ESLint setting from its default eslint.org/docs/rules/linebreak-st...

Collapse
 
pvaladez profile image
pvaladez

I'm about 2 years late, but Notepad has actually been able to read LF line endings since 2018: devblogs.microsoft.com/commandline... :)

Collapse
 
bam92 profile image
Abel Lifaefi Mbula

I use editorconfig, I'm OK with it.

Collapse
 
vrushank profile image
vrushank

We also thought the same that using editor config should be fine but it does not help while team working on cross platform environment. It is always better to define line endings using .gitattributes file.

Collapse
 
jessekphillips profile image
Jesse Phillips

Git should force all committed files to use lf stop entertaining the idea windows choice has any merit.

Collapse
 
tiguchi profile image
Thomas Werner

Those line ending characters used to be control characters for teletypewriters (TTY). CR (carriage return) would tell the device to move the carriage (or print head or whatever) back to the beginning of the current line. Another LF (line feed) control character was necessary for moving the paper to the next line. It was not really a Windows choice or invention. Windows got it from MS-DOS to stay backwards-compatible and MS-DOS got it from CP/M, an OS from the 1970ies, and overall this is how TTYs worked. They needed CR and LF for doing the right thing.

The makers of Unix on the other hand decided that LF would be enough to tell a device driver to send the correct control sequence for moving to the beginning of the next line.

So in the olden days CRLF was a safer choice to control a teletypewriter.

AFAIK CRLF is still the full control sequence that is internally used by modern consoles and terminal emulators for moving the text cursor on the screen to the beginning of the next line. Hitting the Enter key produces just the CR control character. The terminal software automatically adds an LF to it

Collapse
 
jessekphillips profile image
Jesse Phillips

I realize this, and until recently both were needed for notepad to show new lines.

My point is we don't feed this to tty and when we do it is already worked out because recourse is no constrained.

Collapse
 
deadlybyte profile image
Carl Saunders

Yep, fully agree. I'm a Windows user and always set the eof to lf no matter what.

Collapse
 
jcoelho profile image
Josรฉ Coelho • Edited

I think that for the use case you presented the git core.autocrlf config option is more appropriate.
With this option each developer can work with their native eol character.

However what I like about your option is that you can commit the gitattribute file and force the change for every developers

Collapse
 
andreidascalu profile image
Andrei Dascalu

You're not really forcing it if you need to ask everyone to flush their cache / reset gitattributes.
If you need cooperation, it's better to just ask developers to set their autocrlf setting properly.
Prettier issue aside, it's better to preempt accidental commits of eol changes anyway.

Collapse
 
deadlybyte profile image
Carl Saunders

Thanks for the tip.

Collapse
 
circleofconfusion profile image
Shane Knudsen

Aside from issues with prettier, we get the occasional problem where changing the eol character(s) causes a file to show up in source control as if it's been changed.

Much worse, I used to write a bunch of BASH scripts meant to be run on both Linux and Windows machines (under Cygwin). Every so often, somebody would edit the file on a Windows machine, commit it, and then the script would fail to run on the Linux machines because of the line endings. Me and dos2unix got to be good friends.

Collapse
 
vtvh profile image
Hแบฃi

I love dos2unix too, occasionally do clippaste | dos2unix for Windows clipboard to work correctly in Wsl.

Collapse
 
deadlybyte profile image
Carl Saunders

Yeah, I had this same problem with Linux scripts at my old work place too.

Collapse
 
hisgodlyseed profile image
Lee Hyeon-Soo

.gitattributes in GitHub

.gitattributes is also used to get Github to calculate language statistics and display the correct primary language for a repo.

Check out github.com/github/linguist#using-g...

Collapse
 
thepeoplesbourgeois profile image
Josh • Edited

Seems to me like the linter could worry less about something that's no fault of any developer on the team, and more about ...

๐Ÿค”

Actually, why do we have tools that make our codebases more opinionated about formatting than the languages themselves are? Do we not trust that we โ€“ or our coworkers โ€“ are grown adults, with a basic grasp of readable source? How did linters come to rule the world?

Collapse
 
jastuccio profile image
jastuccio • Edited

How did linters come to rule the world?

Our "grown adult co-workers" used to go to war over things like tabs vs spaces, semicolons in JS, and a lot of other stuff. Prettier came along and made an easy to use tool that said "THESE ARE THE RULES. Now be quiet and get back to actual work" I don't think it was even configurable when it came out (or at least severely limited as to what could be customized)

Collapse
 
thepeoplesbourgeois profile image
Josh • Edited

๐Ÿ˜

What a stupid thing to go to war over in the first place. They've heard of "writing style" and "aesthetic", right?

Thread Thread
 
darrylmelander profile image
Darryl

There were a lot of justifiable reasons these wars happened, and some of them are still valid. Imagine a text editor that interprets a tab as "move to the next column that's a multiple of 8" with no way to configure it to do otherwise. Mix tabs and spaces together and what was nicely lined up for you is completely unreadable to me. Or how about 1 tab = 12 spaces, on an 80 character wide screen? Yeah, that was a thing. These examples aren't an issue any more, but other things are, like code editors that automatically reformat things. If you don't standardize or otherwise keep things in check, you can never tell what actually changed from one commit to the next.

Thread Thread
 
thepeoplesbourgeois profile image
Josh • Edited

Or how about 1 tab = 12 spaces, on an 80 character wide screen? Yeah, that was a thing.

My inkling is that the developer who had that rule was either not using a lot of tabs, using a screen a few more than 80 characters wide, or had some other environmental rationale for why they had adopted what seems, to you and I, an exorbitant amount of spacing for our specific environments. If they were working in a new environment where such spacing was no longer reasonable, or if there was a better standard of spacing in their own environment, I maintain that you (or the colleague who pointed it out to you) found yourself at the crux of a teaching opportunity as opposed to the heart of a war-invoking, crucial difference in the ways different people see the world we share.

I continue to draw countless lessons from the time I spent working at Pivotal, where the Tracker team established the code-formatting rule:

If a pair commits code that's legitimately unreadable, it is a call to reassess our hiring policies, writ large. If it is unfamiliar, but still readable, it is an opportunity to ask and learn why the pair determined the feature necessitated this style for the code. In this case, whether we take the opportunity to learn its motivations or not, if it resolves the ticket and doesn't break integration tests, leave it alone until you have actual work you need to do in that part of the codebase.

(EDIT: My words seem to have reverberated through the collective subconscious [no they didn't] and land in the latest update to Visual Studio Code. In spite of everything else, at least people can say I'm prett yified.)

It might sound crazy to most of the people here, I know, but in short, the way we stopped having endless arguments about code formatting, was to stop having endless arguments about code formatting.

Collapse
 
patrykbernasiewicz profile image
Patryk Bernasiewicz • Edited

We don't use linters at work, so we don't have problems with cross-platform line-ending issues.

Collapse
 
teknorah profile image
Norah Shannon

For those using .editorconfig INSTEAD of .gitattributes, please keep in mind that not all editors support .editorconfig :)

Source: stackoverflow.com/a/47868908/1118446

Collapse
 
angularnodejs profile image
AngularNodeJS ๐Ÿš€

This is pretty good advice. I have been using a combination of editorconfig files with pre-commit hooks to run linting and formatting which enforces 'eol'.

Your solution is more elegant. Reading the github reference on this, it might be better to do it this way, using auto.

# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

*.js    text
*.jsx   text
*.json  text

This way, whatever OS you are no, git will decide the correct 'eol' to apply for you.

Collapse
 
zeorin profile image
Xandor Schiefer

Another great use-case for .gitattributes is to mark certain text files as binary. I do this with lock files and other machine-generated files which should be committed to the repo.

This way, when looking through diffs in the history, the staging area, or even on hosted Git platforms, these files no longer add to the noise.

Collapse
 
_kcbhaskar profile image
Bhaskar

Alternatively we can use editorconfig. editorconfig.org/

Collapse
 
chachan profile image
Cherny

I tried this but it comes with the exception for medium/large companies where devs just don't care too much about that and use any editor they want without built-in or plugin support for editorconfig

Collapse
 
andrewlane profile image
Andrew Lane

Should your

git rm --cached -r
Enter fullscreen mode Exit fullscreen mode

command be this instead?

git rm --cached -r .
Enter fullscreen mode Exit fullscreen mode
Collapse
 
deadlybyte profile image
Carl Saunders

Yep, good spot. I'll change it now.

Collapse
 
roadpepe profile image
roadpepe

If you are lazy and want to quickly add a .gitattributes to your project but don't want to create one from scratch, you could use github.com/alexkaratarakis/gitattr... for a template. It's quick, simple and supports most common languages.

Collapse
 
vfonic profile image
Viktor

What's the difference between CR LF, LF and CR? As far as I know all three do the same these days.
To sum it up:

  1. You don't see the character
  2. The output is the same (file size negligently bigger in case of CRLF)
  3. No added value of using one over the other.

I think this should be ignored in prettier.

Focus on something that actually has a visible effect, don't try to fix something for the sake of OCD satisfaction.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.