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,144