16

I need to ignore any changes done to a particular files that are already tracked by Git. Those files should not be removed from either local or remote repository.

I tried to ignore them in .gitignore, but it does not work.

.gitignore:

$MAVEN_PATH_TO_CHILD_MODULE/src/main/java/$PACKAGE/$CLASS.java

Any idea why?

Crazyjavahacking
  • 9,343
  • 2
  • 31
  • 40
  • 1
    Watch out for 'assume unchanged'. Review http://stackoverflow.com/questions/13630849/git-difference-between-assume-unchanged-and-skip-worktree and understand the differences between "assume unchanged" vs "skip worktree". Then see which better appiles for your use case. – Dave Feb 13 '15 at 14:34
  • OP wants to keep the committed files but ignore further changes to them. The flagged duplicate is not - this is a subtly different question. And the duplicate flagged on the duplicate is so far away from this as to be irrelevant. – Ed Randall Aug 09 '22 at 07:43

3 Answers3

22

Only untracked files (not added to Git) can be ignored. Or in other words ignoring is about files which are not known to Git, i.e. are not in the index (have no entry in the staging area).

To make a file untracked (removing it from the index, and thus staging it from deletion in the next commit), but keep it in the working area i.e. in the filesystem, you can use

$ git rm --cached <file>

The file will be removed from remote repository (from the tree of top commit - it will be still present in history) after local commit, and after push to remote.


NOTE: this is unsafe and can lead to data loss!!! For safer (though not perfect) alternative, see below.

If you want for Git to ignore changes so that git diff and git status would not report them, and git commit -a would not commit them (but git add <file> + git commit and git commit <file> would still add them), you can lie to Git with this trick (see git ready » temporarily ignoring files article):

$ git update-index --assume-unchanged <file>

The git update-index command is low-level (plumbing) command. You can find which files are "assumed unchanged" with:

$ git ls-files -v
h <file>

git ls-files -v uses lowercase letters for denoting status files that are marked as assume unchanged.

You can turn it off with

$ git update-index --no-assume-unchanged <file>

Note that this option original purpose is speeding up status on platforms where stat is slow.


Following @Dave comment, and referenced Git - Difference Between 'assume-unchanged' and 'skip-worktree' question, another option in modern enough Git is making Git do not use working area version with skip-worktree bit.

You can turn it on for a tracked file with

$ git update-index --skip-worktree <file>

This makes Git use the index version (the last committed version) in place of the version from the filesystem. You can check which files have this bit set with

$ git ls-files -v
S <file>

The git ls-files -v command will use S to denote files with "skip-worktree" set.

Note that this option original purpose is support for sparse checkout.

Jakub Narębski
  • 309,089
  • 65
  • 217
  • 230
  • 3
    _Those files should not be removed from either local or remote repository._ This part of the question makes a lot of this answer redundant. – Tom Fenech Feb 13 '15 at 10:55
  • Are options like --assume-unchanged or --skip-worktree also persisted to the remote, so that they will have the same effect for anyone else checking out the repository? – SFG Dec 23 '20 at 13:03
  • 1
    @SFG no those flags / options are purely local – Jakub Narębski Dec 24 '20 at 14:10
  • `git rm --cached` seems completely wrong - it creates a "delete" commit, which is explicitly *not* what the OP wanted. – Ed Randall Aug 09 '22 at 07:51
10

The .gitignore just tells git which untracked files to ignore, so it won't do anything if your file is already tracked by git. Instead you can tell git to temporarily ignore any changes to a tracked file using this command:

git update-index --assume-unchanged <file>

And if you ever want to undo this, just run:

git update-index --no-assume-unchanged <file>

See here for more details.

Adam H
  • 1,523
  • 11
  • 21
  • 2
    This is subtly wrong. "assume-unchanged" is a promise to git you wont change the file, and it shouldn't check. If you do change the file, git will ignore those changes, and overwrite those files in the event of a merge or pull. Use "skip-worktree" if you want git to understand you are making untracked changes, and that it should at least try and preserve your work. http://fallengamer.livejournal.com/93321.html – Dave Feb 13 '15 at 14:40
  • For my purposes, this is the concise and correct answer. – Ed Randall Aug 09 '22 at 07:49
  • A better and **safer**, though by no means perfect solution, is to use **`--skip-worktree`** instead of `--assume-unchanged`. The 'skip-worktree' approach would not lead to possible data loss, but it would prevent you from safe operations such as `git stash`. – Jakub Narębski Aug 10 '22 at 08:14
-3

Untrack the files that you want to ignore:

git rm --cached <file>

Then you can add files and .gitignore will not track ignored files.

Neil
  • 322
  • 1
  • 2
  • 13
  • The OP has stated that they do not want to remove the file. – Tom Fenech Feb 13 '15 at 10:55
  • You don't remove the files, only untrack files. Anyway I misunderstand the question like other 16 people that say the same like me. "Duplicate question: http://stackoverflow.com/questions/1139762/ignore-files-that-have-already-been-committed-to-a-git-repository" – Neil Feb 13 '15 at 12:43
  • Firstly, untracking a file means to delete the file from git. The OP does not want the files deleted from git. Secondly your "duplicate" is a different question and solves a different problem. Do not confuse them. – Dave Feb 13 '15 at 14:31