A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Git basics

Have git remember merge conflict resolutions so you never have to do them more than once:
git config --global rerere.enabled 1

Prevent "git push" with no parameters from pushing anything other than your current branch:
git config --global push.default current

Show a graphical summary of the merge tree (looks a bit like gitk).
This gives the answer to "Have I pushed or not"? :
git log --decorate --color --graph  --oneline


Find the point at which you forked (branched):
git merge-base [branch] [trunk or previous branch]


Show all changes made in this branch (if you branched from master):
git log --oneline --name-only --reverse master..HEAD


Ensure only one commit per file; pipe the above through:
| grep -v '^....... ' |sort |uniq -c |sort -nr 
 
Edit all commit messages since a particular commit:
git rebase -i $(git merge-base [branch or HEAD] [trunk or previous branch])


Undo the last commit made locally (e.g. in order to re-do it differently, perhaps in the middle of a rebase): 
git reset HEAD^


To reverse a pushed commit two commits back,
first reverse the second most recent commit, and then commit it back:
git revert -n HEAD~1
git push origin branch
(Do not try to rebase what has been pushed, it will not work. Rebase only changes your local repo)

To revert a merge commit:
git revert SHA -m 1
(Where SHA is the commit ID)

Reset a branch to be same as the repo:
git reset --hard origin/branch_name

Delete a branch:

git branch -D branch_name # delete it locally
git push origin :branch_name # delete it on remote


Use a branch in a different repo for the same project:
git remote add repo_shortname user@server:/repo_name
Use different branch names in each repo.
Push to your repo_shortname instead of origin.

Create a new, tracked branch:
Tracked means that 'git status' will show you how many commits behind the parent branch you are, and if the parent branch has diverged (which means you might want to rebase onto it)
git checkout master # or wherever you want to branch from 
git checkout -t -b my_new_branch

Easily make an alteration to a previous commit:
git commit -m'fixup! same title as another commit' filename
git rebase -i --autosquash [commit id]

(the commit will be put in the correct place and marked as 'fixup' automatically)

A git workflow:
(dca-73 is the name of a branch)
git fetch
git checkout dca-73
git pull origin dca-73
# run tests
# make changes
# run tests
git fetch
git push origin dca-73
git checkout master
git pull origin master
git merge --no-ff dca-73

# run tests

# check it looks right
git log --decorate --graph --oneline

git push origin master




How to merge conflicts without editing the file:

git checkout --ours path/to/filename
git checkout --theirs path/to/filename


Automatically run checks on your code before committing with git hooks:
e.g. Just edit the file .git/hooks/pre-commit in your working directory, and make it executable.
It will not be committed along with your code because it's in the special .git directory.