The Living Thing / Notebooks :

Git tricks

My own git reference. See also classic git tips.

See the fastai masterclass for many more handy helpful tips/links/scripts/recommendations.

Handy git commands

Remove a file from versioning without deleting:

git rm --cached blah.tmp

legit has simplified feature branch workflows.

Filters: smudge and clean, .gitattr

Long story.

Subtrees/submodules/subprojects

The simplest way of integrating external projects is as subtrees. Once this is set up you can mostly ignore them.

putting a substree into a project

creatin’:

git fetch remote branch
git subtree add --prefix=subdir remote branch --squash

updatin’:

git fetch remote branch
git subtree pull --prefix=subdir remote branch --squash
git subtree push --prefix=subdir remote branch --squash

Con: Rebasin’ despite ’em is slow and involved.

Splitting off a sub-project

Use subtree split to prise out one chunk. It has a few wrinkles but is fast and easy.

pushd superproject
git subtree split -P project_subdir -b project_branch
popd
mkdir project
pushd project
git init
git pull ../superproject project_branch

Alternatively, to comprehensively rewrite history to exclude everything outside a subdir:

pushd superproject
cd ..
git clone superproject subproject
pushd subproject
git filter-branch \
    --subdirectory-filter project_subdir \
    --prune-empty -- \
    --all

Submodules

Include external projects as separate repositories within you repository is also possible, but I won’t document it here, since it’s so tedious and has so many things that go wrong if you are not disciplined.

not repeating yourself during merges

git rerere automates this

git config --global rerere.enabled true
git config --global rerere.autoupdate true

Importing some files across a branch

git checkout my_branch -- my_file/

Garbage collecting

In brief, this will purge a lot of stuff from a constipated repo in emergencies:

git reflog expire --expire=now --all && git gc --prune=now

In-depth explanation.

Editing history

Cleaning out all big files

bfg does that:

git clone --mirror git://example.com/some-big-repo.git
java -jar bfg.jar --strip-blobs-bigger-than 10M some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push

Deleting specific things

I think bfg also does this. There is also native support:

git filter-branch -f \
    --index-filter
    'git rm -r --cached --ignore-unmatch unwanted_files'

Making it work with a broken-permissioned FS

e.g. you are editing a git repo on NTFS via Linux and things are silly.

git config core.filemode false

Detecting if there are changes to commit

Thomas Nyman:

if output=$(git status --porcelain) && [ -z "$output" ]; then
  # Working directory clean
else
  # Uncommitted changes
fi

Emergency commit

Oh crap I’m leaving the office in a hurry and I just need to get my work into git ASAP for continuing on another computer. I don’t care about sensible commit messages because I am on my own private branch.

I put this little script in a file called gitbang to automate the most common case.

#!/usr/bin/env bash

if output=$(git status --porcelain) && [ -z "$output" ]; then
  echo "nothing to commit"
else
  git add --all && git commit -m bang
fi

git pull && git push

Content-specific diffing/filtering

jupyter diffing and merging is painful. Workaround: nbdime provides diffing and merging for notebooks. It has git integration:

nbdime config-git --enable --global

git-latexdiff, is the same for LaTeX.

You can set up attributes so that these filters are invoked automatically. It’s a surprisingly under-documented thing for some reason.

Decent GUIs

See Git GUIs.

Which repo am I in?

For fish and bash shell, see bash-git-prompt.