3

Another developer committed his local version of the .gitignore file. I want to modify that file locally without being nagged about it: no showing up on "git status", no "overwritten by checkout" errors.

The often-recommended solution seems to be "git update-index --assume-unchanged .gitignore"

This does not work.

It will indeed prevent the file from showing up in "git status", but it will trigger an error when changing branches:

error: Your local changes to the following files would be overwritten by checkout: .gitignore

More non-solutions:

  • "Add .gitignore to .gitignore" => does nothing.
  • "Add .gitignore to .git/info/exclude" => does nothing.
  • "git rm --cached .gitignore" => .gitignore shows up on git status.

Other non-useful threads:

  • http://stackoverflow.com/questions/767147/how-do-i-tell-git-to-ignore-gitignore
  • http://stackoverflow.com/questions/10750351/git-hub-gitignore-error

So, my question, can this actually be done?
Thanks for your time.

EDIT

From Shahbaz', Chris' and jthill's helpful comments, I conclude that the answer to my question is "No". It looks like there is no built-in mechanism in git to completely ignore a tracked file locally. Fortunately, there are several workarounds that are situationally useful.

Thanks for the answers, guys.

  • 1
    A partial solution is to add local rules in .git/info/exclude. Obviously that doesn't help if you want to REMOVE rules from .gitignore –  May 08 '14 at 16:04
  • If you are tracking `.gitignore`, you could tell git not to _show_ its changes, but it doesn't mean there are no changes. If you switch branch while `.gitignore` is modified, you will lose your changes. Is that what you want? If that's not what you want, go ahead and merge your changes with your colleague's, and commit it. If you don't want to share .gitignore with your colleague, do `git rm --cached .gitignore` as you have mentioned, and _then commit it_ to set it in stone. – Shahbaz May 08 '14 at 16:06
  • 1
    In general, the `.gitignore` file should contain ignores that are applicable to everybody using the codebase. If the committed `.gitignore` is not doing this, consider changing it to remove the non-global ignores and encourage users to use `.git/info/exclude` for their personal ignores. – ChrisGPT was on strike May 08 '14 at 16:07
  • If you're interested I have a short-ish but rather brutal hack that can handle simple situations like this well. It hijacks git's sparse checkout feature, installs a post-checkout hook and adds a command, it's pretty much linux-only (needs good hardlinks and recent GNU). – jthill May 09 '14 at 02:33
  • Thanks for the offer, but right now I'm satified with the existing workarounds. Also, I'd rather play it safe with my source control :-) –  May 09 '14 at 15:23

2 Answers2

0

tl;dr on this answer on how to set up a content filter that will not alter existing content either in the worktree or in the repository:

git config filter.pinned-content.clean  'git show HEAD:%f 2>&- || cat'
git config filter.pinned-content.smudge 'cat %f 2>&- || cat'
mkdir -p .git/info
echo .gitignore filter=pinned-content >>.git/info/attributes

Filters are documented in the .gitattributes manpage, the idea is the 'clean' commands are fed content going into the repo and the 'smudge' commands are fed content coming out of the repo; the filter pair above substitutes whatever content has already been committed for whatever you're trying to add, and whatever you've got now for whatever checkout would try to replace it with.

If the checked-out file has not been changed (is identical to the committed version), and you switch to a branch that has deleted that file (or never had it), git will also delete it from the worktree. You can get the content back by

git show @{1}:path/to/file > path/to/file    # or git show oldbranch:etcetera

If the file is different from the committed version, git will refuse the checkout.

Community
  • 1
  • 1
jthill
  • 55,082
  • 5
  • 77
  • 137
  • You meant echo .gitignore instead of .gitconfig. Close but no cookie. The .gitgnore file got deleted when I switched branches. –  May 08 '14 at 15:41
  • Fixed the typo, thanks. If you switched from a branch that has a tracked `.gitignore` to a branch without a tracked `.gitignore`, what else could git sanely do? – jthill May 08 '14 at 15:47
  • Ignore it completely. Leave it there, just like if it was a file outside the repository. –  May 08 '14 at 15:49
  • Okay, I can see that as a weakness in git. Once a file's tracked, it's rather tenacious about tracking it, arguably, in this circumstance, to a fault. – jthill May 08 '14 at 16:06
  • Thanks for the tic - what prompted you to accept it despite the arguably dangerous misfeature, have you found a workaround for that? – jthill May 08 '14 at 16:29
  • 1
    I didn't find a workaround, but I accept your second comment. Since I can't accept comments, I accepted the answer containing the comment. Sorry, I just seem to be running into UI issues today. –  May 08 '14 at 17:06
-1

You can create a global git ignore

https://help.github.com/articles/ignoring-files#create-a-global-gitignore

Another option would be to modify the local gitignore and remove it from local tracking:

git update-index --assume-unchanged .gitignore

Not sure that will work if the file changes from upstream.

Ian Laird
  • 442
  • 3
  • 9
  • I didn't downvote, but that doesn't answer my question. I want local changes, not global changes (I use more than one repository). –  May 08 '14 at 15:30
  • I did. gitignore has no effect on tracked files, it's a convenience for keeping build products and other fluff off status reports. – jthill May 08 '14 at 15:33
  • I specifically stated that "git update-index --assume-unchanged .gitignore" does not work in my question. –  May 08 '14 at 15:43
  • This is what i do. And it works fine even when changing branches. If it doesn't work for you i am sorry but this is the suggested method from github's website. Good luck, sorry i couldn't help. – Ian Laird May 08 '14 at 15:45
  • 2
    It's probably because one branch has the committed .gitignore file and the other doesn't. Probably people don't notice that this solution doesn't always work because all their branches have long included the .gitignore file. –  May 08 '14 at 15:47