csswizardry.github.com
csswizardry.github.com copied to clipboard
Got any neat Git tips?
Undo changes to one (or more) file(s) in a commit instead of reverting the entire commit:
git show commit-hash -- path/to/file.html | git apply --reverse
Great article, @csswizardry!
Working copy cleanup
Deleting local branches that have been merged and deleted:
git branch --merged | grep -v \"^\\s*master$\" | grep -v \"\\*\" | xargs -n 1 git branch -d
I aliased it as delete-merged and since I use it daily, also as dm.
I always use this in conjunction with the following (aliased as pru) which deletes all stale remote-tracking branches (assuming your upstream is called origin, which is almost always in my personal case):
git remote prune origin
Context switching
I have several projects for work and several open source projects I work on during my personal time. To deal with this and make sure I use the correct email address + correct signing key, I use the following:
- Set up
user.nameonly (no email) and force git to refuse a commit without an email address set up - Enable GPG signing
- Set up "profiles"
- After cloning a repo, switch to correct profile (here with
git persoorgit cht)
It probably seems convoluted but it has worked well for me in the past. I'm sure they could be (or there is?) a plugin doing that out there, just never looked for it, and this is actually simple enough.
Branch naming convention
I like to have my branches named as astorije/my-branch so it's easy to spot in GitHub's branch list and in the command line. It's a nice convention often met in open source projects, and I even managed to convince my entire team to adopt it 🎉.
But I really don't want to type 8 extra characters when creating a branch, so I set up this alias:
cb = "!f() { git checkout -b astorije/$@; }; f"
Now I just need to type git cb my-branch to create astorije/my-branch 😅.
two of my favorite git aliases are:
List all Submodules
alias gsub="grep path .gitmodules | sed 's/.*= //'"
List Tags in a usefull way
alias gt="git tag -l --sort=v:refname | tail -n8"
Best git tip I saw shared on twitter was the :/ filter for latest match. i.e. git log :/"fix: font" will show latest commit matching the text fix: font.
What am I about to commit?
git config --global alias.staged 'diff --staged'
Then run git staged before committing to double-check what's in the index.
Do not stash what is staged
git stash --keep-index will stash everything that has not been git added yet (when interactively adding stuff to the stage).
Select what must be staged
I have aliased ap to git add -p and have never used git add . since then. Always pick what you are adding to the stage, and never commit something unwanted by inattention.
-p is my favourite flag.
git checkout -p HEAD~ will let you pick and choose which hunks you want to unstage from the present commit in case you didn't mean that -a on your last git commit
git log -p -- path/to/file gives the diffs made to the file inline with the log messages. Good for fuzzy text searches.
git add -p allows you to choose what changes you want to add. Make two commits' worth of changes in one file? This lets you interactively chose which of those should be added at the moment. Check the s (split) and e (edit) flags for if one "chunk" has elements of both.
(( BONUS ROUND: If you haven't used git rebase -i to reorganize and squash local changes, you're missing out ))
-pis my favourite flag.
Yep, me too, and it even works with git stash :D
I have 2 aliases that I use all the time:
- my custom one liner log:
l1 = log --format='%Cgreen %h %C(white) %G? %Cred%ai %C(bold)%<(15)%ar %Creset %C(cyan)%<(30)%ae %C(yellow) %s' - alias to commit work in progress (useful for end of the day, but feature still not complete).
cwip = commit -S -m ':construction: WIP'. Note that it will still open the git commit message editor to fill in the details
I use this to fetch pull request by id to local branch.
git fetch origin pull/<id>/head:<branch-name>
There are lots of git tips on this repo https://github.com/git-tips/tips There is npm package to show git tip each time you open a new terminal. https://github.com/nirajpandkar/git-tip
I recently put together a way to find (with fuzzy search) and list branches interactively. Check it out.

In one repository I need to check in JS/CSS compilation results next to the source files. To get an idea of the changes in those compiled files I use this alias:
wdiff = diff -w --word-diff-regex=. --color-words -U0
It configures git-diff to produce the absolutely most minimal diff possible.
git rebase -i --autosquash --autostash
Really handy in projects that don't do merge commits (read, everything I work with).
git reflog
Lost a commit in a rebase? Did a pull and want to go back to a previous state? git reflog gives you the hash corresponding to the last several values of HEAD so you can examine and checkout the point that you're interested in.
I replaced the placeholders in your blog post with actual commands that attempt to Do The Right Thing when no argument is provided:
[alias]
recap = !git log --all --oneline --no-merges --author=${1-$(git config user.email)}
today = !git log --all --since=00:00:00 --oneline --no-merges --author=${1-$(git config user.email)}
changelog = !git log --oneline --no-merges ${1-$(git describe --abbrev=0)}..HEAD
upstream = !git log --oneline --no-merges HEAD..${1-$(git branch -lvv | perl -ne '/^\\*.*\\[(.*?)\\]/ and print "$1\n"')}
local = !git log --oneline --no-merges ${1-$(git branch -lvv | perl -ne '/^\\*.*\\[(.*?)\\]/ and print "$1\n"')}..HEAD
I really liked your diff tips, but instantly was curious whether you could do the same word diff'ing in git-add's --patch mode. You can! (at least since 2.9).
If you want to see color-words in patch mode, just run:
git -c interactive.diffFilter="git diff --color-words" add -p
I set this up as an alias to my commonly used alias in my bash profile:
alias gap='git -c interactive.diffFilter="git diff --color-words" add -p'
My favorite is: alias.catchup !git fetch; git rebase origin/master.
For catching up those random feature branches you haven't had to touch in months.
My $0.02 tip:
Get and use http://gitup.co/ - excellent graphical tool to do rebases, merges and visualising what you and others been up to.
(Hint: tap Cmd+D to see commits descriptions along with the graphical view)
For things like git recap or git today, you don't have to manually configure your email if you set up the alias to include git config --get user.email, like so:
git log --all --oneline --no-merges --author=`git config --get user.email`
@tbirrell this is git pull --rebase, which you can make the default with git config [--global] pull.rebase true (and more).
The --topo-order flag for git log is critical for helping people not hate merge heavy logs.
You can replace "Check Which Changes You’re About to Pull" and "Review What You’re About to Push" with a single command:
git log ...@{u} --left-right --graph
It's short for git log HEAD...@{upstream} --left-right --graph.
Note: It only works when you have a tracking branch set for the current branch.
This will show you the commits that the current branch has that the configured tracking branch does not have, and the reverse:
< 123456 local commit not on remote
< 654321 another local commit not on remote
> abcdef a commit on the remote not found locally
> 8sadf6 another commit on the remote not found locally
You can flip the ... around if you like seeing the angle brackets face the other way:
git log @{u}... --left-right --graph
I explain it in more detail in this blog post, along with similar little things I like to do in git.
I have my personal "cheat-sheet" of non-trivial, but often enough needed, git magical incantations listed here. Initially purely about git, later I started including other Linux stuff too (like how to exit from a hanged ssh session, etc.).
I use my quicklog alias dozens of times a day, which shows branches, tags, commit lines, and relative dates in wonderfully fervent colors:

% git help quicklog
`git quicklog' is aliased to `log --oneline --decorate -10 --pretty=format:'%C(yellow)%h%C(reset)%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset''
% git help quicklog-long
`git quicklog-long' is aliased to `log --oneline --decorate --pretty=format:'%C(yellow)%h%C(reset)%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset''
% which gl
gl: aliased to git quicklog -n 20
% which gll
gll: aliased to git quicklog-long
% which st
st: aliased to git status
gl is great for answering, "What's been happening in this branch." gll is great for, "What's been happening since the beginning of all time." And since they're just git log commands, combining gll with arguments is always useful, like gll release-1.0..release-1.5 --author=statico.
I use this alias to quickly amend my last commit:
instamend = commit --all --amend --no-edit
Unstage added files:
unstage = reset HEAD --
Delete last commit:
squash = reset --hard HEAD~1
Discard current changes:
nah = reset --hard && git clean -df
Shameful and time-saving aliases:
puhs = push
psuh = push
pshu = push
spuh = push
sphu = push
Have shell alias gup (git update) = git checkout master && git pull && git checkout - && git rebase master, to check conflicts before merging.
I am surprised no one mentioned magit. It takes out the need to have these many heavily customized aliases.
Here's a recording of how I made this commit using magit:
I do this in the recording to stage, commit and push:
s(stage)c c(commit)- (Type the commit message)
P p(push) .. Somehow the network latency takes push for few more seconds than usual to finish.
Sorry about the mouse pointer distraction.. I not use the pointer to show anything.. please ignore that if you can.

https://gist.github.com/chrismccoy/8775224
i have some handy 1 liners here
Learnt quite a few things in this thread, thank y’all! Oh, and thanks for the article @csswizardry! I added a few tips to my list of aliases.
Leaving it here if someone want to pick stuff. :)
[alias]
# The basic aliases
s = status
cm = commit -m
cp = cherry-pick
# Branch related aliases
br = branch
co = checkout
com = checkout master
cod = checkout develop
# Syncing related aliases
pur = pull --rebase
prune = fetch --prune
# Rebase related aliases
ri = rebase -i
rb = "!sh -c \"git rebase -i HEAD~$1\" -"
rc = rebase --continue
ra = rebase --abort
rs = rebase --skip
rod = rebase origin/develop
rom = rebase origin/master
# Stash related aliases
poop = stash pop
# Push related aliases
pom = push origin master
pod = push origin develop
force = push --force-with-lease
# Mistake related aliases
abort = checkout -- .
wait = reset HEAD
undo = reset --soft HEAD^
amend = commit --amend --no-edit
# Diff related aliases
changes = diff --name-status
dic = diff --cached
diffstat = diff --stat
lg = log --pretty=oneline --abbrev-commit --graph --decorate
count = "!f() { git rev-list --count HEAD ^${1-develop}; }; f"
# Log related aliases
lg = log --pretty=oneline --abbrev-commit --graph --decorate
overview = log --all --oneline --no-merges
changelog = "!sh -c \"git log --oneline --no-merges $1..HEAD\" -"
I have a million shortcut aliases, but some of my favourites are:
[alias]
track = "!f() { git branch --set-upstream-to=origin/$1 $1; }; f"
# git track branch-name (to track with origin)
del = branch -D
# git del branch-name (to delete locally)
undo = reset --soft HEAD~1
# git undo (to undo the last commit and leave the files there)
stan = "!f() { git stash apply stash@{$1}; }; f"
# git stan 3 (to apply the 3rd item in the stash)
and of course:
[help]
autocorrect = 1
# to fix typos
Congratulations if you scrolled down this far :sparkles:
Working with open source in a Linux distribution context, I often want to know if a certain commit made it into a release. I only recently learned how to do that: use the --contains option to git branch or git tag:
~/p/mediawiki-core.git (master) $ git tag --contains d4385537bcd8284936cbcafcc84718dcc9b52181
1.29.0-rc.0
~/p/mediawiki-core.git (master) $ git branch --contains d4385537bcd8284936cbcafcc84718dcc9b52181
* master
...ok, it seems I have to wait :-(
I just like to have an up to date git --log in a CLI window...
Created a bash alias with this command:
while true; do clear; git log --oneline --graph --all --decorate -n20; sleep .5; done
basically, it shows the 20 last lines of git log (decorated) and refreshes this every .5 seconds
@dgoosens Does it really need to refresh every half a second? :wink:
@albocc depends how fast you commit... lol
All my tweaks: https://github.com/pjg/dotfiles/blob/master/.gitconfig
One of the best Tips I have is the autocomplete option https://git-scm.com/book/en/v1/Git-Basics-Tips-and-Tricks#Auto-Completion. You can autocomplete branch names and git commands.
Also some alias as:
co = checkout checkout
undo = reset --soft HEAD^ undo last commit
squash = rebase -i HEAD~ squash
Also I have activated the simple push so every time I make a push only my actual branch is push.
[push] default = simple
Previous branch is @{-1}. You can use it in some nice aliases.
Checkout branch I was on previously:
gprev='git checkout @{-1}'
and merge previous:
gmergeprev='git merge @{-1}'
@thelitek you can do git checkout - to toggle between your most recent branches :)
git add --patch is probably my favourite, it's tidied my commits up no end. With the array of options for applying to each hunk as it comes up you can really pull apart some work you did into meaningful, atomic commits.
To see updates:
alias gitup='git fetch origin ; git branch -v -a'
Some simple non-git ones, but in the long run (and while adding those aliases you like from above) these two might be helpful:
alias vibr='vi ~/.bash_profile'
alias br='source ~/.bash_profile ; echo --- reloaded'
I use this git/bash command to list the files that have been modified between two commits:
git log --name-only --pretty=oneline --full-index %%COMMIT-N%%..%%COMMIT%% | grep -vE '^[0-9a-f]{40} ' | sort | uniq
This comes in pretty handy, for instance, when you need to update a remote server via FTP.
Lately wrote a little script to make its usage even easier...
You can check it out here:
https://gitlab.com/snippets/1689817
I don't have my own command to share, but I would like to put in a request for anchor links at each h2 on your article so I can link back to / bookmark specific commands
My dotfiles: https://github.com/cmbuckley/dotfiles/blob/master/files/gitconfig
Favourites:
du = diff @{u} HEAD— diff with upstream branchsd = !sh -c 'git stash drop stash@{${1-0}}' -— drop stash (default latest,git sd 1to drop explicit stash)sp = !sh -c 'git stash pop stash@{${1-0}}' -— pop stash (same as above)ss = !sh -c 'git stash show stash@{${1-0}} -p --no-prefix' -— show stash patch (same as above)
All of my complex user-interface stuff (graphs, interactive blame etc) is done with tig.
This gives a nice treemap view of the commits on a repo:
git log --graph --decorate --pretty=oneline --abbrev-commit --all