Terrible Ideas in Git


This article was derived from a talk that GitHub Universe faithfully rejects every year. I can't understand why....

For better or worse, git has become one of the Open Source community's more ubiquitous tools. It lets you manage code effectively. It helps engineers who are far apart collaborate with each other. At its heart, it's very simple, which is why the diagram in so many blog posts inevitably looks something like the one shown in Figure 1.

Figure 1. Git Model (Source: https://nvie.com)

The unfortunate truth that's rarely discussed in detail is that git has a dark side: it makes us feel dumb. I don't care who you are—we all hit a point wherein we shrug, give up and go scrambling for Stack Overflow (motto: "This thread has been closed as Off Topic") to figure out how best to get out of the terrible situations we've caused for ourselves. The only question is how far down the rabbit hole you can get before the madness overtakes you, and you begin raising goats for a living instead.

At its core, all git does is track changes to files and folders. git commit effectively takes a snapshot of the filesystem (as represented by the items added to the staging area) at a given point in time:

cquinn@1d732dc08938 ~/demo1 % git init
Initialized empty Git repository in /home/cquinn/demo1/.git/
cquinn@1d732dc08938(master|...) ~/demo1 % git add ubuntu.iso
cquinn@1d732dc08938(master|·1) ~/demo1 % git commit
 ↪-m "Initial commit"
[master (root-commit) b0d3bfb] Initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 ubuntu.iso
cquinn@1d732dc08938(master|✓) ~/demo1 % git rm --cached
rm 'ubuntu.iso'
cquinn@1d732dc08938(master|·1✓) ~/demo1 % git
 ↪commit -m "There I fixed it"
[master 2d86934] There I fixed it
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 ubuntu.iso
cquinn@1d732dc08938(master|...) ~/demo1 % du -hs .git
174M    .git

So if you do something foolish, such as committing large binaries, you can't just revert the commit—it's still going to live in your git repository. If you've pushed that thing elsewhere, you get to rewrite history forcibly, either with git-filter-branch or the bfg. Either way, it's extra work that's unpleasant to others who share your repository.

Fundamentally, all that git does is create a .git folder in the top level of the repository. This subdirectory contains files and folders that change over time. Wait, isn't there a tool for that?