It’s a common case that I want to modify files that have been tracked by Git, but not commit the changes. For example changing the database configurations to run on my local machine.

Another example is that I don’t want to commit OS specific changes on my dotfiles repository; my main workstation is Ubuntu and I use below configuration for my alacritty terminal app:

# alacritty/alacritty.yml

import:
  - ~/.config/alacritty/os/config_linux.yml

Instead of changing it to config_macos every time after I pull changes, I’d like to ignore this file locally even though it’s checked-in by Git.

So I’ve been looking if there is a sane and manageable way to keep these long-lived local changes without seeing them in git status list.

First thing that came to our minds is using project specific local .gitignorefile. However adding a file to .gitignore won’t work, because the file is already tracked. And even if we assume it’s a new file, .gitignore will ignore this file for all of your project members working on the repository/project.

Fortunately Git has already a command that allows you manually ignore local changes to a file or directory:

$ git update-index --skip-worktree $FILENAME

From –skip-worktree doc:

–[no-]skip-worktree

When one of these flags is specified, the object name recorded for the paths are not updated. Instead, these options set and unset the “skip-worktree” bit for the paths. See section “Skip-worktree bit” below for more information.

To track the file again:

$ git update-index --no-skip-worktree $FILENAME

In order to list the skipped files where you’ve set via --skip-worktree flag:

$ git ls-files -v | grep ^S

Also you may like to have them as aliases as I do. You can add them like below:

$ git config --global alias.hidden '!git ls-files -v | grep "^S"'

Or just update your global git configuration file:

# ~/.config/git/config
# ${XDG_CONFIG_HOME}/.config/git/config
# ~/.gitconfig

[alias]
  skip = update-index --skip-worktree
  unskip = update-index --no-skip-worktree
  skipped = !git ls-files -v | grep \"^S\"

All done!