Suppressing Irrelevant Git Diff Output for Specific Files (e.g., binary files, encrypted files…)

Sometimes, it is useful to suppress certain files from git diff output, especially when the files are large, machine-generated, or not intended for human reading. Typical examples include encrypted files such as *.gpg and *.asc, as well as binary assets like images, audio files, and similar media. These files are usually represented as opaque binary data in diffs, providing no useful information and adding extraneous clutter to git diff output.

Git offers a solution for this through adding YOUR-FILE-PATTERN -diff -text to the .gitattributes file.

Solution: A .gitattributes file that is local to the repository

The .gitattributes file can be defined locally within each individual repository.

For example, to prevent git diff from displaying diffs for files with the .asc and .gpg extensions, include the following lines in the .gitattributes file at the root of your Git repository:

*.asc -diff -text
*.gpg -diff -textCode language: plaintext (plaintext)

Using -diff -text in .gitattributes is beneficial for binary or non-human-readable files because it ensures Git neither attempts to generate textual diffs (-diff) nor applies any text-related processing like end-of-line normalization (-text).

This combination prevents irrelevant or misleading changes from appearing in diffs, avoids potential corruption from automatic text conversions, and keeps version control output clean and focused on meaningful, human-readable changes.

Alternative solution: A global .gitattributes_global file

Rather than adding these rules to every repository individually, you can define them once in a global ~/.gitattributes_global file. This file applies to all Git repositories for your user account unless overridden by a repository-specific .gitattributes.

To set up a global .gitattributes_global file:

Configure Git to use it:

    git config --global core.attributesfile ~/.gitattributes_globalCode language: plaintext (plaintext)

    Add global rules to the ~/.gitattributes_global file. For example:

      *.asc -diff -text -diff
      *.gpg -diff -text -diffCode language: plaintext (plaintext)

      This setup ensures consistent handling of non-human-readable files across all repositories without the need for redundant configuration.

      Conclusion

      Suppressing diffs for non-human-readable files with .gitattributes, whether configured locally or globally, reduces noise in version control workflows. This keeps Git diff output focused on meaningful textual modifications, prevents clutter from binary content, and safeguards against unwanted transformations.

      Related links

      Enhancing Git configuration ~/.gitconfig for performance, efficiency, data integrity, and workflow automation

      Optimizing your Git configuration is fundamental to enhancing efficiency and productivity in version control workflows. A finely-tuned Git setup not only accelerates operations but also aligns the tool with the specific requirements of both individual developers and teams.

      In this article, we will explore Git configurations that enhance both performance and usability.

      All the configurations mentioned in this article should be added to the ~/.gitconfig file. This file follows the INI format, with [sections] defining categories and variables=values specifying settings.

      Performance tuning

      [pack]
      threads = 0
      windowMemory = 5g
      packSizeLimit = 2g
      Code language: plaintext (plaintext)
      • threads = 0 Configures Git to auto-detect the number of CPUs and set the number of threads accordingly.
      • windowMemory = 5g This enhances Git’s efficiency for large repositories. It tells Git to use up to 5GB of RAM when creating packfiles. (A packfile is a way Git stores changes between versions of files efficiently.) By allocating more memory, Git can compare and store these changes more effectively, which can make the packing process faster.
      • packSizeLimit = 2g The packSizeLimit configuration in Git determines the maximum size of a packfile that Git will generate.

      Garbage collection

      [gc]
      auto = 8000
      
      • auto = 8000 Automatically triggers garbage collection when the number of loose objects exceeds 8000, optimizing repository storage and performance. The default value is 6700.

      Core configurations

      [core]
      whitespace = space-before-tab,trailing-space
      preloadindex = true
      Code language: plaintext (plaintext)
      • whitespace = space-before-tab,trailing-space Configures whitespace handling.
      • preloadindex = true Preloads the index into memory for improved performance when running Git commands like status and diff. Setting this to true will make Git load the index into memory early in the execution of commands. This can lead to performance improvements for operations that involve the index, especially in repositories with a large number of files..

      Rebase

      [rebase]
      autoStash = true
      missingCommitsCheck = warnCode language: plaintext (plaintext)
      • autoStash = true Before executing a rebase, automatically stash all uncommitted change. This ensures the rebase proceeds without interference from local modifications. Once the rebase completes, the stashed changes are reapplied, restoring the developer’s original working state.
      • missingCommitsCheck = warn If commits are removed or missing during a rebase, issue a warning rather than # silently ignoring them.

      Merge

      [merge]
      autoStash = true
      ff = only
      conflictStyle = zdiff3
      summary = true
      diffstat = true
      log = 60Code language: plaintext (plaintext)
      • autoStash = true Before executing a merge, automatically stash all uncommitted changes in the working directory and index. This ensures the merge proceeds without interference from local modifications. Once the merge completes, the stashed changes are reapplied, restoring the developer’s original working state.
      • ff = only This setting enforce fast-forward merges for merge, preventing unnecessary merge commits and maintaining a linear commit history.
      • conflictStyle = zdiff3 Uses the zdiff3 conflict style for merges, which includes additional context by showing the base, local, and remote versions of conflicting changes in a more readable format, making it easier to resolve complex conflicts.
      • summary = true Display a brief summary describing what was merged. This includes information such as the merged branch names and the number of commits.
      • diffstat = true Display a diffstat after the merge completes, which summarizes the changes made, showing how many lines were added and removed in each file.
      • log = 60 Include up to 60 commit messages from the merged branch in the merge commit message. This provides historical context and helps reviewers understand the scope of the merge.

      Pull

      [pull]
      ff = only
      default = currentCode language: plaintext (plaintext)
      • ff = only This setting enforce fast-forward merges for pull, preventing unnecessary merge commits and maintaining a linear commit history.
      • default = current This setting automatically pulls the current branch, which helps prevent “There is no tracking information for the current branch. Please specify which branch you want to merge with. See git-pull(1) for details. git pull “

      Push behavior

      [push]
      default = current
      autoSetupRemote = true
      followTags = true
      Code language: plaintext (plaintext)
      • default = current This setting automatically pushes the current branch, which helps prevent the error: “fatal: The current branch BRANCH has no upstream branch.” When this setting is in place, Git will push the current branch to the remote, assuming the branch has an upstream set.
      • autoSetupRemote = true This setting automatically sets up remote tracking for new branches, eliminating the need to manually run git branch --set-upstream-to after creating a new branch. It automates the process of linking local branches to their corresponding remote branches. This is useful for users who frequently create new branches, as it reduces the need for repetitive configuration.
      • followTags = true Push all annotated tags to the remote repository along with the branch # updates. This ensures that tags created locally are also synchronized with the # remote repository during a push operation.

      Enhanced diffing

      [diff]
      tool = vimdiff
      algorithm = histogramCode language: plaintext (plaintext)
      • tool = vimdiff This setting uses vimdiff as the default diff tool when git difftool is executed.
      • algorithm = histogram Diff algorithm for improved diff accuracy, especially in detecting moved code blocks.

      Rerere (Reuse Recorded Resolution)

      [rerere]
      enabled = 1
      autoUpdate = trueCode language: plaintext (plaintext)
      • enabled = 1 Enables automatic resolution of previously encountered merge conflicts, reducing the effort required for repeated merges.
      • autoUpdate = true After a conflict is resolved manually, Git will automatically store the resolution in the rerere cache, making it available for future use.

      Commit

      [commit]
      verbose = trueCode language: plaintext (plaintext)
      • verbose = true This includes the full commit diff in the text editor when composing the commit message, aiding in recalling the context and purpose of the changes.

      Git log dates

      [log]
      date = isoCode language: plaintext (plaintext)
      • date = iso Display dates as YYYY-MM-DD HH:MM:DD (e.g., 2025-03-25 14:59:12 -0400)

      Data integrity (Fsck objects)

      [transfer]
      fsckObjects = true
      
      [receive]
      fsckObjects = true
      
      [fetch]
      fsckObjects = true
      prune = true
      pruneTags = trueCode language: plaintext (plaintext)
      • [transfer|receive|fetch] fsckObjects = true Verifies the integrity of all objects during data transfer operations like clone, fetch, and receive (data transfer), helping detect corruption or tampering early.
      • [fetch] prune = true Automatically remove remote-tracking branches that no longer exist on the remote repository during a ‘git fetch’. This helps keep the local repository clean by removing outdated references to remote branches that have been # deleted.
      • [fetch] pruneTags = true Automatically delete remote tags in your local repository that have been removed from the remote repository during a ‘git fetch’. This ensures that your local tags list is up-to-date and prevents the accumulation of tags that no longer exist on the remote.

      Sort branches and tags

      [branch]
      sort = -committerdate
      
      [tag]
      sort = taggerdateCode language: plaintext (plaintext)
      • sort = -committerdate Configures git branch to sort branches by most recently used rather than alphabetically, making it easier to locate active branches.
      • sort = taggerdate Sort tags by the date they were created.

      Help

      [help]
      autoCorrect = promptCode language: plaintext (plaintext)
      • autoCorrect = prompt When a mistyped Git command closely resembles a valid one, this setting prompts the user with a suggestion before executing the corrected command.

      Aliases

      Here are aliases that abbreviate common Git commands:

      [alias]
      # Pull with rebase and automatically stash local changes before the operation
      up = pull --rebase --autostash
      
      # Show details of the most recent commit or a specified object
      s = show
      
      # Commit all tracked changes
      cia = commit -a
      
      # Continue a rebase after resolving conflicts
      rc = rebase --continue
      
      # Amend the most recent commit with staged changes
      amend = commit --amend
      
      # Amend the most recent commit without changing the commit message
      commend = commit --amend --no-edit
      
      # Push commits to the remote repository
      p = push
      
      # Force push to the remote repository, overwriting history
      pf = push --force
      
      # Stage a specific file or files for commit
      a = add
      
      # Stage all changes (including deletions) in the working directory
      aa = add -A
      
      # Show a short summary of the working directory status
      st = status -s
      
      # Switch branches or restore working tree files
      co = checkout
      
      # List, create, or delete branches
      b = branch
      
      # Discard all local changes and reset to the latest commit on the current branch
      rh = reset --hard HEAD
      
      # Fetch and integrate changes from the remote repository
      pl = pull
      
      # Show changes in the working directory relative to the last commit
      d = diff HEAD
      
      # Show staged changes that will be included in the next commit
      dc = diff --cached
      
      # Launch the configured diff tool to view changes
      dt = difftool
      
      # Show word-by-word diff of the working directory against the last commit
      dw = diff --color-words HEAD
      
      # Show word-by-word details of the most recent commit
      sw = show --color-words
      
      # Display the commit history
      l = log
      
      # Show commit history with GPG signature verification and file change summary
      logs = log --show-signature --stat
      
      # Show full commit history with diffs
      lp = log -p
      
      # Apply changes introduced by existing commits
      chp = cherry-pick
      
      # Abort an in-progress cherry-pick operation
      chpa = cherry-pick --abort
      
      # Continue an in-progress cherry-pick after resolving conflicts
      chpc = cherry-pick --continue
      
      # Quit an in-progress cherry-pick without committing
      chpq = cherry-pick --quit
      
      # Skip the current commit during an in-progress cherry-pick
      chps = cherry-pick --skipCode language: Bash (bash)

      Conclusion

      This Git configuration enhances usability, improves performance, and simplifies repository management through thoughtful settings and powerful aliases. The author’s .gitconfig file is available in the jc-dotfiles repository.

      A Git Tool that can decide whether to use ‘git mv’ or ‘mv’ to move files and/or directories

      The git-smartmv command-line tool, written by James Cherti, allows moving files and/or directories without having to worry about manually choosing whether to use mv or git mv.

      • If the file or directory is being moved within the same Git repository, git-smartmv uses git mv.
      • If the file or directory is being moved between a Git repository and a non-Git directory or a different Git repository, git-smartmv uses mv.

      Installation

      sudo pip install git-smartmvCode language: plaintext (plaintext)

      Shell alias

      To simplify the usage of this tool, you can add the following line to your ~/.bashrc:

      alias mv="git-smartmv"Code language: plaintext (plaintext)

      Usage

      The git-smartmv command-line tool accepts similar arguments as the mv command, including the source file or directory to be moved, and the destination file or directory.

      Example:

      git smartmv file1 file2 directory/

      Second example (rename):

      git smartmv file1 file2

      Links related to git-smartmv