You know how sometimes when you need to change a flag in a versioned config file, it is just so hard to remember not to do git add ., commit, accidentally push the change and break everyone else's toys?

Turns out the authors of Git are a forgetful (and smart) bunch too. Which is why there's git update-index and why it has the super-handy --skip-worktree flag. What it does is that it that tells Git "hey, Git, let's pretend I didn't do any changes to this file and also don't track any of its further changes either, OK?" Kind of like a transient .gitignore. You can run it on your config file and stop worrying about accidentally commiting changes that should stay local.

Now, one can immediately see how this can be pretty useful, right? Two obvious questions pop up though:

  1. How do I turn this thing off?
  2. I forgot what I told Git to forget; how do I tell which files are skipped?

Luckily for us, both have easy enough answers:

  1. git update-index --no-skip-worktree <file> will make all the untracked changes appear in Git as modifications again;
  2. git ls-files -v | grep '^S' will tell you all the files that have been marked as skipped.

Differences with update index --assume-unchanged

To make things complicated, there are actually two flags to update-index whose task is to prevent Git from tracking changes to a file: --skip-worktree and --assume-unchanged. And people usually seem to know about --assume-unchanged only. What's the difference?

Well, turns out --assume-unchanged has been designed with a different usecase in mind: as a performance optimisation for files that are expensive to calculate diff of (think SDKs). On the other hand --skip-worktree goes the extra mile to prevent you from losing your changes such as when you do a git reset --hard (which can obviously save you from potentially a lot of trouble). You can find a great comparison here.

Happy gitting! I'm @tomas_brambora.