Legends of the Hidden Git Features

Teagan Glenn

Teagan42

Senior Automation Consultant

Turnberry Solutions

Comcast

Trouble remembering Git CLI commands?

Introducing Git-Completion

Tab completion for:

  • Commands (with descriptions)
  • List out sub-commands (with descriptions)
  • Auto-complete of arguments
  • Branch names (local and remote)
  • Tag names (local and remote)
  • Git-send-email addresses
  • Tree paths within 'ref:path/to/file'
  • File paths within current working directory and index

 zsh | bash | sh

Return from vacation and your app is on fire?

Never Fear: Git Bisect is here

  • Check out a known working commit and run:
git bisect start; git bisect good
  • Check out a known bad commit and run:
git bisect bad
  • Git will automatically check out a commit near the middle of the two
    • If that commit turns out to be bad, run:
git bisect bad
  • If that commit turns out to be good, run:
git bisect good
  • Repeat until you are provided the commit that broke your code!

Re - Re - Re

(It's really not that scary)

Not from a Horror Movie

Git rerere stands for “reuse recorded resolution”. The idea is that git remembers how you chose to resolve hunk conflicts and applies them again in the future instead of having you resolve them again manually. This is particularly handy for long lived “feature” branches away from the “master” branch. With rerere enabled you can periodically perform a merge, resolve the conflicts then back out of the merge. Git will remember how you resolved the conflicts along the way. When it’s time to merge (where you would normally have to go through many conflicts) git will apply all the fixes you applied in the past manually greatly simplifying the merge process.

Enabling Git rerere

# To enable rerere globally:
git config --global rerere.enabled true

# To enable rerere locally:
git config rerere.enabled true
# show pre-merge recorded state
git rerere status
 
# will show the current state of the resolution
git rerere diff
 
# Fix the conflicts and add and commit the conflicted file
git add conflicted_file
git commit
 
# Reset the changes as rerere has saved them
git reset --hard HEAD^

Example Flow

 

Rrrrr... Matey

A Hook for Any Occasion

pre-commit

prepare-commit-msg

commit-msg

post-commit

pre-rebase

post-checkout

post-merge

pre-push

pre-receive

post-update

push-to-checkout

pre-auto-gc

post-rewrite

rebase

sendemail-validate

post-index-change

update

post-receive

prepare-commit-msg

#!/bin/bash
# Include any branches for which you wish to disable this script
if [ -z "$BRANCHES_TO_SKIP" ]; then
  BRANCHES_TO_SKIP=(master develop staging test)
fi
# Get the current branch name and check if it is excluded
BRANCH_NAME=$(git symbolic-ref --short HEAD)
BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP[@]}" | grep -c "^$BRANCH_NAME$")

# Trim it down to get the parts we're interested in
TRIMMED=$(echo $BRANCH_NAME | sed -e 's:^\([^-]*-[^-]*\)-.*:\1:' -e \
    'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/')
    
# If it isn't excluded, preprend the trimmed branch identifier to the given message
if [ -n "$BRANCH_NAME" ] &&  ! [[ $BRANCH_EXCLUDED -eq 1 ]]; then
  sed -i.bak -e "1s/^/$TRIMMED /" $1
fi

Did you know Jira watches GitHub for references to the story?

If you add your story to your commit, all of your work will be reflected inside the story!

Here is  an example of  adding your branch to the commit message

pre-commit

#!/bin/bash

cd $GIT_DIR
source venv/bin/activate

# Verify linting
pylint --rcfile=.pylintrc ./**/*.py

if [ $? -ne 0 ]; then
	return 1
fi

# Run tests
py.test ./**/.py

return $?

Never commit failing code by forcing your  linting and testing to run before being allowed to  commit!

Up Next: Git Flow

The most underrated Git features

By Teagan Glenn

The most underrated Git features

Git command you should be ashamed not to know!

  • 1,003