The letter A styled as Alchemists logo. lchemists
Published January 15, 2020 Updated February 16, 2020

Git Attributes Binaries

Demonstrates using Git to provide rich attribute metadata for binary files.

Transcript

# Hello and welcome to the Alchemists Screencasts!
# Today, we'll leverage the power of Git attributes for managing binary files.
# A practical example is best so here's a Git repository with an icon:

tree

# The icon.png is a binary file, which Git does not handle well.
# In fact, consider storing binaries *outside* your Git repository.
# The reason is binaries can't be diffed and cause repository bloat over time.
# Warning aside, let's say you have a repository with binaries.
# What happens when you want to compare or view these file?
# To start, we'll use GraphicsMagick (http://www.graphicsmagick.org) via Homebrew:

brew install graphicsmagick

# Now we can use GraphicsMagick to resize our icon to 10x10 pixel resolution:

gm convert -resize "10x10" icon.png icon.png
git diff

# I don't know about you, but that's not terribly helpful. 😅
# Let's install the ExifTool (https://exiftool.org) to enhance Git:

brew install exiftool

# Next we'll teach Git to use ExifTool via the attributes file.

printf "%s\n" "*.png diff=exif" > .git/info/attributes

# With that change in place, let's see what Git diff says:

git diff

# Notice, amongst other metadata, the image width, height, and size changes.
# We can see the image was correctly resized from 57x57 to 10x10 pixels.
# With Git attributes in place, Git show is enhanced as well:

git show icon.png

# Definitely an improvement over the one line output from earlier. 🎉
# The opposite is possible as well.
# First, let's throw away our changes:

git reset --hard HEAD

# Let's say you have a file you want Git to interpret as binary:

printf "%s\n" "<data>" > tutorial.data
git add tutorial.data
git commit --message "Added tutorial data"
printf "%s\n" "<updated data>" > tutorial.data
git diff

# Now we can treat this file as binary.

printf "%s\n" "*.data binary" >> .git/info/attributes
git diff

# Again, be cautious with this approach as binary files lead to repository bloat.
# While we've only been using Git attributes for the local project:

cat .git/info/attributes

# Changes like this are best applied globally.
# Here's my global configuration (Git adheres to the XDG Directory Specification):

cat ~/.config/git/attributes

# In addition to ExifTool capabilities, I've tought Git about Ruby too.
# Notice the use of `diff=ruby` for the various, non-obvious, Ruby files.
# This allows me to compare differences in Ruby syntax.
# You can also use:

touch .gitattributes
# (alternative to `.git/info/attributes`, though the global form is recommended)
# Lastly, you can use custom attributes should the default not be desired:

git config --add core.attributesFile path/to/custom/file

# For more on attributes, see: https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes
#
# Enjoy!
# https://alchemists.io
# ☿ 🜔 🜍 🜂 🜃 🜁 🜄