logoalt Hacker News

.gitignore Isn't the only way to ignore files in Git

536 pointsby FergusArgyllyesterday at 10:29 AM161 commentsview on HN

Comments

hungryhobbityesterday at 7:59 PM

Fun article, but it leaves out my favorite "almost ignore" feature in Git: `.gitattributes`.

This file lets you specify that git should "ignore" the diff from certain files. For instance, Node projects have a `package-lock.json` that is pure noise from a Git standpoint (it's just massive amounts of diff specifying specific versions of libraries, and the real human-readable version is in a separate `package.json` file).

With `.gitattributes` in the root of your project, you can just add a line:

`package-lock.json -diff`

Now, that file will still get staged/committed (which you want) ... but when you `git diff` you won't see the massive amounts of pointless diff in that file.

show 7 replies
rmunntoday at 9:32 AM

I have a habit of writing myself notes in various .txt files, and then not cleaning them up often enough so they end up cluttering my `git status` view. I ended up with a solution not mentioned in the article: create a `scratch` directory, and a `scratch/.gitignore` file containing just one line: `*`. This makes Git ignore everything in the scratch directory, including that same .gitignore file — so I never accidentally check it into Git, and don't end up pushing my personal .gitignore settings onto my coworkers.

Of course, I could have used .git/info/exclude for that, and not risked accidentally adding my `scratch` directory with `git add -A` or something. So I (re-)learned something (which I'd known about but forgotten) today.

But as a reminder to anyone else who had forgotten this: .gitignore files are processed throughout the repo, not just at the top level. You can sprinkle them throughout the repo structure for finer-grained control, which may come in handy in some circumstances.

kevincoxyesterday at 4:02 PM

The global/user wide exclude is a feature that should be more widely known. I frequently have people submitting changes to add their IDE/OS/AI/... files to every project's .gitignore. They are almost always pleasantly surprised when I tell them that they can add them to their standard configuration and have them ignored everywhere without bothering every project and without risk of accidentally committing them on a project where they haven't updated the .gitignore yet.

My general rule is that in-repo .gitignore should only be used for repo-specific things (build outputs, dependency folders, ...) and most user tools should be in their own user config.

show 6 replies
hk1337yesterday at 2:30 PM

~/.config/git/ignore and ~/.config/git/config is the proper place for your global git config and ignore instead of creating a ~/.gitignore_global and changing the config. IMO.

my dotfiles are a lot smaller at the root level taking advantage of the ~/.config/ for a lot more things.

the git exclude isn't used as much because it doesn't get committed to the repository so you'd have to recreate it each time you wanted to use it. that doesn't mean they're bad just why they are not used.

show 2 replies
judofyryesterday at 2:34 PM

Not sure where I picked up this, but I’ve added this to my global Git ignore:

    attic
That way you can just create an attic directory in any project where you can keep random stuff that should never be committed. I’ve yet to find a repo which actually has such a directory checker in.
show 4 replies
dofmyesterday at 4:46 PM

Re: per-user ignores:

> For example, if you’re on macOS, adding .DS_Store here would be ideal.

As long as every Mac user on your project does. If you have more than one, it may be better off taken out of everyone's hands.

show 2 replies
wpollockyesterday at 3:36 PM

One point of clarification: with git, "global" means per-user, not "machine-wide. (I never understood why "--global" wasn't better named, maybe "--user".) That's why these pathnames are in a user's home (the "~" means the current user's home directory).

Machine-wide configuration is called "system" in git, and generally lives under "/etc".

bryancoxwellyesterday at 2:07 PM

I use the ever living hell out of .git/info/exclude. Works great for scripts/Makefiles I only want locally and collaborators wouldn’t care about or be able to use.

show 2 replies
rlpbtoday at 11:50 AM

Placing various artifacts (eg. build artifacts) inside the source tree always seemed like a historical mistake to me. It leads to various accidents such as people checking in their credentials and accidentally bundling such files in source distributions, for example. These consequences are real.

Debian build tooling places build artifacts in the parent directory on the assumption that this is acceptable, but it then surprises people since it's not the norm anywhere else.

Perhaps this ship has sailed. But I think it's worth pointing out that if you have an option, don't design things that place things inside the source tree if you can avoid it.

elyoboyesterday at 10:19 PM

Relatedly, some aliases I have in place.

  assume = update-index --assume-unchanged
  unassume = update-index --no-assume-unchanged
  assumed = "!git ls-files -v | grep ^h | cut -c 3-"
  unassumeall = "!git assumed | xargs git update-index --no-assume-unchanged"
  assumeall = "!git st -s | awk {'print $2'} | xargs git assume"
lmf4lolyesterday at 7:31 PM

Wow! How did I not know this? I am a professional software dev for 20 years… and only ever used .gitignore !

I just realized that I never even „asked“ myself if there might exist a better way than to clutter .gitignore with all kinds of specific excluded only relevant to me. I just accepted the world as it appeared to me…

And Today, it got s little bit better :-)

stevagetoday at 7:59 AM

Wow, how did I not know about the exclude file? I've had this need so many times - working on a shared repo where I want to ignore some files locally.

leleatyesterday at 10:03 PM

There is also

  git update-index --[no]-skip-worktree
for files that are already tracked. This can be useful for some local experimentation... it's just a bit annoying to use because it's not really surfaced anywhere by git (kinda). You need to remember that you set it; otherwise other operations like checkouts may be blocked.
show 1 reply
Hendriktoyesterday at 1:55 PM

This is just a very low-effort regurgitation of this: https://git-scm.com/docs/gitignore

show 3 replies
supermdguytoday at 1:24 AM

One trick I’ve used is creating a folder and then adding a .gitignore inside it with *. Then nothing in that folder gets tracked, without needing to add anything to the public gitignore. Didn’t know about .git/config though!

show 1 reply
jeremyscanvicyesterday at 3:07 PM

I knew about .git/info/exclude and ~/.config/git/ignore but not about git-check-ignore(1). Neat!

adamgordonbelltoday at 3:57 AM

    you may have a personal notes.txt file in a repository that you don’t want to check into git but you also don’t want to add to .gitignore because it’s unique to your workflow. 

    The exclude file lives in the .git directory of every Git repository but changes to it are not checked into Git
Wtf. I've always wanted this, and it was right there.
show 1 reply
h4kunamatatoday at 2:53 AM

>~/.config/git/ignore

This never be considered as a solution. It only works on that PC, when working with a team, this approach is wrong in so many levels.

I host my own Forgejo server/repos, it is just me but .gitignore just makes more sense. It is on the root of the project, and I only have one file to manage. No matter that PC/device I am using, they are automatically covered.

show 2 replies
maxlintoday at 4:00 PM

My first and hopefully only clash with the global ignore file was debugging why a project worked differently between machines. There was a global ignore on the machine I was working on (that I didn't place) that "smartly" tried to exclude "irrelevant" code / project files regardless of project.

I see version control somewhat similarly as I see traffic laws. Sure, they could work in entirely different ways, Germans like their autobahns, but breaks to the norm in an otherwise planar field are rarely arguable for.

ramijamestoday at 12:52 PM

I love these types of threads the most. I learn so much.

andrelaszloyesterday at 10:49 PM

Here's how I use the excludes file to set a different config for a project directory containing multiple repos:

https://laszlo.nu/blog/project-level-git-config.html

show 1 reply
nonoesptoday at 6:59 AM

git update-index --assume-unchanged path/to/file

https://git-scm.com/docs/git-update-index

codensoldertoday at 3:01 PM

something new i learned today, thanks!

dalton_zktoday at 1:56 AM

Nice, I didn't know the other options besides .gitignore

hmokiguessyesterday at 6:53 PM

git is so incredible, it never ceases to amaze me, what a timeless piece of software

bitvvipyesterday at 2:52 PM

I still like using gitignore very much

globular-toastyesterday at 3:41 PM

Magit has good support for these other methods. You press <i> and then select if you want the ignore to be shared (.gitignore) or private (.git/info/exclude).

show 1 reply
antisoltoday at 12:59 AM

Point of pedantry:

  > The ignore file lives in your machine’s home directory in ~/.config/git/ignore. Whatever filenames are added to this file are ignored globally at a machine-level.
The wording here is slightly wrong: ~/.config/git/ignore will ignore files per-user on the machine, not "at a machine level". And it's not "your machine's home directory", it's your user's home directory on that machine. Any other users on the same machine will not see this. Git calls this "global", as in "global for the user".

Git config does also have a --system option which modifies the system-level config file, /etc/gitignore. You could probably ignore stuff at the system/machine level (hint: you don't want to), with this. I'd do something like:

  $ sudo git config --system core.excludesFile /etc/gitignore
  $ sudo touch /etc/gitignore
Note however that user config will override this, so any user who has a core.excludesFile setting will not also look at your system level excludes file. Which is a pretty big caveat.
tonymetyesterday at 5:13 PM

these are great for ignoring files by name, but you often want to ignore binary files or other files by type.

Set a global hooks dir, and then block binary files in pre-commit by using file or checking the git index

   git config --global core.hooksPath ~/.config/git/hooks
Or block large changes, because binary mods are often larger than a real diff.
yieldcrvtoday at 2:11 AM

but dont forget dockerignore if you use docker

PunchyHamsteryesterday at 6:10 PM

another useful snippet

    [includeIf "hasconfig:remote.*.url:[email protected]:*/**"]
    path = /home/dir/per/company/config
allows for remote specific configs, overriding say email or other required options depending on where you send contributions - without having to have per repo config

works for dir too

    [includeIf "gitdir:/home/user/src/work1/"]
Git is REAL bitch about exact syntax here; the first snippet won't work with just :*, it needs :/* ; the second won't work without trailing slash
shinobi-appstoday at 2:28 PM

[flagged]

arikrahmanyesterday at 10:47 PM

[dead]

codymiscyesterday at 9:58 PM

[flagged]

uptownyesterday at 3:54 PM

Not really news. I worked with dozens of developers who have managed to ignore files in Git.

barbazooyesterday at 3:16 PM

Exclude sounds like a recipe for sadness.