Two Git ignore files nobody told me about

(mihai.dinculescu.dev)

87 points | by faithraven 16 hours ago ago

69 comments

  • ktm5j 13 hours ago ago

    Just a nit-pick, but some/repo/path/.gitignore isn't necessarily committed to the repo. For example, if your repo has no .gitignore file, you can totally add one in your clone without adding it to the tree. Of course then you can't do something like `git add .` without committing it.

    Also `~/.gitignore` works as a global gitignore. I usually stick something like `katie*` in there so I can copy some `script.sh` to `katie_script.sh` and then I can make changes that I don't want to commit.

    Quick edit: I'm not sure `~/.gitignore` works out of the box.. looks like I stuck that in my `~/.gitconfig` for excludesfile

    • crtasm 13 hours ago ago

      Out of the box you can use ~/.config/git/ignore and ~/.config/git/config

      • ktm5j 13 hours ago ago

        I have no ~/.config/git directory, ~/.config/git/config might take higher precedence, but ~/.gitconfig works too.

        • crtasm 13 hours ago ago

          Yes you may have to create the directory :)

    • nom 13 hours ago ago

      you can add .gitignore to .gitignore ;)

      • ktm5j 13 hours ago ago

        True! But a gotcha there is that if your repo does have a .gitignore in the tree then this trick won't work. I had a coworker try to do just that and we were all pretty confused when his changes kept getting committed. `git add ./` will stage changes to any file in the commit tree, even if that file matches a line in gitignore.

      • 11 hours ago ago
        [deleted]
      • spider-mario 12 hours ago ago

        In fact tup does exactly that to the .gitignores it generates.

      • sinabis 10 hours ago ago

        yes, that works perfectly

    • infogulch 13 hours ago ago

      I've been using $REPO/.scratch/ and .scratch/.gitignore with just `*` in it as a place for coding agents to use as temp storage (scripts, exports, plans, etc) that won't get committed. It's much easier to access these files under the repo path instead of wading through /tmp.

    • 13 hours ago ago
      [deleted]
    • moritzwarhier 10 hours ago ago

      Wait until you learn about

        .git/exclude
        --assume-unchanged
        --no-update-index
      
      .

      And fwiw, I think global/home-dir .gitignore is bad, for everything except of OS-level spam like .DS-Store

      • happymellon 8 hours ago ago

        Nah, I generate dependency trees from gradle because of the crappy way current $job has aggressive transient dependency scanning and I can't stand just updating someone else's transient dependency without validating that there isn't at least a new version of whatever pulled it in.

        I have dependency_tree globally excluded because it is my unique naming convention. Actually it might just be my unique approach because other people don't seem to mind having 1000 overrides for libraries they don't use.

        • moritzwarhier 7 hours ago ago

          Fair, and sorry, my tone was a bit off, I didn't think much when commenting.

          My preference of not having much in my global gitignore is only sensible for my particular daily work, if you need to partially track build folders in projects and can't control the ignore files automatically, a global ignore might make sense.

        • 7 hours ago ago
          [deleted]
  • 6LLvveMx2koXfwn 14 hours ago ago

    This is great, and nicely written up in the context of agentic repos etc, but presumably no-one reads the official docs, right: https://git-scm.com/docs/gitignore where the multiple ways of ignoring files are clearly stated?

    • faithraven 14 hours ago ago

      Until Claude suggested .git/info/exclude, it never crossed my mind to question how ignoring worked. A search would have answered it in seconds, but you have to think to ask first. I didn't, and I suspect most people don't either. Especially with git, which nearly everyone learns by doing; very few of us ever sit down and learn it properly. That's why I wrote it up: so a few more people can learn this the way we learn everything else in git, by accident.

      Now that you mention it, I should add a link to those docs in the article. Thanks!

      • onaclov2000 13 hours ago ago

        This is true, using AI to help discover better ways of working with stuff is pretty epic, reading docs are about as exciting as writing docs, esp when you are trying to get something done.

        • gritzko 12 hours ago ago

          The motivation fades to make things intuitive.

    • alexpotato 14 hours ago ago

      There is a tweet doing numbers on Twitter right now which is effectively:

      "Do the reading b/c you would be amazed how many people don't do the reading"

      • bigfishrunning 14 hours ago ago

        So many people treat git commands like magic words, and then are terrified when they mess up their repo (example in this xkcd... https://xkcd.com/1597/)

        Reading documentation is a superpower

        • faithraven 14 hours ago ago

          I'd wager a small sum that git is the tool most of us learned by accident, some of them fortunate, some less so. Thankfully, this one was the former.

          • 1718627440 11 hours ago ago

            Yeah, but Git is a tool, that in the face of an accident shoves you it's manual in the face.

        • coldpie 12 hours ago ago

          I'm definitely the friend in the alt-text of this comic. What do you mean you haven't read gitcore-tutorial(7)??

      • windward 12 hours ago ago

        Do the reading b/c there's a machine that has done all the reading so it's hard to add value if you maintain the anti-intellectualism of 2010s software dev.

    • BeetleB 12 hours ago ago

      For a lot of tools, people usually read the docs once, and obscure stuff is quickly forgotten.

    • stephbook 14 hours ago ago

      I have never seen these two files in any git repository I've cloned so far.

      • fortran77 13 hours ago ago

        That’s because, unlike .gitignore, they are not committed.

  • BerislavLopac 7 hours ago ago

    > editor clutter has no business in any project's .gitignore, and yet there it is, in most of them

    I couldn't agree more with this - except that, in practice, nobody bothers to add their own environment clutter to their own global (or even project-related) gitignore. So invariably we end up with PRs (and even main :scream:) peppered with various .vscode and similar lost souls.

  • BerislavLopac 7 hours ago ago

    I can't believe that this article is still alive and well on the interwebz: MacGyver vs James Bond - https://importantshock.wordpress.com/2008/08/07/git-vs-mercu...

  • BigTTYGothGF 12 hours ago ago

    > but pushing the silly filename I picked for my private notes to a remote repository feels unclean

    Pick a directory for them and ignore the directory. Other team members who want to keep their own notes can use that directory as well.

  • psygn89 14 hours ago ago

    This is great... one thing I wish is to be able to exclude are lines, for instance some lines in my config that only benefits the work I do. Some configs don't allow extending and that's where this would come in handy. Anyone have any tricks for that?

    • faithraven 13 hours ago ago

      You might be surprised, it's sort of possible. Ask your favourite AI agent about git clean filters, and .git/info/attributes, the per-clone sibling of .git/info/exclude. The docs are here: https://git-scm.com/docs/gitattributes#_filter

    • jo-m 13 hours ago ago

      You can from the checked in config file include a local file which is not checked in (only if it exists).

      For example, with direnv, the `.envrc` in my projects usually has

          source_env_if_exists .envrc.local
      
      And the repo also ships with a `.envrc.local.example` file.
      • BeetleB 12 hours ago ago

        You missed this:

        > Some configs don't allow extending

  • 14 hours ago ago
    [deleted]
  • TrianguloY 11 hours ago ago

    I learned this while using IntelliJ, because it suggests both options. I searched for the difference and, once understood, I was able to use the knowledge everywhere.

    The other useful advice is when there is a full folder you want to ignore. Putting a .gitignore with a single "*" ignores the full folder...including the gitignore file itself.

    I do use it when I quickly need to ignore the .idea folder

  • teekert 11 hours ago ago

    Oh this is nice. I've fallen into the habit of ignoring /devtools and put any input for agents there,I mount it in the agent container and have it put it's auth and memory there, and plans. And a "start agent container"-script, because people have their own preferences when it comes to agents.

  • havnagiggle 12 hours ago ago

    I prefer a presubmit check for DO NOT SUBMIT and also disable Git smart commits. And then I have those floating around as needed. Seems to avoid all the foot guns I'm reading about, and makes it obvious and easy for other people to use as well. I guess it still shows in my diff tree, but /shrug I still prefer seeing them.

    • etatester 12 hours ago ago

      What footguns? I disable most git hooks so your solution still has ways to shoot your feet.

      • havnagiggle 12 hours ago ago

        Mostly the spooky action at a distance. Gitignore expressions and inheritance of the ignore expressions can exclude files you actually need to include, and you basically lose sight of those -- admittedly those are probably safer bugs than including things that shouldn't be included. But if a file (or even specific lines) shouldn't be included, I would prefer the file/lines have a marker that says it shouldn't be included.

        I run the same presubmits on pre-receive and merge requests, so you wouldn't get too far shooting your own foot. But yeah, if you're not using the feature then it wouldn't save you so it's not foolproof. I also run tools for scanning for credentials, etc.

  • dpkirchner 13 hours ago ago

    See also: git check-ignore

    You can use this subcommand to learn which ignore file is causing your files to be ignored.

    https://git-scm.com/docs/git-check-ignore

    • faithraven 13 hours ago ago

      That's a great shout. With more than one ignore file in play, this command is gold.

  • henrydoughty 13 hours ago ago

    On Windows I never found ~/.config/git/ignore. I just used .gitignore for everything.

    I've been leaving notes sitting untracked rather than put a filename only I use into the repo. .git/info/exclude is what I actually needed.

  • markbnj 13 hours ago ago

    Very useful. Minor typo in the post if you're adding the claude code flag: it's "respectGitIgnore" not "respectGitignore". [probably not true, see below]

    • faithraven 12 hours ago ago

      Thanks, but I think it's the other way round. The docs, the published JSON schema and the binary itself all spell it respectGitignore, lowercase i, named after the .gitignore file. https://code.claude.com/docs/en/settings-reference#respectgi...

      • markbnj 12 hours ago ago

        When I first added it as "respectGitignore" it had no effect and my ignored folder did not show in the @ list. I changed it to "respectGitIgnore" and saved settings.json and the folder did show in the @ list. Then, after a claude restart, the folder stopped showing up. I edited and saved settings.json (but maintained the spelling "respectGitIgnore" and the folder started showing up again. Then after a coding session it stopped showing up, and changing the case of the 'i' and saving hasn't restored the behavior I want... so it just seems flaky at this point.

      • gritzko 12 hours ago ago

        The git-ness of this argument exceeds 100%.

  • biglyburrito 14 hours ago ago

    I'd never heard of .git/info/exclude, core.excludesFile, or ~/.config/git/ignore before. Thanks for posting this!

  • grimgrin 13 hours ago ago

    this was probably discovered by many when seeking how to globally ignore agent configs, until perhaps they decided they'd like to start committing agent configs. though that's just a `git add -f`

  • n4bz0r 12 hours ago ago

    I absolutely despise when people commit their personal ignore patterns. My opinion is that the code in the repository shouldn't know anything about personal environments. The exception is when the entire team benefits from having their common ignore patterns in the repo - in this scenario, the environment details are no longer personal and it doesn't make much sense to not commit them. In any other situation, people are perfectly capable of ignoring their crap on their own and shouldn't pollute the repo. Glad .git/info/exclude is getting more exposure.

    • BeetleB 12 hours ago ago

      > I absolutely despise when people commit their personal ignore patterns.

      Beyond things not being neatly compartmentalized, what is the problem? The only risk I see is that you'll have a file you forgot to commit because it happened to match one of those patterns.

      Having strong opinions on stuff like this is not healthy.

    • OutOfHere 9 hours ago ago

      It depends on whether the pattern is general enough to potentially be useful for others. If it is, then by all means add it to .gitignore. If on the other hand it's specific to the user, e.g. '2026_report.docx', then no, it should not be added.

  • festive-minsky 16 hours ago ago

    Thanks I had no idea about these either!

  • tonymet 12 hours ago ago

    Does anyone have a trick to blacklist files by type e.g. object / binary code, gz files. Often objects & commands lack extensions so going by extension doesn’t work. Git seems to guess binary pretty well upon diff, how to tap into that.

    I’ve used pre-commit hooks for this but I’d rather a simple config flag, it seems trivial.

  • DamonHD 16 hours ago ago

    Ah, very good!

  • globular-toast 13 hours ago ago

    Magit really is the only git frontend worth using. It exposes all of this kind of stuff in an easy to use way. You can easily ignore files using all three methods with magit.

    The more useful thing here is the "typical use" of each one. People who don't know about other methods get this wrong a lot and put cruft from their own tools/editors in .gitignore which is annoying.

  • ivyBadger920 14 hours ago ago

    [dead]

  • cxr 13 hours ago ago

    I've never seen a .gitignore that was justified, ever. It probably shouldn't even exist. I've run into projects often enough with horked build scripts or bad docs about build pre-requisites, where upon failing partway through and necessitating some fix, the build failure leaves the tree in a state where it still won't build successfully even after fixing the thing that caused the original failure. The only fast fix is to rm .gitignore, then look at the output of git-status and rm -rf all the crap that it shows the original build attempt splattered everywhere before re-running the build script for a third attempt. Thanks, .gitignore.

    .gitignore is banished in every project I'm in charge of. Everyone is required to manage their personal .git/info/exclude themselves, and any changeset attempting to slip .gitignore into the project will get ipso facto rejected. (Anyone is free to submit a change that adds a file contrib/gitignore if you think you have a set of useful globs relevant to the project that will be a help to others, along with instructions to cp that file to .git/info/exclude, but .gitignore is not making it in.)

    Git needs to ship a git-ignore command (or extend git-config) that exclusively works by managing .git/info/exclude for you, including converting "legacy" .gitignore into the less anti-social version.

    • athorax 13 hours ago ago

      This is one of the strangest opinions I've seen in awhile. Your complaint seems like it should be pointed at projects not having a working "clean" make target.

      Also:

        git status --ignored
        git clean -ndX # preview what would be removed
        git clean -fdX # actually delete the files (warning: destructive)
      • 4 hours ago ago
        [deleted]
    • quietbritishjim 13 hours ago ago

      Or, you could have a build system that does a 100% out-of-tree build into ./build, and then if the build is broken you delete that one directory. You hardly need git to help you with that.

      • cxr 13 hours ago ago

        Oh, I can? Cool advice! How do I get the people with bad hygiene that we're talking about to follow it?

        (You have lost the plot; your response amounts to explaining how soap and water works to someone who has just described their office mate's tendency not to shower.)

        • quietbritishjim 12 hours ago ago

          Get a new job? You can't be that "in charge of" a repo if you can't enforce rules this basic. In fact, I don't understand how you can enforce something as (being polite) unusual as banning .gitignore and yet can't enforce build system hygiene.

          • cxr 4 hours ago ago

            Believe it or not, there are people whose interactions with software are not limited to projects that they wrote and have control over.

        • 12 hours ago ago
          [deleted]
    • Phemist 13 hours ago ago

      So all your fellow devs do `ln -s contrib/gitignore ./git/info/exclude`?

      Also you can do `git status --ignored` and it will list all files changed, even if ignored. If that is really your main issue.

      • cxr 4 hours ago ago

        > So all your fellow devs do `ln -s contrib/gitignore ./git/info/exclude`?

        I don't know you think that will do or how symlinks work, but it won't lead to anything relevant to this discussion. (To answer your question: no.)

    • Supermancho 11 hours ago ago

      I would not recommend this setup, which is effectively using a more complicated and error prone system. That being said, I could handle it.