I know there are thousands of posts about Git basics, tricks and whatever, but I always end up using terminal aliases for common tasks (commit, push, pull, status, checkout) or going to a physical notebook to see less used commands. I have them, but hardly go check my bookmarks (or google). So I decided to move that tricks sheet here in the internets. Nothing new, just for convenience.
Create a branch and checkout in one step
git checkout -b branch_name
Push all local branches to origin
Force upload of branch to remote as master
git push -u origin branc_name:master
Do not ever do that to your team members. I needed it sometimes for my own server before I had this hook to save branches into different folders
Change commit message (before push)
Download a branch from remote
git fetch origin git checkout branch_name
Remove a branch from remote
git push origin --delete branch_name
Create and push tag with long description
git tag tag_name -a #opens editor window to write desc git push --tags
git tag -d tag_name git push origin :refs/tags/tag_name
Create branch from a previous commit
git checkout -b branch_name commit_id
Create branch from unstaged changes
git stash git checkout -b branch_name git stash apply
Pack last n commits into one
This opens editor where you can select commits you want to maintain as separate (p) or squash into (s), and even use a different commit message.
Remove files from last commit (before pushing)
Imagine you use alias to add all files and commit at same time, and you did not want to use all changed files in your last commit. To remove those files you need to:
git reset --soft HEAD~1 git reset HEAD files/you/dont/want/to/commit
Find commit where bug was introduced
This literally saved my ass many times. We first need to know a past commit_id where feature was working. Then:
git bisect start HEAD goodcommit_id
This goes in cycles, detaching commit in half the process between that good commit and present, so we can test if that is good or bad. When a commit is detached we test and let bisect know if that specific commit is good or bad:
This cycles until you find the causing commit. Finally, you reset to go back to HEAD:
Search for a string through past commits
git grep --heading -n "string" $(git rev-list --all)
If you want a list of files having a string in content, that list including past commits and showing line numbers.
See commits that changed a file
git log --follow path/to/file
These include deletion. So, it can be used to see which commit deleted a file, by adding another argument (-1: limits the result to one commit):
git log -1 --follow path/to/file
List commits in branch B not part of branch A
For instance, you want to know which commits belong exclusively to a branch (those commits were not merged into the other branch yet)
Squash all commits in a branch
git reset $(git commit-tree HEAD^{tree} -m "msg")
That actually is cleaner and faster than interactive rebase, not to mention you avoid having to mark individual commits as squash or pick. It basically creates a commit from a detached HEAD and resets to that commit.
Cherry pick several commits
If you have many consecutive commits you can also use this, where A is the first and B is the last commit
checkout all branches after a clone
git branch -a | grep -v HEAD | perl -ne 'chomp($_); s|^\*?\s*||; if (m|(.+)/(.+)| && not $d{$2}) {print qq(git branch --track $2 $1/$2\n)} else {$d{$_}=1}' | csh -xfs