Git - Temporarily ignore trivial changes to files

GitIgnore

Git Problem Overview


I'm looking for a way to 'hide' minor changes made to a few files in Git, such that they will not show up in git status until a different change is made to those files.

Example: I have a java file where the only change made is the removal of an unused import (a contributor forgot to run an organize imports before committing). Now I have removed that import and the change (obviously) shows up in git. Since I have no other change to make to that file, I don't really like committing the file as part of another (unrelated) change or committing this change stand-alone. Sure, I could revert the change and only applying it whenever I will have to make changes to that file, but I could "risk" forgetting it.

Does a command exists for such a task? It would work somewhat like the assume-unchanged command but in a not permanent way.

What would be the proper way to resolve this if no such command is available?

Thanks in advance.

Git Solutions


Solution 1 - Git

In my use case (developing using an edited config file on my personal machine, running on another machine with the unchanged config), this was the solution for me:

start ignoring changes to a file:

git update-index --assume-unchanged path/to/file

keep tracking again:

git update-index --no-assume-unchanged path/to/file

Solution 2 - Git

The drawback of using git update-index --assume-unchanged is that (as the git manual states), you're promising git that you're not going to change the file.

> When the "assume unchanged" bit is on, the user promises not to change the file and allows Git to assume that the working tree file matches what is recorded in the index.

If you violate this promise and change the file anyway it can have undesirable consequences. E.g. on some implementations, doing a git stash will throw away the changes you made to the file (why shouldn't it if you promised you weren't going to change it?).

Using the --skip-worktree option instead tells git to pretend the working version is up to date with the index version.

> When reading an entry, if it is marked as skip-worktree, then Git pretends its working directory version is up to date and read the index version instead.

This seems to be the more reliable way to ignore changes without the risk that some git commands might throw your changes away:

git update-index --skip-worktree path/to/file

To track the file again:

git update-index --no-skip-worktree path/to/file

To list the files where you've set the skip-worktree:

git ls-files -v | grep ^S

Solution 3 - Git

Keep your changes that are not ready in a separate branch. git rebase this branch atop new changes in the main history as necessary.

Be it development in progress, temporary things, even things that are never to be included in the main project history -- the same process works equally well.

If/when the changes of the branch are ready to be included in the main history; merge it in. If not, keep them in the separate branch and continue rebasing.

(side note: git merge --no-ff may be of use to create a merge-commit even if a fast-forward merge is possible -- depending on the rules of your project, this may be preferable)

Solution 4 - Git

Just don't add the trivial changes.

It's good practice to carefully review the things that you add before committing.

You can even ignore some changes in a file while adding others, using

git add -p.

Solution 5 - Git

I added all the answers here to add some code that made my life a little bit more comfortable. Expects BSD coreutils (like on MacOS).

git-overlook

#!/usr/bin/env bash

path="$1"
root="$(git rev-parse --show-toplevel)"

if [ -z "$path" ]; then
  echo "Specify a path" 1>&2
  exit 1;
fi;

if [ ! -d .git/overlook ]; then
	mkdir $root/.git/overlook
fi;
record="$root/.git/overlook/$(echo $path | sed 's/\./___/g' | sed 's/\//____/g')"
touch "$record"
git update-index --skip-worktree "$path"

git-relook

#!/usr/bin/env bash

path="$1"
root="$(git rev-parse --show-toplevel)"

record="$root/.git/overlook/$(echo $path | sed 's/\./___/g' | sed 's/\//____/g')"
if [ -f "$record" ]; then
  git update-index --no-skip-worktree "$path"
  rm "$record"
fi;

And finally a .git/hooks/pre-commit

#!/bin/bash

set -eu

root="$(git rev-parse --show-toplevel)"

get_record_name() {
  record="$root/.git/overlook/$(echo $1 | sed 's/\./___/g' | sed 's/\//____/g')"
  echo "$record"
}

for file in $(git ls-files -v | grep ^S | sed 's/S //'); do
  record="$(get_record_name $file)"
  record_mtime="$(stat -f %m $record)"
  file_mtime="$(stat -f %m $file)"

  if [ "$record_mtime" -lt "$file_mtime" ]; then
    echo "File $file is overlooked but has been modified since. Please run either git overlook $file or git relook $file" 1>&2
    exit 1
  else
    echo "File $file is overlooked but hasn't been modified"
  fi;

done;

This makes it so that I can run git overlook path/to/file and then I can go about committing on my merry way until I've changed the file that was overlooked, at which point I have to either overlook it again or bring it back in with git relook path/to/file. Obviously it doesn't help me if the overlooked file is the only change I made and then I don't see it in git status.

It makes some files in .git/overlook to keep track of stuff but as far as I know git will peacefully coexist with them.

Solution 6 - Git

There are multiple ways [although may not be clean and neat and would require your attention]

  1. Add the file in concern to .gitignore in your repo so that it doesn't show up for commit. Be careful to remove this from .gitignore when you are ready to commit the file
  2. Ensure you do not 'stage' the file while committing rest of your changes. You may want to write a wrapper over git which will ensure commands like git commit -a or git add . run on all except the file under question. Another alternative would be to use git gui or git citool where you can visually ensure your file isn't in 'staged' area and hence never gets committed
  3. Another way would be to commit all your 'committable' changes and then git stash save your only working file. Later when you are ready to change the file, you can git stash pop and continue working and committing.

Hope that helps :)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZelgadisView Question on Stackoverflow
Solution 1 - GitbenrothView Answer on Stackoverflow
Solution 2 - GitHexAndBugsView Answer on Stackoverflow
Solution 3 - GitjsagerydView Answer on Stackoverflow
Solution 4 - Gitnes1983View Answer on Stackoverflow
Solution 5 - GitRoshanView Answer on Stackoverflow
Solution 6 - GitAnshulView Answer on Stackoverflow