Git Recipes

This page contains a whole lot of Git commands that I personally used in the past to keep as a track record for future use.

Navigating history

git log ; git lg
git checkout ca55e77e
git checkout master
git checkout HEAD^3
git checkout "HEAD@{1 month ago}"
git checkout :/Commit message

Branching

git checkout -b develop # creates new branch develop and does checkout of develop
git merge feature/awesomeness # merges the branch "feature/awesomeness" into the current branch
git branch -d feature/bullshit # deletes local branch "feature/bullshit"
git push origin :feature/bullshit # deletes remote branch "feature/bullshit" from the "origin" remote

Stash

Getting a single file from a stash…

git checkout stash@{0} -- «filename»

Stash all files including untracked files…

git stash -u

Save a stash with a specific message…

git stash apply -m "My stash with ABC"

Comitting

Add specific lines of a file to the commit interactively.

git add -p «filenames»

Commit the staged changes.

git commit -m "your commit message"

Bisect

Trace buggy commit with git bisect…

Manual

git bisect reset # only needed after a bisect
git bisect start
git bisect good «revision»

git bisect bad «revision»

# git will checkout the next revision to check
git bisect (good | bad)

Automated

git bisect start
git bisect good «revision»
git bisect bad «revision»
git bisect «run/path/to/decision/script args…»

Filter Branch

Fix committer/author

#!/bin/sh

git filter-branch -f --env-filter'

n=$GIT_AUTHOR_NAME
m=$GIT_AUTHOR_EMAIL

case ${GIT_AUTHOR_NAME} in
     "Marco Franssen") n="Marco Franssen" ; m="[email protected]" ;;
     "Marco Franssen [email protected]") n="Marco Franssen" ; m="[email protected]" ;;
esac

export GIT_AUTHOR_NAME="$n"
export GIT_AUTHOR_EMAIL="$m"
export GIT_COMMITTER_NAME="$n"
export GIT_COMMITTER_EMAIL="$m"
' HEAD

Remove filter-branch backup

git update-ref -d refs/original/refs/heads/master

Move commits to new Repository

These examples assume you are already on the branch you want to cherry-pick these commits into.

git remote add oldrepo https://github.com/path/to/oldrepo
git fetch oldrepo

Take a specific subset of commits

git cherry-pick --strategy recursive --strategy-option theirs «oldestCommitHash»^..«latestCommitHash»

Take all commits involved in a specific merge commit

git cherry-pick --strategy recursive --strategy-option theirs «mergeCommitHash»^..«mergeCommitHash»

Handle deleted files and conflicts

As you are cherry-picking your target branch might not have all files. You might end up in some conflicts that you will have to handle.

git mergetool
# either c/m or d based on if you want to keep or delete the files
git cherry-pick --continue

Git config

.gitconfig
[alias]
  bw = blame -w -M
  c = commit
  commend = commit --amend --no-edit
  cc = commit --all --amend --no-edit
  ca = commit --all
  co = checkout
  cb = "!f() { git co `git log --until=\"$*\" -1 --format=%h`; } ; f"
  s = status --short
  d = diff
  dc = diff --cached --word-diff=color
  dw = diff --word-diff=color
  l = log
  a = add
  addnw = !sh -c 'git diff -U0 -w --no-color --ignore-blank-lines "$@" | git apply --cached --ignore-whitespace --unidiff-zero -'
  af = add -f
  p = push
  dt = difftool
  mt = mergetool
  ss = show -1 --format=%B--stat
  sw = show -1 --format=%B--stat --word-diff=color
  whatis = show -s --pretty='tformat:%h (%s, %ad)' --date=short
  whatadded = log --diff-filter=A
  deleted = log --diff-filter=D --summary
  lg = log --graph --pretty=format:'%Cred%h%Creset %C(yellow)%an%d%Creset %s [%N] %Cgreen(%ar)%Creset' --date=relative
  lgd = log --graph --pretty=format:'%Cred%h%Creset %C(yellow)%an%d%Creset %s [%N] %Cgreen(%ar)%Creset' --date=default
  lgm = log --graph --pretty=format:'%Cred%h%Creset %C(yellow)%an%d%Creset %s [%N] %Cgreen(%ar)%Creset' --date=relative --author=AUTHOR_EMAIL
  abbr = "!sh -c 'git rev-list --all | grep ^$1 | while read commit; do git --no-pager log -n1 --pretty=format:\"%H %ci %an %s%n\" $commit; done' -"
  refeature = "!f() { git co develop && git pull && git co $1 && git pull && git rebase develop; } ; f"
  ffmerge = "!f() { git refeature $1 && git co develop && git merge $1; } ; f"
  clearbranch = "!f() { git branch -d $1 && git push origin :$1; } ; f"
  please = push --force-with-lease
  undo = restore
  unstage = restore --staged
  wip = for-each-ref --sort='authordate:iso8601' --format='%(color:green)%(authordate:relative)%09%(color:reset)%(refname:short)' refs/heads
[color]
  ui = always
[core]
  pager = less -x1,5
  fileMode = true
  editor = vim
  autocrlf = false
[push]
  default = current
[branch]
  autosetuprebase = remote
[merge]
  tool = vimdiff
  guitool = gvimdiff
  conflictstyle = diff3
[mergetool]
  prompt = false
[diff]
  tool = vimdiff
  guitool = gvimdiff
[difftool]
  prompt = false
[commit]
	gpgSign = true
[tag]
	forceSignAnnotated = true

[includeIf "gitdir:~/code/priv/**/*"]
    path = "~/.gitconfig-private"
[init]
	defaultBranch = main