zellwk / zellwk.com

Github repo for https://zellwk.com
https://zellwk.com
348 stars 285 forks source link

.gitattributes is not doing anything #17

Closed polarathene closed 2 years ago

polarathene commented 5 years ago

Your .gitattributes file in the repo lists a bunch of asset patterns:

*.png
*.svg
*.jpg
*.webp
*.mp4
*.m4v
*.m4a

This matches the files to those patterns but you've not provided anything actionable to anything matched, the file isn't serving any purpose currently.

What you perhaps meant for these particular files was to indicate that they're binary, which would ensure they're not mistaken by git as text files(which could potentially doing EOL normalization), and not attempt to produce any diffs.

Just add a space followed by binary to each line if that was the intended purpose:

*.png binary
*.svg text -diff

SVG you may want to treat as text since that's what it is, but indicate not to produce any diffs(usually they're worked on in graphical programs or generated, rather than editing code directly). That will allow for EOL normalization at checkin(git add / git commit), and potentially at checkout too. Not likely to cause any problems, but if you want to avoid that, binary can be used.

text is good when you want to ensure a file is treated as text by git, and indicates to normalize to LF line endings when stored in the repo(desirable).

zellwk commented 5 years ago

Thanks @polarathene for this feedback! I'm still not exactly sure what to do with .gitattributes though. Created a pull request (#18) with the fix you recommended. Can you help check through and let me know if its 👍?

polarathene commented 5 years ago

Hey @zellwk , that's ok, I think it's common for developers to have files that they see frequently in other repos and only have a rough idea what they're intended for. Perhaps you can write an article on it to compliment your one on gitignore?

I've spent longer than I'd like to admit getting a proper grasp of the how .gitattributes works :sweat_smile: There's some conflicting information out there as well as many confused users on sites like StackOverflow, particularly when it comes to line endings handling/behaviour when the repo is developed on both Windows and macOS/Linux machines.

There's a bit of history, with the .gitconfig variables core.autocrlf and core.eol(which came later), and .gitattributes config that became available sometime after .gitconfig support had been around a while. .gitattribtues can provide more granular control with similar variables/attributes, but they're not 1:1 equivalents. .gitattributes helps avoid problems that generally happen with collaboration across platforms which use different line endings(CRLF, and LF), however, it gets a bit messy as there are some git clients that popular IDEs used to provide git integration(Eclipse I think was one of them), where these few(but broadly used) git clients ignored any .gitattributes file.

Line endings btw, if you aren't familiar with them are invisible characters your text editor uses to denote where a line ends so text flows onto the next one(CR being carriage return, LF being Line Feed, terms that are from earlier typewriter tech iirc). Some text editors/IDEs can have a settings option(I know Atom does) that can render these invisibles for you if it helps visualize/understand it.

Why does it actually matter? If you commit files on Windows to a git repo and the line endings are CRLF(native to windows), and then someone is on macOS commits to the repo with their OS native line endings(LF), you might notice the diff for the commit affects every single line rather than what was just changed, because every single line had their line endings changed! And this would happen everytime the two developers worked on a file previously committed by the other.

There were some other issues such as on checkout of code to your working directory, the files may convert the line endings(or had been converted from committing too), to a different line ending format(usually the one local to your platform, but it can also be the opposite depending on related git settings). This would break some software from working, some Visual Studio specific config files wouldn't be accepted, and on macOS or Linux, shell scripts would not be happy with CRLF(bat files on windows can sometimes get upset too with LF instead of CRLF). And since the conversion could be stealthy or not visible on file inspection, you could end up very puzzled as to why it's not working(I've been there before :sweat_smile: ). In some cases, a file could have mixed line endings, this would break some software, even if it supported both line endings, it didn't expect a file to have both.

Thankfully, these days it's common for your code editor to support either line ending, and write to whichever you want(in Atom, there is a button that says LF or CRLF at the bottom panel/bar, clicking that will convert line endings). Notepad on Windows was known for not rewriting as CRLF for the longest time, but also supports LF now.

Only other time something may go wrong is in the rare event git mistakes a binary file as text and converts the bytes that represent line endings.


TL;DR: It allows you to tell git to treat certain files a bit differently or provide some hints to avoid issues. Besides line endings, there's other attributes like excluding files from your github releases and another for ignoring files from being considered on your repos language stats(click the colour bar on github repo just above the file list). But mostly, the main benefit is ensuring text files are normalized to LF line endings when stored in the repo, and ensuring certain files that need to be a specific line ending are converted to such on checkout(I think they must be LF in the repo to support that).

polarathene commented 5 years ago

Here's an example of a more fleshed out .gitattributes file I made for a project, with some of what I talked about explained at the bottom of the file:

# Normalize all non-binary files line endings to LF upon `git add`/`git commit.`
* text=auto

## SOURCE CODE
*.js               text

## CONFIG
.gitattributes     text export-ignore
.gitignore         text export-ignore
.editorconfig      text
.eslintrc          text
.stylelintrc       text
.babelrc           text
.env               text
*.lock             text -diff
*.json             text
*.yaml             text

## DOCUMENTATION
*.md               text
LICENSE            text

## DOCKER
.dockerignore      text
Dockerfile         text

## OS/EOL Specific
*.bat              text eol=crlf
*.sh               text eol=lf

## Assets - Diffs are less meaningful, so ignore them.
*.svg              text -diff

## FONTS
*.ttf              binary
*.eot              binary
*.otf              binary
*.woff             binary
*.woff2            binary

## GRAPHICS
*.pdf              binary
*.png              binary
*.gif              binary
*.jpg              binary
*.jpeg             binary
*.webp             binary
*.ico              binary

## VIDEO
*.webm             binary

################################################################################
## INFO
################################################################################

### WHAT IS THIS FILE?
# This file when recognized by a git client, will help enforce consistency
# across multiple environments/systems in regards to line endings(CRLF & LF).
# Documentation - `.gitattributes`: https://git-scm.com/docs/gitattributes

# It provides fine-grained control in comparison to the `core.autocrlf` and
# `core.eol` git settings that may vary per system, while the `.gitattributes`
# file has a higher priority than `.gitconfig` and travels with the repository.
# Documentation - `.gitconfig`: https://git-scm.com/docs/git-config

### WHY SHOULD I CARE?
# The desired result is to ensure the repo contains normalized LF line endings,
# notably avoiding unhelpful noise in diffs or issues incurred from mixed line
# endings. Storing as LF ensures no surprises for line endings during checkout.
# Additionally for checkout to the local working directory, line endings can be
# forced to CRLF or LF per file where appropriate, which ensures the files have
# compatible line endings where software expects a specific kind.

### ATTRIBUTES
# `text` normalizes the file(s) line endings to LF upon add/commit. (CRLF -> LF)
# `text=auto` sets `text` if Git decides the matched file is not binary data.

# `eol` enforces a line ending for a file when writing to the working directory.
# `core.autocrlf` when set to `true` or `input` overrides the `core.eol` value.
# `core.eol` is used for any files not explicitly set with an `eol` attr value.
# `core.eol` uses the native line endings for your platform by default.

# `binary` is an alias for `-text -diff`. The file won't be normalized(-text).
# `-diff` indicates not to show a diff. Useful when diffs are not likely to be
# meaningful such as generated content (SVG, Source Maps, Lockfiles).

# `export-ignore` excludes matched files and directories during `git archive`,
# which services like Github use to create releases of a project with.

Similar to .gitignore really :)

zellwk commented 2 years ago

Sorry for the LONG wait on this. I realized I haven't had the incentive to look further into this and understand it, so I'll close this issue for now.

Thanks for all the help!

polarathene commented 2 years ago

I haven't had the incentive to look further into this and understand it

2nd sentence of report:

  • You've not provided anything actionable to anything matched
  • The file isn't serving any purpose currently.

Just delete the file if you don't have any use for it... or leave it if you don't care either way :man_shrugging:

zellwk commented 2 years ago

Perfect. Thank you.