DEV Community

loading...

How to ignore files already managed with Git locally

Toshiharu Nishina
A web developer for the fifth year.Rails/React/GraphQL.
・2 min read

There are ways to write in .gitignoreor.git / info / exclude not to manage files with Git.
These methods are for files that have not been managed with Git yet.

However, There are times when you want to ignore files that are already managed with Git locally
For example, you want to exclude from Git's management, such as when you modify the application's configuration file for local use.

In this post, I will explain the Git command which can ignore files even if they are already managed by Git.

There are two ways

  • git update-index --skip-worktree
  • git update-index --assume-unchanged

git update-index --skip-worktree

When to use?

--skip-worktree is the flag which means the files should change locally.

That is, Use the command when you want to modify files managed by Git locally (or updated automatically) but you do not want Git to manage that change.

Because the command is to prevent local changes from being managed by Git, we will use the command in most cases.

Exclude from the management of Git

$ git update-index --skip-worktree path/to/file
Enter fullscreen mode Exit fullscreen mode

How to confirm

$ git ls-files -v | grep ^S
Enter fullscreen mode Exit fullscreen mode
  • git ls-files shows all files managed by git.
  • -v check the file being ignored.
  • --skip-worktree is displayed withS.

Restore to the management of Git

$ git update-index --no-skip-worktree path/to/file
Enter fullscreen mode Exit fullscreen mode

git update-index --assume-unchanged

When to use?

--assume-unchanged is the flag which means the files should not change locally.

In other words, it is used when ignore files that you do not need to change locally (or should not change).

--assume-unchanged is used when you want to speed up Git's behavior by ignoring unnecessary files.

Also, since it is an idea to ignore local changes, git reset - hard command will delete local changes.

Exclude from the management of Git

$ git update-index --assume-unchanged path/to/file
Enter fullscreen mode Exit fullscreen mode

How to confirm

git ls-files -v | grep ^h
Enter fullscreen mode Exit fullscreen mode
  • assume-unchanged is displayed withh.

Restore to the management of Git

git update-index --no-assume-unchanged path/to/file
Enter fullscreen mode Exit fullscreen mode

by @nishina555

Discussion (10)

Collapse
alexgomesdev profile image
Alexandre Gomes

--asume-unchanged is the right tool for the wrong job(or the wrong tool for the right job). It doesn't do what you think it does. I was also using it until it was pointed out by colleagues what it really does.

Reading the man for update-index, there is a whole section that goes in detail about what --assume-unchanged really does and when it is actually useful. It is used specifically as an alternative to gitignore for filesystems with slow lstat(2) implementation.

This Git community mailing list post goes into more details as to why this is a bad idea.
tl;dr is it is not reliable and it might still cause your files to be detected as changed.

In other words, it is a specific tool for a specific purpose and should not be used for ignoring files. The right tool for what --assume-unchanged does would be the --skip-worktree flag but I won't give more information on it since it's still the wrong tool for what's trying to be achieved here.
When colleagues at Emplifi explained what --assume-unchanged really is and why it is a bad idea, they provided with two alternatives:

  • Use core.excludeFiles git config flag, which allows you to specify a custom gitignore file. It can be used with a global flag so you don't have to always gitignore the same file across git repositories:

git config --global core.excludesfile ~/.gitignore

  • Using .git/info/exclude in your project. It acts as "your own local gitignore that does not get pushed to remote".

More info on where gitignore files are sourced from can be found in its manpage

Collapse
tomhundt profile image
Tom Hundt • Edited

Looks like in my version of git (2.21.0 on Mac) it lists them with a lowercase 's' (not an uppercase 'S'), so using the '-i' (ignore case) flag with 'grep' makes it compatible:

$ git ls-files -v | grep -i ^S
s Audit/base.py
s etl.ini

$ git --version
git version 2.21.0 (Apple Git-122.2)
Collapse
dh_reyo profile image
Dhouibi Iheb

Thank you It's really helpful

What I've understood so far if I am not wrong, we use --skip-worktree to sort of unstage a file, any local modification made to the file it won't appear when we run git status even when we commit, no changes are saved is that it ?

And what's the difference between --skip-worktree and --assume-unchanged ??

Thank you in advance Sir

Collapse
hrvoj3e profile image
hrvoj3e • Edited

Thanks for this.
Just one note to avoid false negatives: use -E flag in grep (in my case at least).

git ls-files -v | grep -E '^S'
git ls-files -v | grep -E '^h'
Collapse
whalemare profile image
Anton Vlasov • Edited

Short cut for those, who want do this for all files in .gitignore

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git update-index --skip-worktree
Enter fullscreen mode Exit fullscreen mode
Collapse
bsides profile image
Rafael Pereira

This helped me a lot, thanks for the throughness!

Collapse
jamesg1 profile image
James G

Great post thanks!

Collapse
ardunster profile image
Anna R Dunster

Great trick, thanks for sharing!

Collapse
diskcrasher profile image
Mike

Where do these changes actually get saved to?

Collapse
rabibsust profile image
Ahmad Jamaly Rabib

Really helpful! Thanks a lot for sharing!