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/subdirs

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.

Download a sub-directory from a git tree

This works for github at least. I think anything running git-svn?

[Heinous hack(https://github.com/buckyroberts/Source-Code-from-Tutorials/tree/master/Python)

  1. replace tree/master => trunk
  2. svn co the new url
svn co https://github.com/buckyroberts/Source-Code-from-Tutorials/trunk/Python

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.